Android跨進程通信Messenger
阿新 • • 發佈:2018-09-15
stat protected sco urn color 服務端 llb fin server
一.概述
我們可以在客戶端發送一個Message給服務端,在服務端的handler中會接收到客戶端的消息,然後進行對應的處理,處理完成後,再將結果等數據封裝成Message,發送給客戶端,客戶端的handler中會接收到處理的結果。
有這麽幾個特點:
-
基於Message,相信大家都很熟悉
-
支持回調的方式,也就是服務端處理完成長任務可以和客戶端交互
-
不需要編寫aidl文件
此外,還支持,記錄客戶端對象的Messenger,然後可以實現一對多的通信;甚至作為一個轉接處,任意兩個進程都能通過服務端進行通信,這個後面再說。
二.應用
package com.imooc.messenger_server; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException;public class MessengerService extends Service { private static final int MSG_SUM = 0x110; //最好換成HandlerThread的形式 private Messenger mMessenger = new Messenger(new Handler() { @Override public void handleMessage(Message msgfromClient) { Message msgToClient = Message.obtain(msgfromClient);//返回給客戶端的消息 switch (msgfromClient.what) { //msg 客戶端傳來的消息 case MSG_SUM: msgToClient.what = MSG_SUM; try { //模擬耗時 Thread.sleep(2000); msgToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2; msgfromClient.replyTo.send(msgToClient); }catch (InterruptedException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } break; } super.handleMessage(msgfromClient); } }); @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } }
服務端就一個Service,可以看到代碼相當的簡單,只需要去聲明一個Messenger對象,然後onBind方法返回mMessenger.getBinder();
然後坐等客戶端將消息發送到handleMessage想法,根據message.what去判斷進行什麽操作,然後做對應的操作,最終將結果通過 msgfromClient.replyTo.send(msgToClient);返回。
可以看到我們這裏主要是取出客戶端傳來的兩個數字,然後求和返回,這裏我有意添加了sleep(2000)模擬耗時,註意在實際使用過程中,可以換成在獨立開辟的線程中完成耗時操作,比如和HandlerThread結合使用。
註冊文件
<service android:name=".MessengerService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.zhy.aidl.calc"></action> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
(二)客戶端
Activity
package com.imooc.messenger_client; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final int MSG_SUM = 0x110; private Button mBtnAdd; private LinearLayout mLyContainer; //顯示連接狀態 private TextView mTvState; private Messenger mService; private boolean isConn; private Messenger mMessenger = new Messenger(new Handler() { @Override public void handleMessage(Message msgFromServer) { switch (msgFromServer.what) { case MSG_SUM: TextView tv = (TextView) mLyContainer.findViewById(msgFromServer.arg1); tv.setText(tv.getText() + "=>" + msgFromServer.arg2); break; } super.handleMessage(msgFromServer); } }); private ServiceConnection mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service); isConn = true; mTvState.setText("connected!"); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; isConn = false; mTvState.setText("disconnected!"); } }; private int mA; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //開始綁定服務 bindServiceInvoked(); mTvState = (TextView) findViewById(R.id.id_tv_callback); mBtnAdd = (Button) findViewById(R.id.id_btn_add); mLyContainer = (LinearLayout) findViewById(R.id.id_ll_container); mBtnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { int a = mA++; int b = (int) (Math.random() * 100); //創建一個tv,添加到LinearLayout中 TextView tv = new TextView(MainActivity.this); tv.setText(a + " + " + b + " = caculating ..."); tv.setId(a); mLyContainer.addView(tv); Message msgFromClient = Message.obtain(null, MSG_SUM, a, b); msgFromClient.replyTo = mMessenger; if (isConn) { //往服務端發送消息 mService.send(msgFromClient); } } catch (RemoteException e) { e.printStackTrace(); } } }); } private void bindServiceInvoked() { Intent intent = new Intent(); intent.setAction("com.zhy.aidl.calc"); bindService(intent, mConn, Context.BIND_AUTO_CREATE); Log.e(TAG, "bindService invoked !"); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mConn); } }
代碼也不復雜,首先bindService,然後在onServiceConnected中拿到回調的service(IBinder)對象,通過service對象去構造一個mService =new Messenger(service);然後就可以使用mService.send(msg)給服務端了。
Android跨進程通信Messenger