Binder,Service,進程間通信學習總結

一、      本地Service與Binder的使用

本地Service和Activity通信可以通過Binder實現,先在Service中繼承Binder實現自己的Binder類。

[java] view plain copy
  1. class MyBinder extends Binder {  
  2.       public LocalBindService getService() {  
  3.           return LocalBindService.this;  
  4.       }  
  5.   }  

然後在Service中的onBind()中返回這個Binder的實例。

[java] view plain copy
  1. @Override  
  2.    public IBinder onBind(Intent intent) {  
  3.        Log.i(TAG,"onBind");  
  4.        doSomeTask();  
  5.        return mMyBinder;  
  6.    }  

在Activity中,通過onServiceConnected()獲取Binder實例由,Binder實例可以得到Service實例。這樣可以調用Service中公共方法,但有時需要Service主動通知Activity做一些更新UI操作。這時需要在Service中定義一個接口,然後Service可以通過這個接口來回調Activity裏面的方法。

[java] view plain copy
  1. interface ProgressChangeListener {  
  2.         void updateProgress(int value);  
  3.     }  
  4.   
  5.     public void setProgressChangeListener(ProgressChangeListener progressChangeListener) {  
  6.         mProgressChangeListener = progressChangeListener;  
  7.     }  

在Activity中:
[java] view plain copy
  1. private ServiceConnection mConnection = new ServiceConnection() {  
  2.         @Override  
  3.         public void onServiceDisconnected(ComponentName name) {  
  4.   
  5.         }  
  6.   
  7.         @Override  
  8.         public void onServiceConnected(ComponentName name, IBinder service) {  
  9.             LocalBindService.MyBinder myBinder = (LocalBindService.MyBinder) service;  
  10.             LocalBindService localBindService =myBinder.getService();  
  11.             //通過Binder與Service通信  
  12.             localBindService.setProgressChangeListener(new LocalBindService.ProgressChangeListener() {  
  13.                 @Override  
  14.                 public void updateProgress(int value) {  
  15.                     mBindProgressBar.setProgress(value);  
  16.                 }  
  17.             });  
  18.         }  
  19.     };  

二、      通過Messenger與遠程進程通信

Messenger可以實現Service與遠程進程通信,Messenger隊列所有的請求放在一個單獨的線程當中,因此,Service每次只能處理一個請求。

1、Service實現了一個Handler,用來接收和處理客戶端發送過來的消息。

[java] view plain copy
  1. class MessengerHandler extends Handler {  
  2.        @Override  
  3.        public void handleMessage(Message msg) {  
  4.            switch (msg.what) {  
  5.                case MSG_REGISTER_CLIENT:  
  6.                    mClients.add(msg.replyTo);  
  7.                    break;case MSG_UNREGISTER_CLIENT:  
  8.                    try {  
  9.                        msg.replyTo.send(Message.obtain(null,  
  10.                                MSG_UNREGISTER_CLIENT, 88880));  
  11.                    } catch (RemoteException e) {  
  12.                        e.printStackTrace();  
  13.                    }  
  14.                    mClients.remove(msg.replyTo);  
  15.                    break;case MSG_SET_VALUE:  
  16.                    mValue = msg.arg1;  
  17.                    for (int i = mClients.size() - 1; i >= 0; i--) {  
  18.                        try {  
  19.                            mClients.get(i).send(Message.obtain(null,  
  20.                                    MSG_SET_VALUE, mValue, 0));  
  21.                        } catch (RemoteException e) {  
  22.                            mClients.remove(i);  
  23.                        }  
  24.                    }  
  25.                    break;default:  
  26.                    super.handleMessage(msg);  
  27.            }  
  28.        }  
  29.    }  

2、創建一個包含Handler引用Messenger對象。

[java] view plain copy
  1. private MessengerHandler mMessengerHandler = new MessengerHandler();  
  2.   private Messenger mMessenger = new Messenger(mMessengerHandler);  

3、通過Messenger 得到Binder,並從onBind()方法將其返回。

[java] view plain copy
  1. @Override  
  2.    public IBinder onBind(Intent intent) {  
  3.        return mMessenger.getBinder();  
  4.    }  

4、客戶端在ServiceConnection中,使用IBinder來實例化這個Messenger,用這個Messenger向Service發送Message對象,Service 中的Handler將處理這個Message對象。

  1. private ServiceConnection mServiceConnection=new ServiceConnection() {  
  2.        @Override  
  3.        public void onServiceConnected(ComponentName name, IBinder service) {  
  4.          mMessengerService=new Messenger(service);  
  5.          mCallbackText.setText("Attached.");  
  6.            try {Message msg = Message.obtain(null,  
  7.                        MessengerService.MSG_REGISTER_CLIENT);  
  8.                msg.replyTo = mMessenger;  
  9.                mMessengerService.send(msg);  
  10.                msg = Message.obtain(null,  
  11.                        MessengerService.MSG_SET_VALUE, this.hashCode(), 0);  
  12.                mMessengerService.send(msg);  
  13.            } catch (RemoteException e) {  
  14.   
  15.            } Toast.makeText(MessengerActivity.this"remote_service_connected",  
  16.                    Toast.LENGTH_SHORT).show();  
  17.        }  
  18.   
  19.        @Override  
  20.        public void onServiceDisconnected(ComponentName name) {  
  21.            mCallbackText.setText("Disconnected.");  
  22.            Toast.makeText(MessengerActivity.this"remote_service_disconnected",  
  23.                    Toast.LENGTH_SHORT).show();  
  24.        }  
  25.    };  

5、客戶端同樣定義一個Handler對象,用於處理服務端返回的Message對象,同時構造一個包含這個Handler引用的Messenger對象,在向服務端發送消息時,將客戶端的Messenger對象賦值給消息的replyTo,這樣,服務端通過replyTo向客戶端發送的Message對象。

通過這種方法,客戶端和服務端可以相互傳遞Message對象。

[java] view plain copy
  1. <span style="font-size:14px;">private Handler mHandler=new Handler(){  
  2.         @Override  
  3.         public void handleMessage(Message msg) {  
  4.             switch (msg.what) {  
  5.                 case MessengerService.MSG_SET_VALUE:  
  6.                     mCallbackText.setText("Received from service: " + msg.arg1);  
  7.                     breakcase  MessengerService.MSG_UNREGISTER_CLIENT:  
  8.                     Toast.makeText(MessengerActivity.this"Received from service: "+msg.arg1,  
  9.                             Toast.LENGTH_SHORT).show();  
  10.                 default:  
  11.                     super.handleMessage(msg);  
  12.             }  
  13.         }  
  14.     };  
  15.   
  16. private Messenger mMessenger=new Messenger(mHandler);</span>  


三、      通過AIDL與遠程進程通信

AIDL(Android InterfaceDefinition Language)是Android接口定義語言的意思,它可以用於讓某個Service與多個應用程序組件之間進行跨進程通信,從而可以實現多個應用程序共享同一個Service的功能。

如果需要Service同時接收多個請求,Messenger不能滿足需求,需要使用AIDL。在這種情況下,Service必須有能力執行多個線程,必須爲Service實現線程安全。

1.創建一個.aidl

AIDL參數和返回值可以是任何類型,甚至其他AIDL生成的接口。 使用Java語言構建一個.aidl文件,每個.aild文件必須定義一個單獨的接口,並且使用確定的聲明和方法簽名。

[java] view plain copy
  1. / IRemoteService.aidl  
  2. package com.example.xujiang.servicelearn;  
  3. import  com.example.xujiang.servicelearn.IRemoteServiceCallback;  
  4. // Declare any non-default types here with import statements  
  5.   
  6. interface IRemoteService {  
  7.       void registerCallback(IRemoteServiceCallback cb);  
  8.             
  9.       void unregisterCallback(IRemoteServiceCallback cb);  
  10. }  

2. 繼承這個接口

Android SDK工具會爲.aidl文件生成一個接口。這個接口有一個叫Stub的內部抽象類。需要寫一個類繼承這個Stub類並且實現這些方法,在onBind返回這個類的實例對象。

[java] view plain copy
  1. private final IRemoteService.Stub mRemoteServiceStub=new IRemoteService.Stub() {  
  2.         @Override  
  3.         public void registerCallback(IRemoteServiceCallback cb) throws RemoteException {  
  4.            if (cb!=null){  
  5.                mCallbacks.register(cb);  
  6.            }  
  7.         }  
  8.   
  9.         @Override  
  10.         public void unregisterCallback(IRemoteServiceCallback cb) throws RemoteException {  
  11.             if (cb!=null){  
  12.                 mCallbacks.unregister(cb);  
  13.             }  
  14.         }  
  15.     };  

3.把接口暴露給客戶端

繼承一個Service並且重寫onBind()來返回實現的Stub類。客戶端通過asInterface方法得到接口的引用,從而可以調用接口裏面的方法。

如果需要在進程間傳遞類,類必須支持Parcelable 接口。支持Parcelable 接口是因爲Android系統需要分解對象爲可以穿越進程的原語。

[java] view plain copy
  1. @Override  
  2.    public IBinder onBind(Intent intent) {  
  3.        Log.i(TAG,"onBind");  
  4.        return mRemoteServiceStub;  
  5.    }  

4.客戶端調用

[java] view plain copy
  1. private ServiceConnection mConnection = new ServiceConnection() {  
  2.         public void onServiceConnected(ComponentName className,  
  3.                                        IBinder service) {  
  4.             mRemoteService = IRemoteService.Stub.asInterface(service);  
  5.             mCallbackText.setText("Attached.");  
  6.             try {  
  7.                 mRemoteService.registerCallback(mServiceCallback);  
  8.             } catch (RemoteException e) {  
  9.             }Toast.makeText(AIDLActivity.this"remote_service_connected",  
  10.                     Toast.LENGTH_SHORT).show();  
  11.         }  
  12.   
  13.         public void onServiceDisconnected(ComponentName className) {  
  14.             mRemoteService = null;  
  15.             mCallbackText.setText("Disconnected.");  
  16.             Toast.makeText(AIDLActivity.this"remote_service_disconnected",  
  17.                     Toast.LENGTH_SHORT).show();  
  18.         }  
  19.     };  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章