AIDL是什麼
AIDL(Android Interface Definition Language)是Android系統自定義的接口描述語言。可以用來實現進程間的通訊。
AIDL 支持的數據類型
共 4 種:
- Java 的基本數據類型
- List 和 Map
- 元素必須是 AIDL 支持的數據類型
- Server 端具體的類裏則必須是 ArrayList 或者 HashMap
- 其他 AIDL 生成的接口
- 實現 Parcelable 的實體
aidl實現步驟(案例一:簡單的add)
服務端
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://blog.csdn.net/guanhang89/article/details/51386404