編程學(xué)習(xí)網(wǎng) > 服務(wù)器 > Linux > Android開(kāi)源:AndLinker-Android 上的 IPC 庫(kù)
2018
03-19

Android開(kāi)源:AndLinker-Android 上的 IPC 庫(kù)

簡(jiǎn)介

AndLinker是一款A(yù)ndroid上的IPC (進(jìn)程間通信) 庫(kù),結(jié)合了 AIDLRetrofit 的諸多特性,且可以與 RxJavaRxJava2 的Call Adapters無(wú)縫結(jié)合使用。項(xiàng)目的設(shè)計(jì)與部分代碼參考了偉大的 Retrofit 項(xiàng)目。

配置

在項(xiàng)目根目錄的 build.gradle 中添加 jcenter() 倉(cāng)庫(kù)

allprojects {
    repositories {
        jcenter()
    }
}

在App的 build.gradle 中添加如下依賴

dependencies {
    implementation 'com.codezjx.library:andlinker:0.7.0'
}

功能特性

  • 以普通Java接口代替AIDL接口
  • Retrofit 一樣生成遠(yuǎn)程服務(wù)接口的IPC實(shí)現(xiàn)
  • 支持的Call Adapters: Call , RxJava Observable , RxJava2 Observable & Flowable
  • 支持遠(yuǎn)程服務(wù)回調(diào)機(jī)制
  • 支持AIDL的所有數(shù)據(jù)類型
  • 支持AIDL的所有數(shù)據(jù)定向tag: in , out , inout
  • 支持AIDL的 oneway 關(guān)鍵字

快速開(kāi)始

使用注解 @ClassName 和 @MethodName 修飾遠(yuǎn)程服務(wù)接口 IRemoteService ,并實(shí)現(xiàn)它

@ClassName("com.example.andlinker.IRemoteService")
public interface IRemoteService {

    @MethodName("getPid")
    int getPid();

    @MethodName("basicTypes")
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

private final IRemoteService mRemoteService = new IRemoteService() {
    
    @Override
    public int getPid() {
        return android.os.Process.myPid();
    }

    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean,
        float aFloat, double aDouble, String aString) {
        // Does something
    }
};

在服務(wù)端App中,創(chuàng)建 AndLinkerBinder 對(duì)象,并注冊(cè)上面的接口實(shí)現(xiàn)。然后在 onBind() 方法中返回,暴露給客戶端

private AndLinkerBinder mLinkerBinder;

public class RemoteService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        mLinkerBinder = AndLinkerBinder.Factory.newBinder();
        mLinkerBinder.registerObject(mRemoteService);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mLinkerBinder;
    }
}

在客戶端App中,通過(guò) Builder 創(chuàng)建 AndLinker 對(duì)象,并通過(guò) create() 方法生成一個(gè) IRemoteService 遠(yuǎn)程接口的IPC實(shí)現(xiàn)

public class BindingActivity extends Activity {

    private AndLinker mLinker;
    private IRemoteService mRemoteService;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLinker = new AndLinker.Builder(this)
                .packageName("com.example.andlinker")
                .action("com.example.andlinker.REMOTE_SERVICE_ACTION")
                .build();
        mLinker.bind();

        mRemoteService = mLinker.create(IRemoteService.class);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLinker.unbind();
    }
}

一切就緒,現(xiàn)在 mRemoteService 對(duì)象中的所有方法都是IPC方法,直接調(diào)用即可

int pid = mRemoteService.getPid();
mRemoteService.basicTypes(1, 2L, true, 3.0f, 4.0d, "str");

支持?jǐn)?shù)據(jù)類型

AndLinker支持AIDL所有數(shù)據(jù)類型:

  • Java語(yǔ)言中的所有原始類型 (如: int , long , char , boolean ,等等)
  • String
  • CharSequence
  • Parcelable
  • List (List中的所有元素必須是此列表中支持的數(shù)據(jù)類型)
  • Map (Map中的所有元素必須是此列表中支持的數(shù)據(jù)類型)

進(jìn)階使用

Call Adapters

在客戶端App中,你可以copy并修改遠(yuǎn)程服務(wù)接口,包裝方法的返回值

@ClassName("com.example.andlinker.IRemoteService")
public interface IRemoteService {

    @MethodName("getPid")
    Observable<Integer> getPid();

    @MethodName("basicTypes")
    Call<Void> basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 
        double aDouble, String aString);
}

在 AndLinker.Builder 中注冊(cè)對(duì)應(yīng)的Call Adapter Factory,剩下的步驟基本和 Retrofit 一致,不再贅述

new AndLinker.Builder(this)
        ...
        .addCallAdapterFactory(OriginalCallAdapterFactory.create()) // Basic
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  // RxJava2
        .build();

處理遠(yuǎn)程服務(wù)接口回調(diào)

使用 @ClassName 和 @MethodName 注解修飾遠(yuǎn)程服務(wù)回調(diào)接口 IRemoteCallback

@ClassName("com.example.andlinker.IRemoteCallback")
public interface IRemoteCallback {

    @MethodName("onValueChange")
    void onValueChange(int value);
}

在遠(yuǎn)程方法中使用 @Callback 注解修飾callback參數(shù)

@MethodName("registerCallback")
void registerCallback(@Callback IRemoteCallback callback);

在客戶端App中,實(shí)現(xiàn)上面定義的遠(yuǎn)程服務(wù)回調(diào)接口 IRemoteCallback ,并且注冊(cè)到 AndLinker 中,就是這么簡(jiǎn)單

private final IRemoteCallback mRemoteCallback = new IRemoteCallback() {
    @Override
    public void onValueChange(int value) {
        // Invoke when server side callback
    }
};
mLinker.registerObject(mRemoteCallback);

指定數(shù)據(jù)定向tag

你可以為遠(yuǎn)程方法的參數(shù)指定 @In , @Out ,或者 @Inout 注解,它標(biāo)記了數(shù)據(jù)在底層Binder中的流向,跟AIDL中的用法一致

@MethodName("directionalParamMethod")
void directionalParamMethod(@In KeyEvent event, @Out int[] arr, @Inout Rect rect);

注意:

  • 所有非原始類型必須指定數(shù)據(jù)定向tag: @In , @Out ,或者 @Inout ,用來(lái)標(biāo)記數(shù)據(jù)的流向。原始類型默認(rèn)是 @In 類型,并且不能指定其他值。
  • 使用 @Out 或者 @Inout 修飾的Parcelable參數(shù)必須實(shí)現(xiàn) SuperParcelable 接口,否則你必須手動(dòng)添加此方法 public void readFromParcel(Parcel in) 。

使用 @OneWay 注解

你可以在遠(yuǎn)程方法上使用 @OneWay 注解,這會(huì)修改遠(yuǎn)程方法調(diào)用的行為。當(dāng)使用它時(shí),遠(yuǎn)程方法調(diào)用不會(huì)堵塞,它只是簡(jiǎn)單的發(fā)送數(shù)據(jù)并立即返回,跟AIDL中的用法一致

@MethodName("onewayMethod")
@OneWay
void onewayMethod(String msg);

反饋

歡迎各位提issues和PRs!

License

Copyright 2018 codezjx <code.zjx@gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

 

 

掃碼二維碼 獲取免費(fèi)視頻學(xué)習(xí)資料

Python編程學(xué)習(xí)

查 看2022高級(jí)編程視頻教程免費(fèi)獲取