知識點-----AIDL(一)簡單的aidl實現
AIDL是什麼
AIDL(Android Interface Definition Language)是Android系統自定義的介面描述語言。可以用來實現程序間的通訊。
AIDL 支援的資料型別
共 4 種:
- Java 的基本資料型別
- List 和 Map
- 元素必須是 AIDL 支援的資料型別
- Server 端具體的類裡則必須是 ArrayList 或者 HashMap
- 其他 AIDL 生成的介面
- 實現 Parcelable 的實體
aidl實現步驟(案例一:簡單的add)
此次的demo,服務端也進行了除錯,如果服務端調通了啟動服務與呼叫方法,客戶端啟動服務和呼叫方法可直接複製過去。
服務端
1、建立專案:建立DemoAidlService專案(跟正常一樣)
2、建立aidl檔案:
在app(Android預覽目錄下)上右鍵 New -> AIDL -> AIDL File。此時自動建立aidl資料夾,並在aidl資料夾下建立跟DemoAidlService包名一樣的路徑,且建立aidl結尾的檔案,
點選build後,發現build資料夾下自動生成debug資料夾下的aidl編譯檔案
3、新增aidl裡的抽象方法:在aidl檔案下新增方法(如add(in int x, in int y)
interface IAddAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); int add(in int x, in int y); }
4、 建立服務:建立自定義服務AddService繼承自Service,在生命週期onBind()中返回值返回 aidl物件mBinder,mBinder = InAddAidlInterface.Stub(){ 可重寫抽象方法,並實現邏輯 }
public class AddService extends Service { @Override public IBinder onBind(Intent intent) { return mBinder; } IAddAidlInterface.Stub mBinder = new IAddAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int add(int x, int y) throws RemoteException { return x + y;//具體的實現邏輯 } }; }
5、啟動服務:啟動服務時要用繫結式啟動bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
關鍵是第二個mConn引數,mConn = ServiceConnection(){ 預設兩個抽象方法,在連線成功方法onServiceConnected中賦值aidl物件mService = IAddAidlInterface.Stub.asInterface(service) }
注意要asInterface,不然會報錯。
public class MainActivity extends AppCompatActivity {
private IAddAidlInterface mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aboutService();
findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_x)).getText().toString());
int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_y)).getText().toString());
try {
Log.d("baibai", "服務端 相加結果:" + mService.add(x, y));
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("baibai", "服務端:連線 Service 成功");
mService = IAddAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private void aboutService() {
Intent intent = new Intent(this, AddService.class);
bindService(intent, mConn, Context.BIND_AUTO_CREATE);
}
}
6、呼叫方法:實際呼叫mService的裡的方法。
客戶端
1、建立專案:建立DemoAidlClient專案(跟正常一樣)
2、建立aidl檔案(但是跟服務端建立的方式):
不能右鍵New -> ……,因為如果這麼建立會建立跟DemoAidlClient的包名是一樣的,而我們需要的是跟服務端的包名一樣,所以要自己手動建立跟服務端一樣的包名路徑,並把服務端的aidl複製到改包名下,build一下,客戶端專案就可以引用到服務端aidl檔案的抽象方法。
3、啟動服務:
public class MainActivity extends AppCompatActivity {
private IAddAidlInterface mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aboutService();
findViewById(R.id.btn_add_client).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_x)).getText().toString());
int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_y)).getText().toString());
try {
Log.d("baibai", "客戶端 相加結果:" + mService.add(x, y));
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private void aboutService() {
Intent intent = new Intent();
intent.setAction("bai.bai.bai.aidl.service_add");//5.0出現以後必須使用顯示啟動,不然會報錯(加了下一行程式碼可解決這個問題)
intent.setPackage("bai.bai.bai.demoaidlservice");//加了這行程式碼,就可以解決5.0版本後隱式啟動服務報錯的問題
Log.d("baibai", "aboutService");
bindService(intent, mConn, Context.BIND_AUTO_CREATE);
}
ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("baibai", "客戶端:連線 Service 成功");
mService = IAddAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConn);
}
}
啟動服務時要用繫結式啟動bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
第一個引數initent:intent裡沒有引數,要intent.setAction(過濾條件),即隱式呼叫,所以要在服務端的清單檔案裡給service新增acton,以便客戶端使用
ps:a、要在onDestory()方法裡解除繫結,不然會報錯。
b、繫結的時候,必須有Intent.setPackage(伺服器的包名),不然會報錯(5.0後必須使用顯示啟動服務,新增這一行程式碼可解決這一報錯問題)。
c、只有在連線成功的時候才會呼叫onServiceConnected()方法,此時mBinder才不為空,型別轉換的時候最好用IAddService.Stub.asInterface()方法,不要直接強制轉換。
第二個引數mConn:mConn = ServiceConnection(){ 預設兩個抽象方法,在連線成功方法onServiceConnected中賦值aidl物件mService = IAddAidlInterface.Stub.asInterface(service) }
注意要asInterface,不然會報錯。
4、呼叫方法:實際呼叫mService的裡的方法。
參考git程式碼:服務端:https://github.com/baiyun1234/DemoAidlService
客戶端:https://github.com/baiyun1234/DemoAidlClient
參考網址:https://blog.csdn.net/guanhang89/article/details/51386404