Android 为多个活动存储 Socket.io 对象

2024-05-01

我正在制作我的第一个基于 Socket.io 的 Android 应用程序。套接字从 Web 服务发送和接收数据。应用程序中有许多屏幕用于不同的功能。我如何在这些不同的活动中使用相同的套接字连接。

我尝试在 Application 类中设置和存储 Socket 对象,它似乎工作得很好,但是当应用程序进入后台并在那里停留一段时间时,应用程序被终止,然后套接字对象为 NULL,导致 aoo 崩溃空指针异常。

public class MyApplication extends Application {

    private Socket mSocket;

    private final String TAG = "Application Class";

    public Socket getSocket() {
        return mSocket;
    }

    public Socket createSocket() {

    try {
        Manager manager = new Manager(new URI("http://0.0.0.0"));
    } catch (URISyntaxException URIse) {
        URIse.printStackTrace();
    }

        return mSocket;
    }

}

在活动中访问套接字

MyApplication app;
app = (MyApplication ) getApplication();
app.getSocket;

您可以为套接字创建一个单例管理器类。它将允许您保持整个应用程序可访问的单个套接字连接。请参阅以下代码并根据您的要求进行更改

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;

import com.myapp.app.ui.adapter.OnSocketConnectionListener;

import java.util.ArrayList;
import java.util.List;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

/**
 * Created by penguin on 6/30/2016.
 * <p/>
 * SocketManager manages socket and internet connection.
 * It also provide listeners for connection status
 */
public class SocketManager {

    /**
     * The constant STATE_CONNECTING.
     */
    public static final int STATE_CONNECTING = 1;
    /**
     * The constant STATE_CONNECTED.
     */
    public static final int STATE_CONNECTED = 2;
    /**
     * The constant STATE_DISCONNECTED.
     */
    public static final int STATE_DISCONNECTED = 3;

    /**
     * The constant CONNECTING.
     */
    public static final String CONNECTING = "Connecting";
    /**
     * The constant CONNECTED.
     */
    public static final String CONNECTED = "Connected";
    /**
     * The constant DISCONNECTED.
     */
    public static final String DISCONNECTED = "Disconnected";

    private static SocketManager instance;

    private SocketManager() {
    }

    /**
     * Gets instance.
     *
     * @return the instance
     */
    public synchronized static SocketManager getInstance() {
        if (instance == null) {
            instance = new SocketManager();
        }
        return instance;
    }

    /**
     * The constant TAG.
     */
    public static final String TAG = SocketManager.class.getSimpleName();
    private Socket socket;
    private List<OnSocketConnectionListener> onSocketConnectionListenerList;

    /**
     * Connect socket.
     *
     * @param token  the token
     * @param userId the user id
     * @param host   the host
     * @param port   the port
     */
    public void connectSocket(String token,String userId, String host, String port) {
        try {
            if(socket==null){
                String serverAddress = host+":"+port;
                IO.Options opts = new IO.Options();
                opts.forceNew = true;
                opts.reconnection = true;
                opts.reconnectionAttempts=5;
                opts.secure = true;
                opts.query = "token=" + token + "&" + "user_id=" + userId;
                socket = IO.socket(serverAddress, opts);

                socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        fireSocketStatus(SocketManager.STATE_CONNECTED);
                        Log.i(TAG, "socket connected");
                    }
                }).on(Socket.EVENT_RECONNECTING, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.e(TAG, "Socket reconnecting");
                        fireSocketStatus(SocketManager.STATE_CONNECTING);
                    }
                }).on(Socket.EVENT_RECONNECT_FAILED, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.e(TAG, "Socket reconnection failed");
//                        fireSocketStatusIntent(SocketManager.STATE_DISCONNECTED);
                    }
                }).on(Socket.EVENT_RECONNECT_ERROR, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.e(TAG, "Socket reconnection error");
//                        fireSocketStatus(SocketManager.STATE_DISCONNECTED);
                    }
                }).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.e(TAG, "Socket connect error");
                        fireSocketStatus(SocketManager.STATE_DISCONNECTED);
                        socket.disconnect();
                    }
                }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.e(TAG, "Socket disconnect event");
                        fireSocketStatus(SocketManager.STATE_DISCONNECTED);
                    }
                }).on(Socket.EVENT_ERROR, new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        try {
                            final String error = (String) args[0];
                            Log.e(TAG + " error EVENT_ERROR ", error);
                            if (error.contains("Unauthorized") && !socket.connected()) {
                                if (onSocketConnectionListenerList != null) {
                                    for (final OnSocketConnectionListener listener : onSocketConnectionListenerList) {
                                        new Handler(Looper.getMainLooper())
                                                .post(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        listener.onSocketEventFailed();
                                                    }
                                                });
                                    }
                                }
                            }
                        } catch (Exception e) {
                            Log.e(TAG, e.getMessage() != null ? e.getMessage() : "");
                        }
                    }
                }).on("Error", new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Log.d(TAG, " Error");
                    }
                });
                socket.connect();
            }else if(!socket.connected()){
                socket.connect();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private int lastState = -1;

    /**
     * Fire socket status intent.
     *
     * @param socketState the socket state
     */
    public synchronized void fireSocketStatus(final int socketState) {
        if(onSocketConnectionListenerList !=null && lastState!=socketState){
            lastState = socketState;
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    for(OnSocketConnectionListener listener: onSocketConnectionListenerList){
                        listener.onSocketConnectionStateChange(socketState);
                    }
                }
            });
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    lastState=-1;
                }
            },1000);
        }
    }

    /**
     * Fire internet status intent.
     *
     * @param socketState the socket state
     */
    public synchronized void fireInternetStatusIntent(final int socketState) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                if(onSocketConnectionListenerList !=null){
                    for(OnSocketConnectionListener listener: onSocketConnectionListenerList){
                        listener.onInternetConnectionStateChange(socketState);
                    }
                }
            }
        });
    }

    /**
     * Gets socket.
     *
     * @return the socket
     */
    public Socket getSocket() {
        return socket;
    }

    /**
     * Sets socket.
     *
     * @param socket the socket
     */
    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    /**
     * Destroy.
     */
    public void destroy(){
        if (socket != null) {
            socket.off();
            socket.disconnect();
            socket.close();
            socket=null;
        }
    }

    /**
     * Sets socket connection listener.
     *
     * @param onSocketConnectionListenerListener the on socket connection listener listener
     */
    public void setSocketConnectionListener(OnSocketConnectionListener onSocketConnectionListenerListener) {
        if(onSocketConnectionListenerList ==null){
            onSocketConnectionListenerList = new ArrayList<>();
            onSocketConnectionListenerList.add(onSocketConnectionListenerListener);
        }else if(!onSocketConnectionListenerList.contains(onSocketConnectionListenerListener)){
            onSocketConnectionListenerList.add(onSocketConnectionListenerListener);
        }
    }

    /**
     * Remove socket connection listener.
     *
     * @param onSocketConnectionListenerListener the on socket connection listener listener
     */
    public void removeSocketConnectionListener(OnSocketConnectionListener onSocketConnectionListenerListener) {
        if(onSocketConnectionListenerList !=null
                && onSocketConnectionListenerList.contains(onSocketConnectionListenerListener)){
            onSocketConnectionListenerList.remove(onSocketConnectionListenerListener);
        }
    }

    /**
     * Remove all socket connection listener.
     */
    public void removeAllSocketConnectionListener() {
        if(onSocketConnectionListenerList !=null){
            onSocketConnectionListenerList.clear();
        }
    }

    /**
     * The type Net receiver.
     */
    public static class NetReceiver extends BroadcastReceiver {

        /**
         * The Tag.
         */
        public final String TAG = NetReceiver.class.getSimpleName();

        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager cm =
                    (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnectedOrConnecting();

            SocketManager.getInstance().fireInternetStatusIntent(
                    isConnected?SocketManager.STATE_CONNECTED:SocketManager.STATE_DISCONNECTED);
            if (isConnected) {
                if(SocketManager.getInstance().getSocket()!=null
                        && !SocketManager.getInstance().getSocket().connected()){
                    SocketManager.getInstance().fireSocketStatus(SocketManager.STATE_CONNECTING);
                }
                PowerManager powerManager =
                        (PowerManager) context.getSystemService(Context.POWER_SERVICE);
                boolean isScreenOn;
                if (android.os.Build.VERSION.SDK_INT
                        >= android.os.Build.VERSION_CODES.KITKAT_WATCH) {
                    isScreenOn = powerManager.isInteractive();
                }else{
                    //noinspection deprecation
                    isScreenOn = powerManager.isScreenOn();
                }

                if (isScreenOn && SocketManager.getInstance().getSocket() !=null) {
                    Log.d(TAG, "NetReceiver: Connecting Socket");
                    if(!SocketManager.getInstance().getSocket().connected()){
                        SocketManager.getInstance().getSocket().connect();
                    }
                }
            }else{
                SocketManager.getInstance().fireSocketStatus(SocketManager.STATE_DISCONNECTED);
                if(SocketManager.getInstance().getSocket() !=null){
                    Log.d(TAG, "NetReceiver: disconnecting socket");
                    SocketManager.getInstance().getSocket().disconnect();
                }
            }
        }
    }
}

连接插座

您可以从任何活动或后台服务连接/断开套接字

    SocketManager.getInstance().connectSocket(user.getToken(), user.getUserId(),
            getResources().getString(R.string.host), "8000");

Update

如果您的应用程序在后台被杀死,套接字也会被破坏。如果您希望套接字在后台保持连接,您必须使用与套接字无关的后台服务创建自己的逻辑。

实施OnSocketConnectionListener

public interface OnSocketConnectionListener {
    void onSocketEventFailed();
    void onSocketConnectionStateChange(int socketState);
    void onInternetConnectionStateChange(int socketState);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 为多个活动存储 Socket.io 对象 的相关文章

  • Android自定义控件命名空间问题

    我一直在为 Android 开发自定义控件 尽管我尝试按照建议进行操作here https stackoverflow com questions 4495511 how to pass custom component parameter
  • 如何从一个活动中完成一系列开放的子活动?

    我正在尝试为我的应用程序制作一个退出按钮 无论如何 我能够跟踪我的应用程序中的所有活动实例 然后完成它们 但在某些情况下 仍有一些活动仍然存在 不知道怎么办 有没有什么方法可以杀死android中的特定应用程序 或者我可以通过任何其他方式退
  • OPENGL ES 不工作:无当前上下文

    我尝试了 OpenGL ES2 for Android 一书中所示的程序 但它不起作用 我已经在Odroid E 三星s3 三星y 三星star上进行了测试 the gl version suported returns 2 but i g
  • 有没有办法将搜索栏添加到我的实际首选项屏幕?

    我一直看到有关添加您自己的搜索栏首选项的教程 但它不在我实际的 prefs xml 中 有什么方法可以在我的主偏好设置屏幕中添加一个 或者我必须将其分开 Google 似乎有 2 个滑块首选项 搜索栏首选项 https github com
  • 毕加索磁盘缓存

    我正在使用 Picasso 从 URL 加载图像 Picasso with getApplicationContext load product getImageUrl into imageView 据我所知 每次都会访问该网址 而不是缓存
  • Android Facebook sdk 3.5 分享对话框

    您好 我正在为 android sdk 3 5 实现 facebook 共享对话框 但是我按照指南没有取得任何成功 FacebookDialog shareDialog new FacebookDialog ShareDialogBuild
  • Android ListView 自定义适配器 ImageButton

    这可能不是正确的方法 如果有更好的方法请告诉我 我创建了一个自定义适配器类 在我的 getView 方法中我膨胀了我想要使用的视图 public View getView int position View convertView View
  • ListView:防止视图回收

    我有一个使用回收视图的 ListView 我试图阻止视图被回收 所以我使用 setHasTransientState android support v4 view ViewCompatJB setHasTransientState Vie
  • 如何忽略 LeakCanary 中的某些类?

    有人能给我一个如何忽略 LeakCanary 中的某些类的有效示例吗 我正在查看这个示例 以忽略 LeakCanary 中第三方库中的某些类 但我不知道将其放在应用程序中的何处 我把它放在我的应用程序类中 但这些变量和方法有错误 isInA
  • android:进程和进程名称

    我试图理解android process属性 Ref says http developer android com guide topics manifest application element html proc 如果分配给该属性的
  • 无法在云控制台中启用 Maps SDK for Android

    我在云控制台中启用适用于 Android 的 Maps SDK 时遇到此问题 https console cloud google com https console cloud google com 它会抛出以下错误 附截图 我收到错误消
  • 使用 RxJava 限制吞吐量

    我现在遇到的情况很难解释 所以我会写一个更简单的版本来解释这个问题 我有一个Observable from 它发出一系列由ArrayList文件数量 所有这些文件都应上传到服务器 为此 我有一个函数可以完成这项工作并返回一个Observab
  • 更改 Android 中的媒体音量?

    我可以更改媒体音量吗 如何 到目前为止我用过这个 setVolumeControlStream AudioManager STREAM MUSIC 但有一个搜索栏并且想要更改媒体音量 而不是铃声音量 那么有人可以告诉我如何更改媒体音量onC
  • android 多关键词搜索

    我的应用程序包含搜索功能 它将搜索数据库内的内容 我的搜索的弱点是 我只能使用一个标签进行搜索 例如我只能搜索 猫 它会返回我的数据库中包含 猫 一词的内容 因为我正在使用LIKE在 select 语句期间进行查询 如何使用多个标签进行搜索
  • 收到“无法解析上传的APK的AndroidManifest.xml。它是否正确编译?”启用 Google 应用签名后出现错误

    启用后谷歌应用程序签名 https support google com googleplay android developer answer 7384423 hl en 每次我尝试将签名版本 APK 上传到 Play 商店时 都会收到一
  • 如何在Android网格视图中设置单元格大小?

    我正在尝试为应用程序制作一个带有大图标的网格视图 但我找不到任何有关修改 Android 上网格布局上的单元格大小的教程 有人可以给我一个例子或相关链接吗 Thanks 就像另一个一样适配器视图 http developer android
  • 使用 UPI url 调用 PSP 应用程序

    我正在尝试创建一个商家应用程序 它将根据 NPCI 的指南生成一个 url 此 url 将作为意图共享 并且 PSP 应用程序 任何注册的银行应用程序 应该能够侦听该 url 并被调用 我已经形成了这样的网址 upi pay pa icic
  • 如何在 kotlin 中检查 lambda 空值

    在 Kotlin 中如何检查 lambda 是否为空 例如 我有这样的签名 onError Throwable gt Unit 我如何区分它的默认值是应用于主体还是应用于此函数的值 您无法测试 lambda 的主体是否为空 因此它不包含源代
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • Application.onLowMemory() 未调用

    我创建了自己的应用程序类 我尝试调试它 代码在 Application onCreate 处停止 但不会在 onLowMemory 处停止 为了测试该场景 我打开了许多其他高内存应用程序 我看到的是调试会话终止 在 Eclipse 中 并且

随机推荐

  • Apache:配置应用程序侦听器时出错

    当我尝试运行该应用程序时 我遇到了这个问题 警告 SetContextPropertiesRule Context 设置属性 源 到 org eclipse jst j2ee server CongressApp 没有找到匹配的 财产 20
  • 运行时签名是什么?

    当涉及到有界类型时 我对 Java 的类型擦除有一些理解上的问题 考虑一下 class Event From the API class FooEvent extends Event abstract class Foo
  • 带参数的多重继承

    我已经阅读了很多有关继承的内容 但我似乎无法理解为什么这会给我一个错误 使用Python 2 7 x class A object def init self value super A self init print First s va
  • 是否可以使用 jQuery 从 SQL Server 检索数据?

    是否可以使用 jQuery 从 SQL Server 检索数据并使用 HTML 控件显示数据 jQuery 被设计为在浏览器环境中运行 所以这是一个具有 DOM 的环境 具有 JavaScript 支持 显然 等等 要从 MS SQL Se
  • 将参数内的日期转换为整数

    现在我有一个存储过程 它将日期作为integer 140213 但在SSRS我需要转换在date parameter to the integer前面提到过 现在我试图通过两个参数 日期和转换 来实现这一目标 一个参数允许您选择日期 第二个
  • 如何在本机反应中获取元素的宽度?

    如何获取 React Native 中元素的宽度 例如 View 由于React Native中没有宽度的百分比使用 如何获取元素或父元素的宽度 您可以致电onLayout测量元素的事件 measureView event console
  • 如何动态添加JSF组件

    我可以动态添加 JSF 组件吗 我需要一个带有按钮的表单 该按钮应该添加一个
  • NSFetchRequest 不返回任何内容

    任何人都可以发现为什么这不返回任何 ManagedObjects 吗 我试图将以下内容添加到 ATNSManagedObject EasyFetching 类中 但获取结果不返回任何内容 如果我在 EasyFetch 类之外获取这些对象 我
  • PL/SQL 中是否有方法将文本转换/编码为 XML 兼容文本?

    我的一位同事需要将 PL SQL 方法中的文本转换为符合 XML 的文本 因为他正在通过更新文本模板来构建 Excel 电子表格 PL SQL 中是否有方法将文本转换 编码为 XML 兼容文本 好吧 如果您只想转换 XML 字符 您需要执行
  • Django 信号发射一次,接收两次——为什么?

    我正在使用 Django 信号 但即使发出一次 它们似乎也会被接收两次 这是我正在使用的代码 这是一个将 Uploadify 与 Django 结合使用的简单包装器 Signal emitting code emits whenever a
  • RAILS 3 模型验证包含不起作用

    Schema Information Schema version Table name terms id integer not null primary key user id integer term type string 255
  • 是否可以将 Firebase 与 Windows 8 应用结合使用?

    我希望在使用 WinJS 制作的 Windows 8 应用程序中使用 Firebase 以下是我尝试写入 Firebase 根目录的方式 var dataRef new Firebase https
  • Python 中 iter 函数的第二个参数是什么?

    让我们考虑一个文件 echo e This is a foo bar sentence nAnd this is the first txtfile in the corpus gt test txt cat test txt This i
  • jQuery 中如何查找具有特定 id 的 div 是否存在?

    我有一个附加一个函数 div 到单击时的元素 该函数获取单击元素的文本并将其分配给名为的变量name 然后将该变量用作 div id附加元素的 我需要看看是否 div id with name在我追加元素之前已经存在 但我不知道如何找到它
  • STL容器如何复制对象?

    我知道 STL 容器 比如vector添加对象时复制该对象 push back方法如下 void push back const T x 我很惊讶地发现它把该项目作为参考 我编写了一个示例程序来看看它是如何工作的 struct Foo Fo
  • 将多嵌套 dict/json 加载到 pandas 中

    我正在尝试加载一个非常令人困惑的多重嵌套JSON变成熊猫 我已经在使用了json 规范化 http pandas pydata org pandas docs stable reference api pandas io json json
  • 如何为 ActionBar 的 ActionMode 背景设置动画?

    背景 可以更改操作栏的背景 甚至可以在两种颜色之间设置动画 如下所示 public static void animateBetweenColors final ActionBar actionBar final int colorFrom
  • Intellij IDEA 无法使用 Play 框架解析符号

    我正在使用 IDEA 13 和 Play 2 2 1 并且正在做示例游玩地点 http www playframework com documentation 2 2 x JavaTodoList public static Result
  • Lua :: 如何编写加载多个CPU的简单程序?

    我还无法用 Lua 编写一个可以加载多个 CPU 的程序 自从Lua通过协程支持这个概念 http www lua org pil 9 4 html 我相信这是可以实现的 我失败的原因可能是以下之一 这在Lua中是不可能的 我写不出来 an
  • Android 为多个活动存储 Socket.io 对象

    我正在制作我的第一个基于 Socket io 的 Android 应用程序 套接字从 Web 服务发送和接收数据 应用程序中有许多屏幕用于不同的功能 我如何在这些不同的活动中使用相同的套接字连接 我尝试在 Application 类中设置和