對於AIDL的一些使用:最基礎使用、稍高級使用、......java
<!--more-->android
此章節可能和本文沒有太大關係,瞭解一下便可git
基本開發流程:先開發Service端,後開發Client端github
使用AndroidStudio建立AidlDemo工程後,再在裏面建立Service Module和Client Module,不用管默認的app Modulebash
分支:feature/aidl_baseapp
包名:com.fqxyi.aidlserviceide
一、建立aidl文件,如:IAidlBinder.aidl
,新增接口,如:String getInfo();
函數
二、檢查build/generated/source/aidl/debug
下是否存在對應的java文件,若無則Rebuild Project
,若出現錯誤,請查看#FAQ章節ui
三、建立繼承於android.app.Service的Service類,如:AidlService.java
,並實現必需要實現的onBind方法this
3.一、在AndroidManifest.xml文件中靜態註冊Service,詳細註冊代碼以下:
<!-- exported表示是否支持其它應用調用當前組件 --> <!-- process表示將組建運行到單獨的進程中 --> <!-- action用於用於過濾識別其餘的Intent --> <service android:name=".AidlService" android:exported="true" android:process=":Remote"> <intent-filter> <action android:name="com.fqxyi.aidlservice.remote"/> </intent-filter> </service>
四、接着咱們回到AidlService.java文件,onBind方法須要咱們返回一個IBinder對象。顯然,到目前爲止可以獲得IBinder對象的類只有經過IAidlBinder.aidl自動生成的IAidlBinder.java類。
因爲默認代碼格式很亂,因此爲了方便查看,咱們可使用快捷鍵格式化一下代碼:Ctrl(Command)+Alt(Option)+L
仔細閱讀代碼發現,咱們想要獲得的IBinder對象是經過asBinder()方法返回的,因此接下來咱們只須要返回一個IAidlBinder.Stub的對象就能夠了。
五、實例化IAidlBinder.Stub的對象以後,咱們能夠處理咱們自定義的方法getInfo(),好比最簡單的就是返回一串字符串:return "I'm a Server";
包名:com.fqxyi.aidlclient
一、將Service端的aidl文件,拷貝到main文件夾下,須要注意的是aidl文件的包名仍是Service端的包名,具體目錄結構以下:
aidlclient |--src |--main |--aidl |--com.fqxyi.aidlservice // Service端的包名 |--IAidlBinder.aidl
二、檢查build/generated/source/aidl/debug
下是否存在對應的java文件,若無則Rebuild Project
,若出現錯誤,請查看#FAQ章節
三、建立Intent對象並實例化,接着配置在Service端配置的action
,實現Service的綁定,具體代碼以下因此:
Intent intent = new Intent(); intent.setAction("com.fqxyi.aidlservice.remote"); intent.setPackage("com.fqxyi.aidlservice"); bindService(intent, conn, Context.BIND_AUTO_CREATE);
四、上述代碼因不存在ServiceConnection而報錯,因此很簡單,咱們須要建立一個ServiceConnection對象並實例化,接着在必需要實現的onServiceConnected(ComponentName name, IBinder service)方法中初始化IAidlBinder
,在onServiceDisconnected(ComponentName name)方法中將IAidlBinder置爲null
。
仔細閱讀IAidlBinder.java代碼發現,咱們想要獲得的IAidlBinder對象是經過asInterface(android.os.IBinder obj)方法返回的,須要傳入一個IBinder對象,因此接下來就很簡單了,只須要以下代碼便可:
IAidlBinder.Stub.asInterface(service);
五、最後咱們只須要經過第4步獲得的IAidlBinder對象,調用getInfo()方法,就能夠獲得內容。
分支:feature/aidl_advanced
此處文檔說明基於#開發流程-最基礎使用章節,經過列出不一樣點進行說明。
包名:com.fqxyi.aidlservice
一、建立aidl文件,如:IAidlBinder.aidl
,新增接口,如:String getInfo();
和Student getStudentInfo();
須要注意的是Student是咱們本身定義的一個實現了Parcelable接口的Model類,在aidl文件中定義接口,須要咱們手動import語句,添加引用。
二、建立Student類,具體代碼以下所示:
package com.fqxyi.aidlservice.model; import android.os.Parcel; import android.os.Parcelable; /** * Created by qingfeng on 2017/7/27. */ public class Student implements Parcelable { private String name; private int 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; } protected Student(Parcel in) { this.name = in.readString(); this.age = in.readInt(); } 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.writeString(name); dest.writeInt(age); } }
你們若是不深究、只考慮使用的話,不用擔憂本身會不會寫這些代碼,由於主要代碼是自動生成
的。
咱們只須要定義一個name和age屬性,而後執行如下兩部操做就好了:
三、建立Student.aidl文件,聲明Student實現了Parcelable接口,具體代碼以下所示:
// Student.aidl package com.fqxyi.aidlservice.model; // Declare any non-default types here with import statements import com.fqxyi.aidlservice.model.Student; parcelable Student;
四、檢查build/generated/source/aidl/debug
下是否存在對應的java文件,若無則Rebuild Project
,若出現錯誤,請查看#FAQ章節
三、建立繼承於android.app.Service的Service類,如:AidlService.java
,並實現必需要實現的onBind方法
3.一、在AndroidManifest.xml文件中靜態註冊Service,詳細註冊代碼以下:
<!-- exported表示是否支持其它應用調用當前組件 --> <!-- process表示將組建運行到單獨的進程中 --> <!-- action用於用於過濾識別其餘的Intent --> <service android:name=".AidlService" android:exported="true" android:process=":Remote"> <intent-filter> <action android:name="com.fqxyi.aidlservice.remote"/> </intent-filter> </service>
四、接着咱們回到AidlService.java文件,onBind方法須要咱們返回一個IBinder對象。顯然,到目前爲止可以獲得IBinder對象的類只有經過IAidlBinder.aidl自動生成的IAidlBinder.java類。
因爲默認代碼格式很亂,因此爲了方便查看,咱們可使用快捷鍵格式化一下代碼:Ctrl(Command)+Alt(Option)+L
仔細閱讀代碼發現,咱們想要獲得的IBinder對象是經過asBinder()方法返回的,因此接下來咱們只須要返回一個IAidlBinder.Stub的對象就能夠了。
五、實例化IAidlBinder.Stub的對象以後,咱們能夠處理咱們自定義的方法getInfo(),好比最簡單的就是返回一串字符串:return "I'm a Server";
若是咱們想要處理getStudentInfo()方法的話,能夠在onCreate()方法中進行初始化賦值操做,而後在getStudentInfo()方法中直接return便可。
包名:com.fqxyi.aidlclient
一、將Service端的aidl文件、和須要調用的文件,如:Student.java
,拷貝到main文件夾下,須要注意的是這些文件的包名仍是Service端的包名,具體目錄結構以下:
aidlclient |--src |--main |--aidl |--com.fqxyi.aidlservice // Service端的包名 |--model |--Student.aidl |--IAidlBinder.aidl |--java |--com.fqxyi.aidlservice // Service端的包名 |--model |--Student.java
二、檢查build/generated/source/aidl/debug
下是否存在對應的java文件,若無則Rebuild Project
,若出現錯誤,請查看#FAQ章節
三、建立Intent對象並實例化,接着配置在Service端配置的action
,實現Service的綁定,具體代碼以下因此:
Intent intent = new Intent(); intent.setAction("com.fqxyi.aidlservice.remote"); intent.setPackage("com.fqxyi.aidlservice"); bindService(intent, conn, Context.BIND_AUTO_CREATE);
四、上述代碼因不存在ServiceConnection而報錯,因此很簡單,咱們須要建立一個ServiceConnection對象並實例化,接着在必需要實現的onServiceConnected(ComponentName name, IBinder service)方法中初始化IAidlBinder
,在onServiceDisconnected(ComponentName name)方法中將IAidlBinder置爲null
。
仔細閱讀IAidlBinder.java代碼發現,咱們想要獲得的IAidlBinder對象是經過asInterface(android.os.IBinder obj)方法返回的,須要傳入一個IBinder對象,因此接下來就很簡單了,只須要以下代碼便可:
IAidlBinder.Stub.asInterface(service);
五、最後咱們只須要經過第4步獲得的IAidlBinder對象,調用getInfo()方法,就能夠獲得內容,也能夠調用getStudentInfo()方法,得到Student對象。
Error:Execution failed for task ':aidlservice:compileDebugAidl'. > java.lang.RuntimeException: com.android.ide.common.process.ProcessException: Error while executing process /qingfeng/work/sdk/build-tools/25.0.2/aidl with arguments {-p/qingfeng/work/sdk/platforms/android-25/framework.aidl -o/qingfeng/data/openSource/AidlDemo/aidlservice/build/generated/source/aidl/debug -I/qingfeng/data/openSource/AidlDemo/aidlservice/src/main/aidl -I/qingfeng/data/openSource/AidlDemo/aidlservice/src/debug/aidl -I/Users/qingfeng/.android/build-cache/92fb7eb4401d63eb124015b36c2a8a534302f1c9/output/aidl -d/var/folders/tq/f6kngw516g15xs24gdh80qvh0000gn/T/aidl1446680322459273337.d /qingfeng/data/openSource/AidlDemo/aidlservice/src/main/aidl/com/fqxyi/aidlservice/IAidlBinder.aidl}
出現此類問題,實際上是由於你的aidl文件編寫錯誤,請仔細檢查:
FATAL EXCEPTION: main Process: com.fqxyi.aidlclient, PID: 19282 java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.fqxyi.aidlservice.remote } at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1219) at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1318) at android.app.ContextImpl.bindService(ContextImpl.java:1296) ...
若是你使用的Android設備的版本大於5.0,則須要在bindService的時候,爲你的intent添加如下語句:
intent.setPackage("com.fqxyi.aidlservice");
什麼?
代碼太多?
做者寫的太爛?看的頭昏腦漲...
不要緊,直接去看源碼就好了,記住:
最基礎使用分支:feature/aidl_base,傳送門
稍高級使用分支:feature/aidl_advanced,傳送門