跨進程間通信,分別有Client端和Service端不同進程
1.定義AIDL文件,此文件現代當於一個協議,定義服務端要實現的方法。
如:
- package com.example.aidl;
- interface IMyService {
- void play();
- void pause();
- }
2.實現服務端Service:
如:
public class AIDLService extends Service {
- private MyBinder mBinder;
- @Override
- public IBinder onBind(Intent intent) {
- mBinder = new MyBinder();
- return mBinder; //返回binder對象
- }
- /*
- * 該類繼承了IMyService.Stub類而不是extends Binder類。
- * IMyService.Stub是Binder的子類。
- * 進程內的Service定義MyBinder內部類是繼承Binder類。
- */
- public class MyBinder extends IMyService.Stub {
- @Override
- public void play() throws RemoteException {
- Log.i(tag, "service 自定義 play()...");
- }
- @Override
- public void pause() throws RemoteException {
- Log.i(tag, "service 自定義 pause()...");
- }
- }
3.把AIDL文件接口複製到Client項目
4.在Client項目中調用Service項目的服務。
如:
- public class MainActivity extends Activity implements OnClickListener {
- Button btnBind, btnPlay, btnPause;
- IMyService mBinder; // 接口的一個引用
- boolean mIsBind = false; // 綁定值爲true,未綁定製爲false;
- private ServiceConnection mConn = new ServiceConnection() {
- @Override
- public void onServiceDisconnected(ComponentName name) {
- }
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- /*
- * 獲得另一個進程中的Service傳遞過來的IBinder對象-service,
- * 用IMyService.Stub.asInterface方法轉換該對象,這點與進程內的通信不同
- */
- mBinder = IMyService.Stub.asInterface(service);
- mIsBind = true;
- Log.i("MainActivity", "onServiceConnected....");
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- btnBind = (Button) findViewById(R.id.btn_bind);
- btnPlay = (Button) findViewById(R.id.btn_play);
- btnPause = (Button) findViewById(R.id.btn_pause);
- btnBind.setOnClickListener(this);
- btnPlay.setOnClickListener(this);
- btnPause.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- int btn = v.getId();
- switch (btn) {
- case R.id.btn_bind:
- intent.setAction(Constant.ACTION_AIDL);
- bindService(intent, mConn, BIND_AUTO_CREATE); //綁定服務
- break;
- case R.id.btn_play:
- if (mIsBind){
- try {
- mBinder.play(); //調用IMyService接口的方法,服務端的邏輯就可以使用
- } catch (RemoteException e) {
- e.printStackTrace();
- }//調用service中的play()
- }
- break;
- case R.id.btn_pause:
- if(mIsBind){
- try {
- mBinder.pause(); //調用IMyService接口的方法
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- break;
- }
- }
- }
以上可以看到,Stub是IMyService中的一個靜態抽象類,繼承了Binder,並且實現了IMyService接口。這也就解釋了我們定義IMyInterface.Stub的時候爲什麼需要實現IMyService中的方法了,也說明了爲什麼我們可以把IMyService.Stub向上轉型成IBinder了。
總結:
AIDL的最終效果就是讓 IPC的通訊就像調用函數那樣簡單。自動的幫你完成了參數序列化發送以及解析返回數據的那一系列麻煩。而你所需要做的就是寫上一個接口文件,然後利用aidl工具轉化一下得到另一個java文件,這個文件在服務和客戶端程序各放一份。服務程序繼承IxxxxService.Stub 然後將函數接口裏面的邏輯代碼實現一下。