標籤:對象 lte 有一個 null 子類 用戶端 ons action label
Android進程間的通訊方式可以通過以下兩種方式完成:
1 Android介面定義語言(AIDL)2 使用Messenger綁定服務
本文我們將學習使用Messenger綁定服務的方式進行進程間的通訊。
Android AIDL和Messenger區別
使用Messenger是執行處理序間通訊最簡單的方法,因為Messenger會在單一線程中建立包含所有請求的隊列,這樣您就不必對服務進行安全執行緒設計。而純粹的AIDL介面會同時向服務發送多個請求,服務隨後必須應對多執行緒。AIDL通常應用在服務被設計到單獨的應用中的情境(即服務端可用戶端不屬於同一個app的情況),而Messenger通常應用在同一app的不同進程的情境中。
Messenger基本思想
服務端(被動方)提供一個Service來處理用戶端(主動方)串連,維護一個Handler(具體來講:是Handler的子類)來建立Messenger,在onBind時返回Messenger的binder(調用Messenger的getBinder()方法,該方法返回一個IBinder對象,用戶端將通過該對象作為參數建立一個Messenger對象用於與服務端進行通訊)。
Messenger使用步驟
1、服務端實現一個Handler,由其接收來自用戶端的每個調用的回調2、使用第1步的Handler的執行個體作為target建立Messenger對象(即該Messenger持有了對Handler的引用)3、使用Messenger建立一個IBinder(通過調用Messenger的getBinder()方法),服務端的onBind()方法中將其返回到用戶端4、用戶端使用IBinder將Messenger(引用服務端的Handler執行個體)執行個體化,然後使用後者將Message對象發送給服務端5、服務端在其Handler中接收每個Message
這樣,用戶端並沒有調用服務端的“方法”,而用戶端傳遞的訊息(Message對象)是服務端在其Handler中接收到的。
如果想讓服務端對用戶端發迴響應,則還需要在用戶端中建立一個持有用戶端Handler實作類別的Messenger,當用戶端收到onServiceConnected()回調時,在向服務發送的Message時,send()方法的replyTo參數中需包含用戶端的Messenger。這樣,用戶端就可在其Handler實作類別中接收到來自服務端的響應訊息。
簡單樣本
AndroidMainfest.xml
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="yf.exam.client.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MessengerService" android:process=":custom_process"/></application>
在上面的設定檔中,service的android:process屬性用於在一個單獨進程中啟動service,看如片:
布局檔案很簡單,這裡只有一個按鈕,用於向服務端發送訊息並顯示服務端響應內容,這裡不再給出。
用戶端:MainActivity
public class MainActivity extends Activity { private static final int REPLY_MSG_ID = 2; private boolean mServiceConnected = false; private Button btn = null; //用於向Service端發送訊息的Messenger private Messenger mBoundServiceMessenger = null; //用於接收Service發送訊息的Messenger private final Messenger mReceiveMessenger = new Messenger(new ReceiveMessHandler(this)); private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mBoundServiceMessenger = null; mServiceConnected = false; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mBoundServiceMessenger = new Messenger(service); mServiceConnected = true; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button)findViewById(R.id.button); bindService(new Intent(this, MessengerService.class), conn, Context.BIND_AUTO_CREATE); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mServiceConnected){ //擷取訊息對象 Message msg = Message.obtain(null, 1, 0, 0); try{ //replyTo參數包含用戶端Messenger msg.replyTo = mReceiveMessenger; //向Service端發送訊息 mBoundServiceMessenger.send(msg); }catch(RemoteException re){ re.printStackTrace(); } } } }); } @Override protected void onDestroy() { super.onDestroy(); if(mServiceConnected){ unbindService(conn); mServiceConnected = false; } } /** * 用戶端實現一個Handler用於接收服務端返回的響應 * @author Administrator * */ static class ReceiveMessHandler extends Handler{ //持有當前Activity的弱引用,避免記憶體泄露 private final WeakReference<MainActivity> mActivity; public ReceiveMessHandler(MainActivity activity){ mActivity = new WeakReference<MainActivity>(activity); } @Override public void handleMessage(Message msg) { switch(msg.what){ case REPLY_MSG_ID: Toast.makeText(mActivity.get(), msg.getData().getString("msg"), Toast.LENGTH_SHORT).show(); break; } } }}
服務端:MessengerService.java
public class MessengerService extends Service { private static final int REPLY_MSG_ID = 2; private static final int MSG_ID = 1; static class BoundServiceHandler extends Handler{ private final WeakReference<MessengerService> mService; public BoundServiceHandler(MessengerService service){ mService = new WeakReference<MessengerService>(service); } @Override public void handleMessage(Message msg) { switch(msg.what){ case MSG_ID: Messenger replyMessenger = msg.replyTo; Message replyMsg = Message.obtain(null, REPLY_MSG_ID); //向用戶端響應的訊息內容 Bundle b = new Bundle(); b.putString("msg", "this is the message reply from service"); replyMsg.setData(b); try{ replyMessenger.send(replyMsg); }catch(RemoteException re){ re.printStackTrace(); } break; default: super.handleMessage(msg); } } } private final Messenger mMessenger = new Messenger(new BoundServiceHandler(this)); @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); }}
Android進程間的通訊之Messenger