AIDL:Android Interface Define Language(Android接口定義語言),
主要用於服務端與客戶端進程間通信(當然也可以多客戶端);
大寫的PS: 遠離手機,沒事就得多擡頭.
二月二,龍擡頭,天子耕地臣趕牛,春耕夏耘率天下,五穀豐登太平秋。
言歸正傳:Android中跨進程間通信方式有很多種方式: 比如 aidl, Messenger, 文件共享, 廣播(BroadCast), ContentProvider,Socket(網絡通信) ,每種方式都有自己的使用場景和優缺點.
AIDL默認情況下只能傳遞基本類型、String、List、Map、CharSequence。下篇講解傳遞複雜數據類型.
本章由我給您介紹使用Android Studio實現跨進程傳遞簡單數據String類型(aidl);
--------------------------------------------------------
首先配上服務端的代碼,也就是咱們的AppOne的代碼:
第一步 : 創建AIDL文件.
步驟:File –> New –> AIDL –> AIDL File 完成創建之後(默認名稱),
可以看到src/main的目錄下生成了一個IMyAidlInterface.aidl文件.
不管他默認生成什麼方法.咱們把他改成咱們想要的方法.例如:
package com.it.heima.;
interface IMyAidlInterface {
String getValue();
}
然後手動編譯,clean | rebuild | make moudle "app";當然最後一個是最合適的,前者都太耗時.
然後怎麼查看是否編譯成功呢?
成功的話會在app/build/generated/sourse/aidl/debug/com.it.heima/下給咱們生成一個IMyAidlInterface接口.
第二步 : 創建遠程服務Service.
package com.it.heima;
import com.it.heima.IMyAidlInterface;
public class MyService extends Service {
IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub(){
@Override
public String getValue() throws RemoteException {
return "這是服務端返回的內容";
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
PS : IMyAidlInterface.Stub即爲服務端AIDL文件的代理對象.
第三步 : 在AndroidMenifest.xml中的application標籤中配置Service.
<!-- MyService -->
<service
android:name=".MyService"
android:process=":remote">
<intent-filter>
<action android:name="com.it.heima.MyService" />
</intent-filter>
</service>
Android系統最大的進程是com.android.phone.
process: 如果不自己指定的話此service默認運行在自己的包的進程中,也就是com.it.heima進程中.
如果自己指定的話會運行在com.it.heima:remote;
加不加冒號又分兩種區別 :
一,加冒號 : 表示該服務所在的進程是私有的.當客戶端需要該service時,系統會自動創建新進程.
二,不加冒號,表示該服務所在的進程是共享的,當幾個客戶端都需要該service時,會共用一個進程.
至此服務端的配置完畢.
-----------------------------------------------------------------------------------------
配置客戶端的代碼,也就是咱們的AppTwo的代碼:
第一步 : 需要將服務端的main/aidl包拷貝到客戶端的app/main下.手動編譯.查看是否成功.
第二步 : 客戶端綁定服務端服務(遠程服務).
package com.it.baima;
import com.it.heima.IMyAidlInterface;
public class MainActivity extends Activity implements View.OnClickListener {
private IMyAidlInterface mService;
private Button btn_bind, btn_get;
private TextView tv;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
btn_bind = (Button) findViewById(R.id.btn_bind);
btn_get = (Button) findViewById(R.id.btn_get);
tv = (TextView) findViewById(R.id.tv);
btn_bind.setOnClickListener(this);
btn_get.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind:
Intent intent = new Intent();
intent.setAction("com.it.heima.MyService");
//從 Android 5.0開始 隱式Intent綁定服務的方式已不能使用,所以這裏需要設置Service所在服務端的包名
intent.setPackage("com.it.heima");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_get:
try {
String str = mService.getValue();
tv.setText(str);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (serviceConnection != null) {
unbindService(connection);
}
}
}
就是一個簡單的界面上方有兩個Button(bindButton和getButton),和一個TextView.
首先點擊bindButton後通過bindService綁定服務端的MyService.
通過 mService = IMyAidlInterface.Stub.asInterface(service)
可以獲取到服務端的代理對象,從而可以通過回調方法從服務端獲取到我們所需的數據從而展示到我們的客戶端.
運行AppTwo,點擊bindButton,好的已經綁定好了服務,再點擊getButton通過回調方法獲取到AppOne的數據.並且等待下方的TextView改變字體.我去,我褲子都脫了你給我看空指針異常?好吧,log指示getValue爲空.怎麼爲空呢?咱們明明return了一個字符串啊.後來一想...AppOne都沒有運行到咱們的手機上.從哪裏訪問服務呢?setAction,setPackage的操作都白做了,系統根本找不到啊.想讓進程間通訊怎麼只能運行一個進程呢?趕緊把咱們的AppOne先運行到手機上,這樣兩個進程都存在,才叫進程間通訊嘛.再運行一下看看咱們的AppTwo,好的,這回褲子沒白脫.
傳遞複雜數據類型.請看大牛文章Android進程間通信之----Aidl傳遞對象
如有問題請多指正,您的指正使我更正確的前行.