AIDL:android interface define language(接口定義語言)
作用:方便遠程調用其他服務中的方法
注意:安卓四大組件都要在清單文件注冊
aidl創建圖:
AIDL的全稱是什么?如何工作?能處理哪些類型的數據?
AIDL全稱Android Interface Definition Language(AndRoid接口描述語言)是一種接口描述語言; 編譯器可以通過aidl文件生成一段代碼,通過預先定義的接口達到兩個進程內部通信進程跨界對象訪問的目的.AIDL的IPC的機制和COM或CORBA類似, 是基於接口的,但它是輕量級的。它使用代理類在客戶端和實現層間傳遞值.
如果要使用AIDL, 需要完成2件事情:
1. 引入AIDL的相關類.;
2. 調用aidl產生的class.
理論上, 參數可以傳遞基本數據類型和String, 還有就是Bundle的派生類, 不過在Eclipse中,目前的ADT不支持Bundle做為參數
具體實現步驟如下:
1、創建AIDL文件, 在這個文件里面定義接口, 該接口定義了可供客戶端訪問的方法和屬性。
2、編譯AIDL文件, 用Ant的話, 可能需要手動, 使用Eclipse plugin的話,可以根據adil文件自動生產java文件並編譯, 不需要人為介入.
3、在Java文件中, 實現AIDL中定義的接口. 編譯器會根據AIDL接口, 產生一個JAVA接口。這個接口有一個名為Stub的內部抽象類,它繼承擴展了接口並實現了遠程調用需要的幾個方法。接下來就需要自己去實現自定義的幾個接口了.
4、向客戶端提供接口ITaskBinder, 如果寫的是service,擴展該Service並重載onBind ()方法來返回一個實現上述接口的類的實例。
5、在服務器端回調客戶端的函數. 前提是當客戶端獲取的IBinder接口的時候,要去注冊回調函數, 只有這樣, 服務器端才知道該調用那些函數
AIDL語法很簡單,可以用來聲明一個帶一個或多個方法的接口,也可以傳遞參數和返回值。 由於遠程調用的需要, 這些參數和返回值並不是任何類型.
下面是些AIDL支持的數據類型:
1. 不需要import聲明的簡單Java編程語言類型(int,boolean等)
2. String, CharSequence不需要特殊聲明
3. List, Map和Parcelables類型, 這些類型內所包含的數據成員也只能是簡單數據類型, String等其他比支持的類型.
(另外: 我沒嘗試Parcelables, 在Eclipse+ADT下編譯不過, 或許以后會有所支持).
實現接口時有幾個原則:
.拋出的異常不要返回給調用者. 跨進程拋異常處理是不可取的.
.IPC調用是同步的。如果你知道一個IPC服務需要超過幾毫秒的時間才能完成地話,你應該避免在Activity的主線程中調用。也就是IPC調用會掛起應用程序導致界面失去響應. 這種情況應該考慮單起一個線程來處理.
.不能在AIDL接口中聲明靜態屬性。
IPC的調用步驟:
1. 聲明一個接口類型的變量,該接口類型在.aidl文件中定義。
2. 實現ServiceConnection。
3. 調用ApplicationContext.bindService(),並在ServiceConnection實現中進行傳遞.
4. 在ServiceConnection.onServiceConnected()實現中,你會接收一個IBinder實例(被調用的Service). 調用
YourInterfaceName.Stub.asInterface((IBinder)service)將參數轉換為YourInterface類型。
5. 調用接口中定義的方法。你總要檢測到DeadObjectException異常,該異常在連接斷開時被拋出。它只會被遠程方法拋出。
6. 斷開連接,調用接口實例中的ApplicationContext.unbindService()
參考:http://buaadallas.blog.51cto.com/399160/372090
interface InterfaceAidl { void interfacePay(); }
public class MyService extends Service { class MyBinder extends InterfaceAidl.Stub { @Override public void interfacePay() throws RemoteException { pay(); } } @Nullable @Override public IBinder onBind(Intent intent) { MyBinder binder = new MyBinder(); return binder; } private void pay() { Log.i("service","支付成功"); } }
public class MainActivity extends AppCompatActivity { private Intent intent; private MyServiceConnection myServiceConnection; private InterfaceAidl interfaceAidl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intent = new Intent(this,MyService.class); myServiceConnection = new MyServiceConnection(); } public void bind(View view){ bindService(intent, myServiceConnection, BIND_AUTO_CREATE); } public void pay(View view){ try { interfaceAidl.interfacePay(); } catch (RemoteException e) { e.printStackTrace(); } } class MyServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { interfaceAidl = InterfaceAidl.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } } @Override protected void onDestroy() { super.onDestroy(); unbindService(myServiceConnection); } }
遠程調用服務
遠程服務。
1:將服務所在的項目中man目錄下的aidl目錄復制粘貼到當前項目。然后同步。會在項目的build-generated--source--
aidl---debug--生成一個PayInterface.java文件.
2:在MainActivity里創建意圖。
intent = new Intent();
//從5.0開始,intent不能使用隱式意圖
intent.setAction("aidl_server.pay");
intent.setPackage("com.qf.gao.d25_aidl_service");//指定包名,
3:其他的跟調用本地服務一樣。
interface InterfaceAidl { void interfacePay(); }
<service android:name=".MyService">
<intent-filter>
<action android:name="aidl_interface.pay"></action>
</intent-filter>
</service>
public class MainActivity extends AppCompatActivity { private Intent intent; private InterfaceAidl interfaceAidl; private MyServiceConnection myServiceConnection; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intent = new Intent(); myServiceConnection = new MyServiceConnection(); intent.setAction("aidl_interface.pay"); intent.setPackage("com.example.administrator.aidlservice"); } public void bind(View view){ bindService(intent,myServiceConnection,BIND_AUTO_CREATE); } public void pay(View view){ try { interfaceAidl.interfacePay(); } catch (RemoteException e) { e.printStackTrace(); } } class MyServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { interfaceAidl = InterfaceAidl.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } } @Override protected void onDestroy() { super.onDestroy(); unbindService(myServiceConnection); } }