Android Studio創(chuàng)建AIDL文件并實(shí)現(xiàn)進(jìn)程間通訊實(shí)例
在Android系統(tǒng)中,跨進(jìn)程通信是非常普遍的事情,它用到了Binder機(jī)制處理進(jìn)程之間的交互。Binder機(jī)制會(huì)開(kāi)放一些接口給Java層,供android開(kāi)發(fā)工程師調(diào)用進(jìn)程之間通信。這些接口android封裝到了AIDL文件里,當(dāng)我們項(xiàng)目用到跨進(jìn)程通信時(shí)可以創(chuàng)建.aidl文件,.aidl文件可以協(xié)助我們達(dá)到跨進(jìn)程的通信。下面簡(jiǎn)單介紹用AndroidStudio創(chuàng)建AIDL文件的過(guò)程。
a.新建AIDL文件
1.項(xiàng)目文件夾右鍵---> new --->選擇AIDL

2.自定義一個(gè)接口名稱(chēng)

3.創(chuàng)建之后我們看到了xxx.aidl文件,然后編輯自己項(xiàng)目需要實(shí)現(xiàn)的方法,這里很簡(jiǎn)單就獲取一個(gè)字符串的方法getAllName。

4.寫(xiě)好之后,我們需要重新ReBuild,完后在項(xiàng)目build/generated/source/aidl/debug/包名 目錄下就看到了系統(tǒng)為我們生成的以剛才.aidl文件名命名的java文件。

該java文件系統(tǒng)會(huì)自動(dòng)生成代碼:
Stub:描述了一個(gè)Java服務(wù),對(duì)應(yīng)是一個(gè)遠(yuǎn)程的Service。
Proxy:描述了一個(gè)Java服務(wù)的代理對(duì)象,在Client端就會(huì)得到這個(gè)對(duì)象。
這兩者都實(shí)現(xiàn)了IPersonManager接口。
asInterface:將Java服務(wù)的代理對(duì)象即一個(gè)BinderProxy封裝成了一個(gè)IPersonManager.Stub.Proxy對(duì)象,實(shí)現(xiàn)了IPersonManager接口。
onTransact:負(fù)責(zé)接收分發(fā)進(jìn)程間的通信。它首先會(huì)收到Client發(fā)來(lái)的請(qǐng)求,不同的方法進(jìn)入相應(yīng)的case代碼中,然后交給Stub的子類(lèi)去處理事件,例如 java.lang.String _result = this.getAllName(); 這里的this就可以讓它的子類(lèi)去接收該請(qǐng)求并處理。
IBinder的transact方法:用來(lái)發(fā)送進(jìn)程間的請(qǐng)求。
b.利用AIDL實(shí)現(xiàn)進(jìn)程間的通訊
一:接口文件中只含有基礎(chǔ)數(shù)據(jù)類(lèi)型
如上aidl文件,IPersonManager中只用到了基本數(shù)據(jù)類(lèi)型,此時(shí)要完善Server端的小項(xiàng)目,還需要新建一個(gè)Service。
Server端代碼如下
public class PersonService extends Service {
private static String names = "alice & iland";
public PersonBinder mPersonBinder;
@Override
public void onCreate() {
super.onCreate();
mPersonBinder = new PersonBinder();
}
@Override
public IBinder onBind(Intent intent) {
return mPersonBinder;
}
public class PersonBinder extends IPersonManager.Stub{
@Override
public String getAllName() throws RemoteException {
return names;
}
}
}
繼承系統(tǒng)的Service,并建立一個(gè)內(nèi)部類(lèi)繼承IPersonManager.Stub,這里很簡(jiǎn)單,當(dāng)客戶(hù)端請(qǐng)求要獲取名字時(shí)我們這里把names給到客戶(hù)端。
Client端代碼如下
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private Button btnGet;
private EditText etShow;
public IPersonManager mIPersonManager;
ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected: ");
mIPersonManager = IPersonManager.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
mIPersonManager = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGet = (Button) findViewById(R.id.btn_getname);
etShow = (EditText) findViewById(R.id.et_allnamef);
btnGet.setOnClickListener(this);
Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
intent.setPackage("com.ly.testaidlserver");
bindService(intent,sc, Service.BIND_AUTO_CREATE);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_getname:
String names = null;
try {
if (mIPersonManager!=null)
names = mIPersonManager.getAllName();
} catch (RemoteException e) {
e.printStackTrace();
}
etShow.setText(names);
break;
default:
break;
}
}@Override
protected void onDestroy() {
super.onDestroy();
unbindService(sc);
}
}
在onServiceConnected方法中拿到IPersonManager的代理對(duì)象,最終獲取到 alice & ilan,與服務(wù)端數(shù)據(jù)一致。
注意:
1.bindService方法在5.0以后做出改變,隱式意圖需要設(shè)置Package 或者 Commponent,直接定義一個(gè)action是報(bào)異常的。
Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
intent.setPackage("com.ly.testaidlserver");
bindService(intent,sc, Service.BIND_AUTO_CREATE);
2.我們需要把Server端的aidl文件復(fù)制到Client端,在Client中存放aidl的文件夾也需要跟Server端包名一致。
如圖:


上圖為aidl文件在Server端存放的路徑,下圖為復(fù)制到Client端aidl文件的路徑,這里要保持一致,因此Client端需要針對(duì)Server端的包名新建一個(gè)Package。
3.當(dāng)我們啟動(dòng)項(xiàng)目的時(shí)候,如果在Activity中IPersonManager找不到報(bào)出異常,請(qǐng)?jiān)赼pp的build.gradle中添加aidl文件指名目錄,如本例中添加,
sourceSets{
main {
aidl.srcDirs = ['src/main/aidl','src/main/java']
}
}
二:接口文件中含有復(fù)雜數(shù)據(jù)類(lèi)型、
1.新建一個(gè)Person.aidl 內(nèi)容非常簡(jiǎn)單
parcelable Person;
2.新建一個(gè)Person實(shí)體類(lèi),為了能在進(jìn)程間進(jìn)行通信必須實(shí)現(xiàn)Parcelable接口。
3.在IPersonManager中添加了一個(gè)方法,這里注意用到的Person類(lèi)必須將包名improt進(jìn)去。
4.將IPersonManager.aidl、Person.aidl、Person.java復(fù)制到客戶(hù)端的aidl包下。
5.查看是否需要修改build.gradle中sourceSets設(shè)置
代碼基本沒(méi)有變化:
Person.java
public class Person implements Parcelable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in.readString(), in.readInt());
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
IPersonManager.aidl
interface IPersonManager {
String getAllName();
List<Person> getPersonList();
}
Server
public class PersonService extends Service {
private List<Person> persons = new ArrayList<Person>();
public PersonBinder mPersonBinder;
@Override
public void onCreate() {
super.onCreate();
mPersonBinder = new PersonBinder();
Person p1 = new Person("alice",23);
persons.add(p1);
Person p2 = new Person("iland",18);
persons.add(p2);
}
@Override
public IBinder onBind(Intent intent) {
return mPersonBinder;
}
public class PersonBinder extends IPersonManager.Stub{
@Override
public String getAllName() throws RemoteException {
return "";
}
@Override
public List<Person> getPersonList() throws RemoteException {
return persons;
}
}
}
Clent
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private Button btnGet;
private EditText etShow;
public IPersonManager mIPersonManager;
ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected: ");
mIPersonManager = IPersonManager.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
mIPersonManager = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGet = (Button) findViewById(R.id.btn_getname);
etShow = (EditText) findViewById(R.id.et_allnamef);
btnGet.setOnClickListener(this);
Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
intent.setPackage("com.ly.testaidlserver");
bindService(intent,sc, Service.BIND_AUTO_CREATE);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_getname:
ArrayList<Person> persons = null;
try {
if (mIPersonManager!=null)
persons = (ArrayList<Person>) mIPersonManager.getPersonList();
} catch (RemoteException e) {
e.printStackTrace();
}
String result = "";
for (Person person : persons){
result = result+person.getName()+"__"+person.getAge();
}
etShow.setText(result);
break;
default:
break;
}
}@Override
protected void onDestroy() {
super.onDestroy();
unbindService(sc);
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android studio實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android studio實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
android studio打印日志語(yǔ)句Log.d()詳解
這篇文章主要介紹了android studio打印日志語(yǔ)句Log.d()詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04
超實(shí)用的Android手勢(shì)鎖制作實(shí)例教程
這篇文章主要介紹了一個(gè)超實(shí)用的Android手勢(shì)鎖制作實(shí)例教程,普通的圓環(huán)形圖標(biāo)變換,在App和系統(tǒng)的鎖屏界面中都可以調(diào)用,需要的朋友可以參考下2016-04-04
Android編程自定義title bar(標(biāo)題欄)示例
這篇文章主要介紹了Android編程自定義title bar(標(biāo)題欄)的方法,結(jié)合實(shí)例形式分析了Android針對(duì)標(biāo)題欄的設(shè)置與頁(yè)面布局操作相關(guān)技巧,需要的朋友可以參考下2016-10-10
Android SurfaceView預(yù)覽變形完美解決方法
本篇文章主要介紹了Android SurfaceView預(yù)覽變形完美解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
Android中使用Gson解析JSON數(shù)據(jù)的兩種方法
Json是一種類(lèi)似于XML的通用數(shù)據(jù)交換格式,具有比XML更高的傳輸效率;本文將介紹兩種方法解析JSON數(shù)據(jù),需要的朋友可以參考下2012-12-12
Android自動(dòng)測(cè)試工具M(jìn)onkey的實(shí)現(xiàn)方法
本文主要介紹Android Monkey 實(shí)現(xiàn)方法,Monkey測(cè)試是一種為了測(cè)試軟件的穩(wěn)定性、健壯性的快速有效的方法,具有非常重要的參考價(jià)值,希望對(duì)小伙伴有所幫助2016-07-07
Android開(kāi)發(fā)實(shí)現(xiàn)AlertDialog中View的控件設(shè)置監(jiān)聽(tīng)功能分析
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)AlertDialog中View的控件設(shè)置監(jiān)聽(tīng)功能,結(jié)合實(shí)例形式分析了Android針對(duì)AlertDialog中的控件使用View進(jìn)行監(jiān)聽(tīng)的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11

