Listening socket.io events and updating LiveData (a class of android.arch.lifecycle)in application class android

主宰稳场 提交于 2021-02-18 19:10:28

问题


I am working on a chat application and Currently I am listening and emitting socket events in an Activity.

Now i want to listen all the socket events even when chat activity is not in foreground as i want to store all the messages from different users in the local DB at the same time i want to update LiveData to update UI.

In order to achieve this I am listening socket events in the Application class as following:

public class ChatApplication extends Application {

public Socket mSocket;
private Map<String, Boolean> receivedFriendEventsMap = new HashMap<>();
private List<Result> friendsList = new ArrayList<>();
private AppDatabase database;

@Override
public void onCreate() {
    super.onCreate();
    try {
        mSocket = IO.socket(Constants.CHAT_SERVER_URL);
        //mSocket.connect();
    } catch (URISyntaxException e) {
        throw new RuntimeException(e);
    }
    Instance = this;
    applicationHandler = new Handler(getInstance().getMainLooper());
    NativeLoader.initNativeLibs(ChatApplication.getInstance());
    //mSocket.connect();
    database = AppDatabase.getDatabase(getApplicationContext());

    mSocket.on("friend_status", new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.d(TAG, "" + args[0] + args[1]);
            receivedFriendEventsMap.put((String) args[0], (Boolean) args[1]);
        }
    });

    mSocket.on("listen_friend_message", new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.d(TAG, "listen_friend_message: " + (String) args[0] + args[1]);

            SocketMessage socketMessage = new Gson().fromJson((String) args[0], SocketMessage.class);
            //database.socketMessageDao().addMessage(socketMessage);
            mSocket.emit("trigger_friend_message_delivered", socketMessage.getMsg_id(), socketMessage.getSender_id(), socketMessage.getReceiver_id(), args[1]);
        }
    });

    SocketMessage socketMessage = new Gson().fromJson((String) result, SocketMessage.class);
    //database.socketMessageDao().addMessage(socketMessage);
    Log.d(TAG, new Gson().toJson(database.socketMessageDao().getAllMessages(), new TypeToken<List<SocketMessage>>() {
    }.getType()));
}

Is this the right approach? If not, could anyone please suggest me some good solution. Any help is appreciated.


回答1:


You need to use LifeCycleService to connect and listen to sockets and then use service binding to observe changes in activity

This is a service class that connects to the socket and has MutableLiveData() socketData that observe the connection of the socket (You can create any type of LiveDataObject and observe inactivity)

 class SocketService : LifecycleService() {
    val socketData  = MutableLiveData<String>()
    var mSocket: Socket? = null
    private val mBinder = SocketBinder()

    override fun onCreate() {
        super.onCreate()
        mSocket?.let {
            if (!it.connected()) it.connect()
        } ?: run {
            initSocketConnection()
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)
        mSocket?.let {
            if (!it.connected()) it.connect()
        } ?: run {
            initSocketConnection()
        }
        return START_NOT_STICKY
    }

    override fun onBind(intent: Intent): IBinder {
        super.onBind(intent)
        return mBinder
    }

    override fun onUnbind(intent: Intent?): Boolean {
        return true
    }

    override fun onRebind(intent: Intent?) {
        super.onRebind(intent)
    }

    private fun initSocketConnection() {
        try {
            val options = IO.Options()
            options.timeout = 5000
            options.transports = arrayOf(WebSocket.NAME)
            mSocket = IO.socket(BuildConfig.SOCKET_SERVER_ADDRESS, options)
            connectSocket()
        } catch (e: URISyntaxException) {
            throw RuntimeException(e)
        }
    }

    private fun connectSocket() {
        mSocket?.let {
            it.connect()
            it.on(Socket.EVENT_CONNECT) {
                connectSocketListener()
                Log.e(SOCKET_TAG, "Connection Successful")
                socketData.postValue(  "Connection Successful for live data")
            }
            it.on(Socket.EVENT_CONNECT_ERROR) { args ->
                Log.e(SOCKET_TAG, "Connection Fail " + args[0].toString())
            }
            it.on(Socket.EVENT_CONNECT_TIMEOUT) { args ->
                Log.e(SOCKET_TAG, "Connection Fail " + args[0].toString())
            }
            it.on(Socket.EVENT_ERROR) { args ->
                Log.e(SOCKET_TAG, "Connection Fail " + args[0].toString())
            }
            it.on(Socket.EVENT_CONNECTING) {}

        }
    }

    override fun onDestroy() {
        super.onDestroy()
        stopSocket()
    }

    private fun stopSocket() {
        mSocket?.let {
            it.disconnect()
            it.off(Socket.EVENT_CONNECT) {}
            it.off(Socket.EVENT_CONNECT_ERROR) {}
            it.off(Socket.EVENT_CONNECT_TIMEOUT) {}
            it.off(Socket.EVENT_ERROR) {}
            it.off(Socket.EVENT_CONNECTING) {}
            disconnectSocketListener()
        }
    }

    private fun connectSocketListener() {

    }

    private fun disconnectSocketListener() {

    }

    inner class SocketBinder : Binder() {
        fun getService(): SocketService = this@SocketService
    }
}

Now in Activity you need to bind this service and listen to changes in LiveData object

class BaseActivity : AppCompatActivity() {
    private var mService: SocketService? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    private val mConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mService = (service as SocketService.SocketBinder).getService()
            mService?.let {
                it.socketData.observe(it) { arg ->
                    Log.d(SOCKET_TAG, arg)
                }
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {

        }
    }

    override fun onStart() {
        super.onStart() 
        val intent = Intent(this, SocketService::class.java)
        bindService(intent, mConnection, BIND_AUTO_CREATE)
       
    }

    override fun onStop() {
        super.onStop()
        try {
            mService?.let {
                unbindService(mConnection)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

You can see when socket is connected i am posting value in LiveData and when it is bounded I am registering an observer to listen data.



来源:https://stackoverflow.com/questions/54051614/listening-socket-io-events-and-updating-livedata-a-class-of-android-arch-lifecy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!