如何在Android中将套接字事件作为后台服务来处理?

Wop*_*ppi 9 android socket.io

我是Android开发的新手,我希望我的应用程序能够检测套接字事件,即使应用程序未通过后台服务处于活动状态(因此我可以执行推送通知,例如,如果有一个新的消息由套接字事件触发,如Whatsapp和其他人这样做).

我实现了后台服务和一个启动服务的应用程序类,但是在后台服务中将套接字事件作为Runnable任务放在哪里以及如何放置.

我修改了下面的socket.io android chat项目示例并添加了服务和应用程序类.

ChatApplication.java

package com.github.nkzawa.socketio.androidchat;

import android.app.Application;
import android.content.Intent;
import android.content.res.Configuration;

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

import java.net.URISyntaxException;

public class ChatApplication extends Application {

    @Override
    // called when the application is starting, before any other application objects have been created
    public void onCreate() {
        super.onCreate();

        // represents our background service
        Intent background = new Intent(this, SocketBackgroundService.class);
        startService(background);
    }

    private Socket mSocket;
    {
        try {
            mSocket = IO.socket(Constants.CHAT_SERVER_URL);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public Socket getSocket() {
        return mSocket;
    }
}
Run Code Online (Sandbox Code Playgroud)

SocketBackgroundService.java

package com.github.nkzawa.socketio.androidchat;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class SocketBackgroundService extends Service {
    private boolean isRunning;
    private Thread backgroundThread;

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

    @Override
    public void onCreate() {
        this.isRunning = false;
        this.backgroundThread = new Thread(myTask);
    }

    private Runnable myTask = new Runnable() {
        @Override
        public void run() {
            // do something in here
            Log.i("INFO", "SOCKET BACKGROUND SERVICE IS RUNNING");

            //TODO - how to handle socket events here?
            //How do I do something like mSocket.on(Socket.EVENT_CONNECT,onConnect); here?
        }
    };

    @Override
    public void onDestroy() {
        this.isRunning = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if( !this.isRunning) {
            this.isRunning = true;
            this.backgroundThread.start();
        }

        return START_STICKY;
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

如果您需要套接字,即使您的应用程序停止后也要保持活动状态。将套接字移至后台服务,然后可以在服务中添加套接字事件。


Man*_*are 5

您在主线程上打开套接字。不要在主线程上打开套接字连接,它会给你 ANR(应用程序无响应)错误,这是由于 UI 线程上的大量工作而发生的。它阻塞 UI 线程超过 5 秒。所以我建议你在服务内部的线程上打开套接字连接。
这是使用普通套接字的示例:

  1. 创建一个服务类用于在后台服务上启动线程
  2. 在 Thread 类上创建以在线程上打开套接字连接
  3. 为套接字通信创建单独的类

    public class SocketBackgroundService extends Service {
    
    private SocketThread mSocketThread;
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public void onCreate() {
    
        mSocketThread = SocketThread.getInstance();
    }
    
    
    @Override
    public void onDestroy() {
        //stop thread and socket connection here
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mSocketThread.startThread) {
        } else {
            stopSelf();
        }
    
        return START_STICKY;
    }
    }
    
    public class SocketThread extends Thread {
    
    private static SocketThread mSocketThread;
    private SocketClient mSocketClient;
    
    private SocketThread() {
    }
    
    // create single instance of socket thread class
    public static SocketThread getInstance() {
        if (mSocketThread == null)//you can use synchronized also
        {
            mSocketThread = new SocketThread();
        }
        return mSocketThread;
    }
    
    
    public boolean startThread() {
          mSocketClient = new SocketClient();
        if (socketClient.isConnected()) {
            mSocketThread.start()
            return true;
        }
        return false;
    }
    
    @Override
    public void run() {
        super.run();
        while (mSocketClient.isConnected()) {
            // continue listen
        }
        // otherwise remove socketClient instance and stop thread
    }
    
    public class SocketClient {
        //write all code here regarding opening, closing sockets
        //create constructor
        public SocketClient() {
            // open socket connection here
        }
    
        public boolean isConnected() {
            return true;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 你好 Sam,我是 android 开发的新手,想知道你在哪个部分检测到我的代码在主线程上运行?通过上面的 Ashish 的建议,我让后台服务运行起来并能够监听套接字。正如你提到的这个问题,我想改进它。这是我的工作代码:https://gist.github.com/arvi/a31843d26dcd1fd69c32bbe2bb7130d7 如果你能抽出时间给建议,非常感谢,我真的很感激。:) (2认同)
  • 嗨 Woppi,关于选择正确的方法/方式,我将举一个例子或建议,为了达到我们的目的地,他们有很多方法,但我们必须选择正确的方法,或者至少我们必须尝试。就像在技术方面一样,我们必须首先对项目进行研发,然后我们才能有很多方法来执行项目。然后我们选择合适的。如果失败,那么我们选择下一个。所以不要担心。如果你失败了……你会学到更多。 (2认同)