看過官方文檔以及其他的博客和慕課網對AIDL的介紹,做了以下的整理,方便隨時查看:
AIDL介紹
AIDL(Android interface Definition Language,安卓接口定義語言),使用AIDL可以實現跨進程通信。
Android中的綁定服務有三種,分別是:擴展Binder類,Messenger,AIDL。
- 擴展Binder類主要用於服務只是本應用的後臺工作線程。
- Messenger實現跨不同的進程工作,是執行進程間通信 (IPC) 的最簡單方法,因爲 Messenger 會在單一線程中創建包含所有請求的隊列,服務一次接受一個請求,這樣就不必對服務進行線程安全設計。
- AIDL用於跨進程通信,讓服務同時處理多個請求,需要服務具備多線程處理能力,採用線程安全式設計。
注意:只有運行不同應用的客戶端,用IPC訪問服務,並且想要在服務中處理多線程時,纔有必要使用AIDL。
AIDL創建
在Android Studio裏,直接在Java包上右擊,創建一個AIDL文件,就會自動生成aidl包,並創建了指定的aidl文件。
完成aidl文件的創建後,點擊上方的
這樣就會自動生成相應的java類:
AIDL實現
注意 AIDL中不能有修飾訪問符(public,private,protected),支持Java基本數據類型(除short,例如int,long,char等),支持String,CharSequence,List,Map。必須爲其他數據類型加入import語句。在方法參數使用時,所有非原語參數(我認爲是其他數據類型),要有in,out,inout來標記數據走向,默認爲in。(in表示客戶端的參數輸入,out表示服務端的參數輸入,inout表示客戶端可輸入、服務端也可輸入)
下面是使用AIDL進行簡單的數據傳輸:
在IMyAIDL中聲明一個方法,我們想要通過這個方法獲取字符串信息,修改完畢後點擊這個按鈕,Android SDK工具會生成aidl文件相應的java接口文件
// IMyAIDL.aidl
package com.example.aidldemo;
interface IMyAIDL {
String getMessage(String s);
}
創建Service的類MyService,在Manifest中註冊Service:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
我們通過SDK生成的java接口文件中包括一個名爲Stub的子類,這個子類是其父接口的抽象實現,用於聲明aidl文件中的所有方法。我們通過Service實現這個接口,向客戶端公開接口,以便客戶端進行綁定,這就需要通過onBinde方法了:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mbinder;
}
private final IMyAIDL.Stub mbinder = new IMyAIDL.Stub() {
@Override
public String getMessage(String s) throws RemoteException {
return "收到消息"+s;//返回獲取到的內容
}
};
}
現在當客戶端調用bindService連接服務器,客戶端的OnServiceConnected()回調會接收服務的onBind()方法返回mbinder實例。Stub中定義了asInterface()方法,這個方法將IBinder傳遞給客戶端的onServiceConnected()。
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAIDL = IMyAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAIDL = null;
}
};
完整代碼
public class MainActivity extends AppCompatActivity {
private TextView textView ;
private EditText editText;
private IMyAIDL iMyAIDL;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
editText = (EditText) findViewById(R.id.edit);
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAIDL = IMyAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAIDL = null;
}
};
public void startService(View view) {
try {
String message = iMyAIDL.getMessage(editText.getText().toString());
textView.setText(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
佈局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.aidldemo.MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text"
/>
</LinearLayout>
效果如圖