Android studio使用系統源碼的AIDL接口

前言

最近使用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文件進行描述說明,說明服務端支持什麼樣的接口。AIDL的接口樣式以下:app

//ITestService.aidl
package com.xxx.yyy;
interface ITestService {
    boolean write(String str);
    String read();
}
複製代碼

這裏的AIDL文件,引用的包名爲服務端所在的進程包名。框架

Android.mk文件中引用AIDL文件

Android.mk文件中爲整個進程的編譯規則,這裏添加了AIDL文件後,須要將AIDL文件添加進去,不然會編譯失敗,增長以下語句便可:ide

LOCAL_SRC_FILES += $(call all-Iaidl-files-under, src)
複製代碼

這裏表示編譯AIDL文件。post

建立AIDL相應的Java文件

既然不能生成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;
    }
}
複製代碼

Androidmanifest.xml註冊服務

添加服務端的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的實現到此結束。

互動

若是文章存在錯誤描述,可直接留言,一塊兒探討!

可能感興趣的文章

Android系統框架

關於Android狀態欄高度爲0仍顯示的問題

踩坑之NavigationBar 的隱藏與否

最後

我在微信公衆號也有寫文章,更新比較及時,有興趣者能夠關注以下公衆號!

相關文章
相關標籤/搜索