最簡單的Android Aidl 使用
首先,為什麼要用aidl
---------------------------------------------------------------------------------------------------------------------------
aidl其實就是進程間的通訊官方文檔特別提醒我們何時使用AIDL是必要的:只有你允許用戶端從不同的應用程式為了進程間的通訊而去訪問你的service,以及想在你的service處理多線程。如果不需要進行不同應用程式間的並發通訊(IPC),you should create your interface by implementing a Binder;或者你想進行IPC,但不需要處理多線程的,則implement your interface using a Messenger
簡單說就是,1、你某個service想被別人使用;2、你想使用其它進程的service
然後,怎麼用aidl(一下是一個最簡單的使用,從服務端擷取一個字串)-------------------------------------------------------------------------
步驟:服務端1、在服務程式端建立xxx.aidl檔案,裡面放介面(這個介面要與檔案名稱一樣),寫法跟寫Java程式一樣2、建立一個Service,這個Service裡面實現之前那個aidl檔案裡面的介面3、manifest.xml檔案註冊Serviceclient端1、copy之前的那個aidl檔案過來(要獨立一個跟服務端檔案夾相同名字的檔案夾,否則會報錯最後面的那個錯誤)2、在activity裡面初始化ServiceConnection(用來bind Service的),和
獲得服務端的service服務端的service = 介面.Stub.asInterface(service);//在ServiceConnection的onServiceConnected裡面實現3、bindService
實現代碼:先看一下目錄結構
ExecuteMyAidlService.aidl檔案(注意介面名稱要與檔案名稱前邊相同)
package aid;interface ExecuteMyAidlService { String sayHello();}MyAidlService.java檔案
package aidlservice;import aid.ExecuteMyAidlService;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;public class MyAidlService extends Service{private static final String TAG = "MyAidlService"; private ExecuteMyAidlService.Stub mBinder = new ExecuteMyAidlService.Stub() {@Overridepublic String sayHello() throws RemoteException {// TODO Auto-generated method stubreturn "hello ";} };@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn mBinder;}private void Log(String str) { android.util.Log.d(TAG, "------ " + str + "------"); } @Override public void onCreate() { Log("service create"); } @Override public void onStart(Intent intent, int startId) { Log("service start id=" + startId); } }activity裡面沒有東西就不貼了
用戶端的目錄結構
ClientActivity的代碼:
package com.example.aidlclienttest;import aid.ExecuteMyAidlService;import android.support.v7.app.ActionBarActivity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class ClientActivity extends ActionBarActivity { private ExecuteMyAidlService mIaidlServerService = null; private TextView mTextView = null; private Button mButton = null; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { mIaidlServerService = null; } public void onServiceConnected(ComponentName name, IBinder service) { mIaidlServerService = ExecuteMyAidlService.Stub.asInterface(service); //aidl通訊 try { String mText = "Say hello: " + mIaidlServerService.sayHello(); mTextView.setText(mText); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_client); mTextView = (TextView)findViewById(R.id.helloword); mButton = (Button)findViewById(R.id.getServiceFromAidl); mButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent service = new Intent("aidl.ExecuteMyAidlService");service.setAction("aidl.ExecuteMyAidlService"); bindService(service, mConnection,BIND_AUTO_CREATE); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.client, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}
這裡就實現了最簡單的aidl通訊的過程看一下效果先開啟服務端
然後再啟動client端,點擊bindservice之後
進階aidl<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPgo8c3Ryb25nPi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTwvc3Ryb25nPgoxoaLI57n7ztLP67TTc2VydmljZbvxyKG21M/zxNijv6Oo1+7SqtOm08OjqQq9q7bUz/PKtc/WcGFyY2VsYWJsZSC907/aCiAgICDOqtXiuPa21M/z0LS49mFpZGzOxLz+W8Dvw+bWu9Do0qq2qNLl0rvPwtXiuPa21M/zvs3Q0MHLyOc6XQo8c3Ryb25nPjwvc3Ryb25nPjxwcmUgY2xhc3M9"brush:java;">parcelable Object
2、如果activity要往service裡面傳遞資料呢?【如果是對象一樣是要parcelable,(因為client和server的aidl檔案是一樣的)】要在介面函數那裡加上in基本類型(int,long,char,boolean等),String,CharSequence,List,Map,其他類型必須使用import匯入,即使它們可能在同一個包裡,比如上面的Student,儘管它和IMyService在同一個包中,但是還是需要顯示的import進來。
另外,介面中的參數除了aidl支援的類型,其他類型必須標識其方向:到底是輸入還是輸出抑或兩者兼之,用in,out或者inout來表示,一般in標記,因為大多數情況下輸入型參數。
過程中碰到的錯誤------------------------------------------------------------------------------------------------------------------------------------------------java.lang.SecurityException: Binder invocation to an incorrect interface在service端和client端都有.aidl檔案,一定要放在單獨的包中,因為兩個app中的MainActivity的包名不相同,會導致兩個.aidl檔案內容不同。單獨一個包,只放.aidl檔案,就能保證包名和檔案內容都是相同的。