跨進(jìn)程間如何進(jìn)行AIDL IPC 通信(四)

在前三篇博客中,我們介紹了如何進(jìn)行AIDL IPC通信,代碼設(shè)計(jì)及AIDL數(shù)據(jù)傳輸?shù)念愋汀T诘谝黄┛痛a設(shè)計(jì)中,我們?cè)f(shuō)過(guò),需要將AIDL接口文件及對(duì)應(yīng)生成的Java文件要原封不動(dòng)拷貝到客戶端,這樣客戶端才能正常編譯執(zhí)行,但是這樣操作非常麻煩且不合理,所以今天我們將要介紹如何將AIDL接口文件及對(duì)應(yīng)生成的Java文件生成Jar包庫(kù),直接丟給第三方客戶端使用。嚴(yán)格意義上說(shuō),這篇博客不屬于AIDL IPC通信的范疇,但為了使整個(gè)AIDL IPC通信設(shè)計(jì)的連續(xù)性,我還是決定將其放到這里。同樣以前面的工程為例:

1. 創(chuàng)建Module

創(chuàng)建Module其實(shí)就是為了創(chuàng)建android lib庫(kù)。由于我們的AIDL接口是在service端設(shè)計(jì)的,且由service端對(duì)外提供,因此我們選擇在service端工程創(chuàng)建這個(gè)module.
點(diǎn)擊File菜單,New --> New Module --> Android Library,輸入要?jiǎng)?chuàng)建的Module Name等信息。創(chuàng)建成功后會(huì)在我們的工程中多了個(gè)module目錄結(jié)構(gòu),如圖1所示。


圖1

2. 新建AIDL接口

右擊Module Java包文件夾,新建IAidlJarTest.aidl接口,隨便寫(xiě)個(gè)接口函數(shù)

package tech.onroad.aidljar;
interface IAidlJarTest {
    void add(int a, int b);
}

重新編譯,同樣會(huì)在如下目錄生成對(duì)應(yīng)的Java文件,如圖2所示


圖2

3. 添加引用module編譯

在app module的build.gradle文件dependencies中添加一行compile project(':aidljar'),使得app module依賴我們的AidlJar module。

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    compile project(':aidljar')
}

這樣就可以在app module中調(diào)用剛才的IAidlJarTest.aidl的接口了。

4. 新建一個(gè)Service來(lái)實(shí)現(xiàn)aidl接口

具體如何創(chuàng)建Service及實(shí)現(xiàn)接口方法請(qǐng)參考《跨進(jìn)程間如何進(jìn)行AIDL IPC 通信(一)》第一節(jié)。
創(chuàng)建AidlJarService并實(shí)現(xiàn)add()接口,代碼如下:

public class AidlJarService extends Service {
    public final String TAG = "AidlJarService";
    public AidlJarService() {
    }

    private IAidlJarTest.Stub mBinder = new IAidlJarTest.Stub() {

        @Override
        public void add(int a, int b) throws RemoteException {
            Log.d(TAG, "Add result: " + (a + b));
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
    }
}

還有別忘了在AndroidManifest.xml注冊(cè)該service.

<service
    android:name=".service.AidlJarService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="tech.onroad.aidlservicedemo.aidljarservice" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

5. 編寫(xiě)生成Jar包腳本

劃重點(diǎn)了^^
在Module aidljar的build.gradle加入如下腳本:

task makeAidlJar(type: Copy) {
    //delete exist jar library
    delete 'build/libs/aidltest.jar'
    //copy from file path
    from('build/intermediates/bundles/release/')
    //to dist file path
    into('build/libs/')
    include('classes.jar')
    rename ('classes.jar', 'aidltest.jar')
}

makeAidlJar.dependsOn(build)

然后在AS的Terminal執(zhí)行命令:gradlew makeAidlJar
BUILD SUCCESSFUL 后就會(huì)生成aidltest.jar
如下圖3所示


圖3

至此Service端和Jar library都已生成成功。接下來(lái)我們將嘗試一下在client端引用這個(gè)jar包,看能不能正常調(diào)用。

6. 在client端引入該jar包庫(kù)

將service端生成的aidltest.jar復(fù)制到AidlClientDemo工程中的app/libs/目錄下,如圖4所示


圖4

右擊aidltest.jar,選擇Add As Library...
接下來(lái)我們就可以正常調(diào)用該庫(kù)的接口了。

7. 調(diào)用jar包庫(kù)的接口

為了方便,我直接在client端工程MainActivity.java修改. 具體步驟可參考《跨進(jìn)程間如何進(jìn)行AIDL IPC 通信(一)》的第二節(jié),編碼完成后如下

private IAidlJarTest mIAidlJarTest;
ServiceConnection aidlServiceconn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        mIAidlJarTest = IAidlJarTest.Stub.asInterface(iBinder);
        try {
            mIAidlJarTest.add(8, 8);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        mIAidlJarTest = null;
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent mServiceIntent = new Intent();
    //mServiceIntent.setAction("tech.onroad.aidlservicedemo.onroadservice");
    //mServiceIntent.setPackage("tech.onroad.aidlserverdemo");
    //bindService(mServiceIntent, conn, Context.BIND_AUTO_CREATE);

    //Test aidl jar service
    mServiceIntent.setAction("tech.onroad.aidlservicedemo.aidljarservice");
    mServiceIntent.setPackage("tech.onroad.aidlserverdemo");
    bindService(mServiceIntent, aidlServiceconn, Context.BIND_AUTO_CREATE);
}

8. 測(cè)試運(yùn)行

將兩個(gè)apk push到模擬器運(yùn)行,Log 控制臺(tái)輸入如下log


圖5

運(yùn)行結(jié)果與我們預(yù)期一致,說(shuō)明Client成功調(diào)用aidltest.jar的接口。

完整代碼可到我的github下載:

https://github.com/onroadtech/AidlDemo

-----完-----

更多博文可訪問(wèn)我的個(gè)人網(wǎng)站:www.onroad.tech
歡迎指定,共同進(jìn)步,指定郵箱:onroad_tech@163.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2、Andro...
    隔壁老李頭閱讀 10,828評(píng)論 13 43
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,284評(píng)論 25 708
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評(píng)論 18 139
  • AIDL是Android跨進(jìn)程間的一種非常重要的IPC通信機(jī)制,今天我們將來(lái)詳細(xì)講述如何不同app之間如何進(jìn)行AI...
    onroad_tech閱讀 600評(píng)論 0 1
  • 《詩(shī)經(jīng)》里有很多“征夫淚”和“相思情”,我對(duì)《王風(fēng) 小雅 君子于役》印象很深,腦海里一直浮現(xiàn)這樣的畫(huà)面:落日西山,...
    采之言閱讀 942評(píng)論 0 2