Android IPC處理序間通訊詳解最新AndroidStudio的AIDL操作)_Android

來源:互聯網
上載者:User

前言

前面梳理了Android的線程間的通訊《Thread、Handler和HandlerThread關係何在?》 ,這些都是在同一個進程中,那進程間的通訊,或者說不同的應用間的通訊該如何?呢?這個時候就要用到AIDL(Android Interface Definition LanguageAndroid介面定義語言 )。

使用方法(AndroidStudio)

我發現現在AIDL的教程基本上還是eclipse的,但是在AndroidStudio裡面使用AIDL還是有一些不同的,來看看怎麼用,首先建立一個工程當做server服務端:

建立好後在任意檔案夾右鍵New-->AIDL-->AIDL File,編輯檔案名稱後會自動在src/main目錄下面建立aidl檔案夾,包的目錄結構如下:

main
aidl
com.example.tee.testapplication.aidl
java
com.example.tee.testapplication
res
AndroidManifest.xml

自動產生的aidl檔案如下:

// AidlInterface.aidlpackage com.example.tee.testapplication.aidl;// Declare any non-default types here with import statementsinterface 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的基礎類型以及List、Map等,如果是自訂類的話需要手動匯入,我們後面再說,先來最簡單的,建立一個 IMyAidlInterface.aidl檔案,修改如下:

package com.example.tee.testapplication.aidl;interface IMyAidlInterface { String getValue();}

在介面中定義一個getValue方法,返回一個字串,現在可以編譯一下工程,找到app/build/generated/source/aidl/debug目錄,在我們應用程式套件名下會發現產生了一個Interface類,名字跟我們定義的aidl的檔案名稱字一樣,這說明其實aidl檔案在最後還是會轉換成介面來實現,而且這個檔案不需要我們維護,在編譯後自動產生。

然後建立一個類繼承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類中定義一個內部類繼承IMyAidlInterface.Stub,並且重寫我們在aidl也就是在介面中定義的getValue方法,返回字串get value。

到了這裡,我們就建立好了這個服務端,作用是在調用後返回一個字串,最後在AndroidManifest檔案中聲明:

<service android:name=".MAIDLService" android:process=":remote"//加上這句的話用戶端調用會建立一個新的進程 android:exported="true"//預設就為true,可去掉,聲明是否可以遠程調用 > <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="com.example.tee.testapplication.aidl.IMyAidlInterface" /> </intent-filter></service>

android:process=":remote"這一行的作用是聲明是否調用時建立進程,接下來寫用戶端代碼,建立一個工程,將剛才建立的aidl檔案拷貝到這個工程中,注意同樣也是要放在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的傳入的參數字串是在manifest裡面自訂的action標籤,並且在onDestroy記得取消綁定服務。

執行結果就是我們在點擊TextView時會顯示服務端給我們返回的get value字串

自訂的對象

剛才我們使用的是基礎類型String,在使用我們自己定義的類的時候用上面的方法是不行的,用我們自訂的類需要手動匯入,修改剛才我們建立的作為服務端的工程

首先在開始產生的aidl包下(所有aidl相關的檔案都要放在這個包下)建立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); }}

需要實現Parcelable序列化介面,AndroidStudio會自動產生靜態內部類CREATOR和describeContents方法,這些部分我們都不需要修改,用自動產生的就好。然後重寫writeToParcel方法,自訂readFromParcel方法,注意這兩個方法裡面的屬性順序必須一致,一個是寫入,一個是讀取。在構造方法Student(Parcel in)中調用readFromParcel(in)方法。

接下來建立Student.aidl檔案(也是在aidl包中):

// Student.aidlpackage com.example.tee.testapplication.aidl;// Declare any non-default types here with import statementsparcelable Student;

注意這裡Student前面的關鍵字parcelable首字母是小寫哦,再修改IMyAidlInterface.aidl檔案如下:

// IMyAidlInterface.aidlpackage com.example.tee.testapplication.aidl;// Declare any non-default types here with import statementsimport com.example.tee.testapplication.aidl.Student;interface IMyAidlInterface { Student getStudent(); void setStudent(in Student student); String getValue();}

定義了兩個方法,一個是設定Student,一個是擷取Student,在setStudent這個方法注意參數在類型前面有個in關鍵字,在aidl裡參數分為in輸入,out輸出

現在在MAIDLService.java中重寫新加的兩個方法:

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(); }}

服務端代碼修改完畢,來到用戶端工程,同樣要把剛才的aidl包下的檔案拷貝覆蓋過來,保持兩邊一致,然後在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(); } }});

現在編譯工程,會發現工程會報錯,找不到類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'] } }}

也就是指定一下檔案目錄,現在再編譯就沒有問題了

總結

Android的IPC使用起來還是挺簡單的,AIDL檔案的文法也跟我們平時使用介面的時候很相似,但是它只支援基礎類型,只能引用AIDL檔案,需要使用自訂類的時候要稍微麻煩一點。

以上就是對Android IPC 進程通訊的資料整理,後續繼續補充相關資料謝謝大家對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.