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

时间:2016-11-15 06:27:06

标签: 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;
    }
}

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;
    }
}

2 个答案:

答案 0 :(得分:4)

如果您的应用程序停止后仍需要套接字。将套接字移动到后台服务,然后您可以在服务中添加套接字事件。

答案 1 :(得分:3)

您在主线程上打开套接字。不要在主线程上打开套接字连接,它会给你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() {
                =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;
        }
    }