Android IPC進(jìn)程間通信詳解最新AndroidStudio的AIDL操作)
前言
前面梳理了Android的線程間的通信《Thread、Handler和HandlerThread關(guān)系何在?》 ,這些都是在同一個(gè)進(jìn)程中,那進(jìn)程間的通信,或者說(shuō)不同的應(yīng)用間的通信該如何實(shí)現(xiàn)呢?這個(gè)時(shí)候就要用到AIDL(Android Interface Definition LanguageAndroid接口定義語(yǔ)言 )。
使用方法(AndroidStudio)
我發(fā)現(xiàn)現(xiàn)在AIDL的教程基本上還是eclipse的,但是在AndroidStudio里面使用AIDL還是有一些不同的,來(lái)看看怎么用,首先新建一個(gè)工程當(dāng)做server服務(wù)端:
創(chuàng)建好后在任意文件夾右鍵New-->AIDL-->AIDL File,編輯文件名后會(huì)自動(dòng)在src/main目錄下面新建aidl文件夾,包的目錄結(jié)構(gòu)如下:
main
aidl
com.example.tee.testapplication.aidl
java
com.example.tee.testapplication
res
AndroidManifest.xml
自動(dòng)生成的aidl文件如下:
// AidlInterface.aidl
package com.example.tee.testapplication.aidl;
// Declare any non-default types here with import statements
interface AidlInterface {
/**
* 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);
}
我們可以看到aidl文件的代碼格式跟java很像,支持java的基礎(chǔ)類型以及List、Map等,如果是自定義類的話需要手動(dòng)導(dǎo)入,我們后面再說(shuō),先來(lái)最簡(jiǎn)單的,新建一個(gè) IMyAidlInterface.aidl文件,修改如下:
package com.example.tee.testapplication.aidl;
interface IMyAidlInterface {
String getValue();
}
在接口中定義一個(gè)getValue方法,返回一個(gè)字符串,現(xiàn)在可以編譯一下工程,找到app/build/generated/source/aidl/debug目錄,在我們應(yīng)用包名下會(huì)發(fā)現(xiàn)生成了一個(gè)Interface類,名字跟我們定義的aidl的文件名字一樣,這說(shuō)明其實(shí)aidl文件在最后還是會(huì)轉(zhuǎn)換成接口來(lái)實(shí)現(xiàn),而且這個(gè)文件不需要我們維護(hù),在編譯后自動(dòng)生成。
然后新建一個(gè)類繼承Service:
public class MAIDLService extends Service{
public class MAIDLServiceImpl extends IMyAidlInterface.Stub{
@Override
public String getValue() throws RemoteException {
return "get value";
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MAIDLServiceImpl();
}
}
在MAIDLService類中定義一個(gè)內(nèi)部類繼承IMyAidlInterface.Stub,并且重寫我們?cè)赼idl也就是在接口中定義的getValue方法,返回字符串get value。
到了這里,我們就新建好了這個(gè)服務(wù)端,作用是在調(diào)用后返回一個(gè)字符串,最后在AndroidManifest文件中聲明:
<service android:name=".MAIDLService" android:process=":remote"http://加上這句的話客戶端調(diào)用會(huì)創(chuàng)建一個(gè)新的進(jìn)程 android:exported="true"http://默認(rèn)就為true,可去掉,聲明是否可以遠(yuǎn)程調(diào)用 > <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="com.example.tee.testapplication.aidl.IMyAidlInterface" /> </intent-filter> </service>
android:process=":remote"這一行的作用是聲明是否調(diào)用時(shí)新建進(jìn)程,接下來(lái)寫客戶端代碼,新建一個(gè)工程,將剛才創(chuàng)建的aidl文件拷貝到這個(gè)工程中,注意同樣也是要放在aidl文件夾下,然后在MainActivity中編寫代碼如下:
public class MainActivity extends AppCompatActivity {
private TextView mValueTV;
private IMyAidlInterface mAidlInterface = null;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = new Intent("com.example.tee.testapplication.aidl.IMyAidlInterface");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
mValueTV = (TextView) findViewById(R.id.tv_test_value);
mValueTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mValueTV.setText(mAidlInterface.getValue());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
if(mAidlInterface != null){
unbindService(mServiceConnection);
}
super.onDestroy();
}
}
注意這里新建Intent的傳入的參數(shù)字符串是在manifest里面自定義的action標(biāo)簽,并且在onDestroy記得取消綁定服務(wù)。
執(zhí)行結(jié)果就是我們?cè)邳c(diǎn)擊TextView時(shí)會(huì)顯示服務(wù)端給我們返回的get value字符串
自定義的對(duì)象
剛才我們使用的是基礎(chǔ)類型String,在使用我們自己定義的類的時(shí)候用上面的方法是不行的,用我們自定義的類需要手動(dòng)導(dǎo)入,修改剛才我們創(chuàng)建的作為服務(wù)端的工程
首先在開(kāi)始生成的aidl包下(所有aidl相關(guān)的文件都要放在這個(gè)包下)新建Student.java
public class Student implements Parcelable{
public String name;
public int age;
protected Student(Parcel in) {
readFromParcel(in);
}
public Student() {
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
}
public void readFromParcel(Parcel in){
age = in.readInt();
name = in.readString();
}
@Override
public String toString() {
return String.format(Locale.ENGLISH, "STUDENT[%s:%d]", name, age);
}
}
需要實(shí)現(xiàn)Parcelable序列化接口,AndroidStudio會(huì)自動(dòng)生成靜態(tài)內(nèi)部類CREATOR和describeContents方法,這些部分我們都不需要修改,用自動(dòng)生成的就好。然后重寫writeToParcel方法,自定義readFromParcel方法,注意這兩個(gè)方法里面的屬性順序必須一致,一個(gè)是寫入,一個(gè)是讀取。在構(gòu)造方法Student(Parcel in)中調(diào)用readFromParcel(in)方法。
接下來(lái)新建Student.aidl文件(也是在aidl包中):
// Student.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements parcelable Student;
注意這里Student前面的關(guān)鍵字parcelable首字母是小寫哦,再修改IMyAidlInterface.aidl文件如下:
// IMyAidlInterface.aidl
package com.example.tee.testapplication.aidl;
// Declare any non-default types here with import statements
import com.example.tee.testapplication.aidl.Student;
interface IMyAidlInterface {
Student getStudent();
void setStudent(in Student student);
String getValue();
}
定義了兩個(gè)方法,一個(gè)是設(shè)置Student,一個(gè)是獲取Student,在setStudent這個(gè)方法注意參數(shù)在類型前面有個(gè)in關(guān)鍵字,在aidl里參數(shù)分為in輸入,out輸出
現(xiàn)在在MAIDLService.java中重寫新加的兩個(gè)方法:
private Student mStudent;
public class MAIDLServiceImpl extends IMyAidlInterface.Stub{
@Override
public Student getStudent() throws RemoteException {
return mStudent;
}
@Override
public void setStudent(Student student) throws RemoteException {
mStudent = student;
}
@Override
public String getValue() throws RemoteException {
return "get value : " + Thread.currentThread().getName() + Thread.currentThread().getId();
}
}
服務(wù)端代碼修改完畢,來(lái)到客戶端工程,同樣要把剛才的aidl包下的文件拷貝覆蓋過(guò)來(lái),保持兩邊一致,然后在MainActivity.java中修改如下:
mValueTV = (TextView) findViewById(R.id.tv_test_value);
mStudentTV = (TextView) findViewById(R.id.tv_test_student);
mValueTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mValueTV.setText(mAidlInterface.getValue());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
mStudentTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Student student = new Student();
student.age = 10;
student.name = "Tom";
mAidlInterface.setStudent(student);
mStudentTV.setText(mAidlInterface.getStudent().toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
現(xiàn)在編譯工程,會(huì)發(fā)現(xiàn)工程會(huì)報(bào)錯(cuò),找不到類Student,我們需要在app目錄下的build.gradle文件添加代碼如下:
android {
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
}
也就是指定一下文件目錄,現(xiàn)在再編譯就沒(méi)有問(wèn)題了
總結(jié)
Android的IPC使用起來(lái)還是挺簡(jiǎn)單的,AIDL文件的語(yǔ)法也跟我們平時(shí)使用接口的時(shí)候很相似,但是它只支持基礎(chǔ)類型,只能引用AIDL文件,需要使用自定義類的時(shí)候要稍微麻煩一點(diǎn)。
以上就是對(duì)Android IPC 進(jìn)程通信的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料謝謝大家對(duì)本站的支持!
相關(guān)文章
Android程序設(shè)計(jì)之AIDL實(shí)例詳解
這篇文章主要介紹了Android程序設(shè)計(jì)的AIDL,以一個(gè)完整實(shí)例的形式較為詳細(xì)的講述了AIDL的原理及實(shí)現(xiàn)方法,需要的朋友可以參考下2014-09-09
Android中使用AsyncTask實(shí)現(xiàn)文件下載以及進(jìn)度更新提示
AsyncTask,它使創(chuàng)建需要與用戶界面交互的長(zhǎng)時(shí)間運(yùn)行的任務(wù)變得更簡(jiǎn)單,本篇文章主要介紹了Android中使用AsyncTask實(shí)現(xiàn)文件下載以及進(jìn)度更新提示,有興趣的可以了解一下。2016-12-12
Android進(jìn)階事件分發(fā)機(jī)制解決事件沖突
這篇文章主要為大家介紹了Android進(jìn)階事件分發(fā)機(jī)制解決事件沖突過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Flutter 首頁(yè)必用組件NestedScrollView的示例詳解
今天介紹的組件是NestedScrollView,大部分的App首頁(yè)都會(huì)用到這個(gè)組件。對(duì)Flutter 首頁(yè)必用組件NestedScrollView的相關(guān)知識(shí)感興趣的一起看看吧2020-05-05
Android實(shí)現(xiàn)中國(guó)象棋游戲(局域網(wǎng)版)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)局域網(wǎng)版的中國(guó)象棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Android 動(dòng)畫之AlphaAnimation應(yīng)用詳解
本節(jié)講解AlphaAnimation 動(dòng)畫,窗口的動(dòng)畫效果,淡入淡出什么的,有些游戲的歡迎動(dòng)畫,logo的淡入淡出效果就使用AlphaAnimation,具體的祥看本文,需要的朋友可以參考下2012-12-12
快速解決進(jìn)入fragment時(shí)不能彈出軟件盤的問(wèn)題
下面小編就為大家?guī)?lái)一篇快速解決進(jìn)入fragment時(shí)不能彈出軟件盤的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android提高之TelephonyManager功能探秘
這篇文章主要介紹了Android的TelephonyManager功能,可以幫助讀者更好的理解Java反射機(jī)制,需要的朋友可以參考下2014-08-08

