最近使用Android studio開發的時候,須要用到系統類,導入jar包能夠解決該問題,但因爲該應用須要作到平臺兼容,導入jar包的方式會顯得APP很臃腫。最後考慮使用AIDL方式,APP端做爲客戶端,系統源碼實現服務端。java
AIDL是一個縮寫,全稱是Android Interface Definition Language(Android接口定義語言)。主要用於進程間通訊。下面詳細說說服務端和客戶端該如何建立AIDL,並讓兩個進程進行通信。android
這裏服務端是在系統源碼中實現,網上查找資料,都說先建立一個AIDL文件,而後在Android.mk文件中添加AIDL文件的編譯,就會生成一個對應的Java文件。折騰了好久,都沒生出一個Java文件,坑。 若是沒有Java文件生成,則本身建立一個便可,下面說說操做。微信
AIDL接口,須要有一個AIDL文件進行描述說明,說明服務端支持什麼樣的接口。AIDL的接口樣式以下:app
//ITestService.aidl
package com.xxx.yyy;
interface ITestService {
boolean write(String str);
String read();
}
複製代碼
這裏的AIDL文件,引用的包名爲服務端所在的進程包名。框架
Android.mk文件中爲整個進程的編譯規則,這裏添加了AIDL文件後,須要將AIDL文件添加進去,不然會編譯失敗,增長以下語句便可:ide
LOCAL_SRC_FILES += $(call all-Iaidl-files-under, src)
複製代碼
這裏表示編譯AIDL文件。post
既然不能生成AIDL相應的Java文件,那咱們就要本身去建立Java文件。Java文件的建立內容以下:spa
//TestService.java
package com.xxx.yyy;
import android.content.Context;
import android.content.IntentFilter;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class TestService extends Service {
static private final String TAG = "TestService";
@Override
public void onCreate() {
super.onCreate();
}
ITestService.Stub mBinder = new ITestService.Stub() {
@Override
public boolean write(String str) throws RemoteException {
return false;
}
@Override
public String read() throws RemoteException {
return null;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
複製代碼
添加服務端的AIDL和Java文件後,還須要註冊服務,在Androidmanifest.xml文件中註冊以下:3d
<service android:name=".TestService"
android:process=":remote"
android:exported="true">
<intent-filter>
<action android:name="com.xxx.yyy.TestService"/>
</intent-filter>
</service>
複製代碼
到這裏,服務端的工做就完成了。code
客戶端是用AS開發的,因此咱們須要在AS中也建立一個AIDL文件,否則AS沒接口可調用。這裏直接將服務端的AIDL文件拷貝過來便可。這裏要特別注意的是,AIDL文件的路徑。若是路徑不匹配,AS就會編譯錯誤。這裏說的路徑匹配,是指AIDL文件中,AIDL文件所在的文件路徑要符合AIDL文件引用的包名。這裏結合本例說明。先放上AIDL文件的路徑:
as_project/src/main/aidl/com/xxx/yyy/ITestService.aidl
複製代碼
首先先在main目錄下,建立一個aidl的文件夾,接下來的目錄級別就是跟隨着AIDL文件中的包名來了:
package com.xxx.yyy;
複製代碼
拷貝AIDL文件後,接下來就是客戶端綁定服務,使用服務端的接口。先貼上代碼:
import com.xxx.yyy.ITestService;
static private ITestService mTestService;
static private ServiceConnection mCon;
void init(Context context) {
mCon = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mTestService = ITestService.Stub.asInterface((IBinder) service);
Log.d(TAG,"onServiceConnected! ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"onServiceDisconnected! ");
}
};
Intent intent = new Intent();
intent.setPackage("com.xxx.yyy");
Boolean res = context.bindService(intent, mCon, Context.BIND_AUTO_CREATE);
}
複製代碼
init方法放在activity的onCreate方法中調用便可。
這裏須要注意的地方有兩點:
1.bindservice的時候,傳入的intent須要setpackage,這個package名爲服務端的包名,不然bindservice的時候會返回false。
2.bindservice成功後,onServiceConnected不是立刻回調,會延遲,因此綁定成功後,須要等待onServiceConnected成功回調後,再去調用服務端的接口,不然你會看到報空異常。
try {
boolean res = mTestService.write(str);
}catch (Exception e) {
e.printStackTrace();
}
複製代碼
AIDL的實現到此結束。
若是文章存在錯誤描述,可直接留言,一塊兒探討!
我在微信公衆號也有寫文章,更新比較及時,有興趣者能夠關注以下公衆號!