【问题标题】:Android Socket.IO best practices for keeping connection aliveAndroid Socket.IO 保持连接活跃的最佳实践
【发布时间】:2014-06-07 13:05:38
【问题描述】:

我的Android 应用程序正在使用AndroidAsync 库通过Socket.IO 客户端连接到Node.js 服务器。套接字客户端是通过服务建立的。

  • 应用打开时,套接字需要保持打开/连接状态
  • 应用未打开时套接字可以关闭
  • 有一种例外情况,即套接字需要在应用未打开时保持打开状态

我目前正在onResume 中启动 Socket.IO 服务,并在应用程序中每个ActivityonPause 中停止。

这似乎真的很低效,因为我基本上每次按下主页按钮或切换到应用程序中的另一个活动时都会停止套接字并重新创建一个新的。

处理上述关于保持套接字打开的要求的最佳方法是什么?

public class SocketIOService extends Service {

    private Preferences prefs;
    private SocketIOClient socket;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            ConnectCallback callback = new ConnectCallback() {
                @Override
                public void onConnectCompleted(Exception ex, SocketIOClient client) {
                    if (ex != null) {
                        ex.printStackTrace();
                        return;
                    }

                    Log.v("SOCKET IO CONNECTION", "ESTABLISHED");

                    client.setDisconnectCallback(new DisconnectCallback() {
                        @Override
                        public void onDisconnect(Exception e) {
                            Log.v("SOCKET IO CONNECTION", "TERMINATED");
                        }
                    });

                    client.setErrorCallback(new ErrorCallback() {
                        @Override
                        public void onError(String error) {
                            Log.e("SOCKET IO ERROR", error);
                        }
                    });

                    client.setExceptionCallback(new ExceptionCallback() {
                        @Override
                        public void onException(Exception e) {
                            e.printStackTrace();
                        }
                    });

                    client.setReconnectCallback(new ReconnectCallback() {
                        @Override
                        public void onReconnect() {
                            Log.v("SOCKET IO CONNECTION", "RECONNECTED");
                        }
                    });

                    client.on(EVENT_NEWS, new EventCallback() {
                        @Override
                        public void onEvent(JSONArray argument, Acknowledge acknowledge) {
                            Log.v("EVENT:NEWS", argument.toString());
                        }
                    });

                    client.on(EVENT_MESSAGE_RECEIVE, new EventCallback() {
                        @Override
                        public void onEvent(JSONArray argument, Acknowledge acknowledge) {
                            handleMessageReceive(argument);
                        }
                    });

                }
            };

            socket = SocketIOClient.connect(AsyncHttpClient.getDefaultInstance(), URL_SERVER, callback).get();

            JSONArray array = new JSONArray();
            JSONObject obj = new JSONObject();
            prefs = new Preferences(this);
            try {
                obj.put(KEY_USER_ID, prefs.getUserId());
            } catch (JSONException e) {
                e.printStackTrace();
            }
            array.put(obj);
            socket.emit(EVENT_LOG_USER_ID, array);

            Log.v("SOCKET LOG USER ID", array.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // If we get killed, after returning from here, restart
        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {
        Log.v("SOCKET IO SERVICE", "STOPPED");
        if (socket != null) {
            if (socket.isConnected()) {
                socket.disconnect();
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void handleMessageReceive(JSONArray json) {
        ChatMessage message = JReader.createMessage(json);
    }

}

【问题讨论】:

  • 您最终是如何处理您的要求的?
  • 尝试使用ActivityLifecycleCallbacks stackoverflow.com/questions/3667022/…
  • @LeonelMachava 我最终使用 GCM 在应用程序处于后台时处理任何传入请求。虽然我已经考虑过了,如果我想使用计数器,基本上可以使用其他服务来保持连接多 5-10 分钟。

标签: android sockets service socket.io


【解决方案1】:

查看未回答的旧问题并找到此问题。 我认为最好的方法是使用自动启动的绑定服务。

使用 bindService() 您可以在 onResume() 或 onStart() 中绑定您的活动,并让您的服务关闭连接并在没有客户端绑定时自行停止。

您可以在这里找到更多信息https://developer.android.com/guide/components/bound-services

【讨论】:

  • 如果我不使用Service,我应该按照您的建议写Service吗?或者我可以简单地覆盖onStartonStop 事件来控制套接字?在这种情况下,当一个活动不可见时,我们将错过套接字事件。然后在onStart 中我们可以重新加载数据(例如,聊天消息)并重新启动套接字。这样电池就不会很快耗尽。
  • @CoolMind 具有绑定服务,所有活动都绑定到它,您可以从许多活动中使用套接字,并且在从一个活动导航到另一个活动时不会重新启动它(实际上在导航时保持您的套接字连接处于活动状态)。如果您只有一个活动,并且您在 onStop 中处理套接字断开连接,然后在 onStart 中处理重新连接和数据检索,那么它是相同的。归根结底,如果您只在一个活动上,则无需“需要”使用服务(尽管将业务逻辑与活动分开总是好的)
【解决方案2】:

我有部分解决方案(我认为不会解决您的第三个要求)。 我开始写一个简单的多人游戏,只是为了学习游戏编程。 我决定使用 TCP 连接(为什么?这是另一个问题......),当用户在每个活动中进行时,我必须保持连接打开(登录 -> 大厅 -> 选择对手......), 我使用了单例模式(双重锁定检查),包含连接套接字。

伪代码

class ClientConnection{
    private static ClientConnection conn = null;
    Socket mSocket; // your socket  
    protected ClientConnection(){
        mSocket = new Socket();
        // mSocket.connect( bla bla bla ) 

    }

    public Socket getSocket(){
        return mSocket();
    }
    public static ClientConnection getInstance(){
        if(conn == null){
            synchronized (LOCK) {
                if(conn == null){
                    conn = new ClientConnection();
                }
            }
        }
        return conn;        
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-21
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 2011-12-05
    • 2012-10-10
    相关资源
    最近更新 更多