1. 程式人生 > >XIPC 一個Android通用的IPC(程序通訊)框架

XIPC 一個Android通用的IPC(程序通訊)框架

XIPC

xipc api

一個Android通用的IPC(程序通訊)框架。該專案主要是模仿餓了麼開源專案Hermes的設計進行的自我理解改寫。

關於我

github csdn

特徵

  • 支援自定義服務介面實現程序通訊,無需定義AIDL介面,所有IPC通訊就像呼叫本地函式一樣簡單。

  • 支援自定義介面服務(服務發現)、獲取單例和獲取工具類方法。

  • 支援程序通訊的介面回撥。

  • 支援介面回撥的執行緒控制。

  • 擁有垃圾回收機制,防止介面回撥記憶體洩漏。

  • 支援跨程序和跨應用通訊。

實現原理

該框架主要使用以下技術實現:

  • 註解反射

  • 動態代理

  • AIDL

  • 服務繫結

  • 程序間垃圾回收

詳細實現原理請點選檢視

演示(請star支援)

在這裡插入圖片描述

apk下載

遠端服務應用

呼叫服務應用

如何使用

1.先在專案根目錄的 build.gradle 的 repositories 新增:

allprojects {
     repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

2.然後在dependencies新增:

dependencies {
  ...
  implementation 'com.github.xuexiangjys:XIPC:1.0.1'
}

3.最後在Application中註冊介面服務:

XIPC.init(this);
XIPC.debug(BuildConfig.DEBUG);

//本地只需要註冊實現,無需註冊介面
XIPC.register(UserManager.class);
XIPC.register(LoadingTask.class);
XIPC.register(FileUtils.class);
XIPC.register(LoadingCallback.class);
XIPC.register(ComputeService.class);

//遠端註冊介面
//註冊包名下的所有定義的服務介面
XIPC.register("com.xuexiang.remotedemo.service");


如何實現跨應用通訊

1.介面定義和實現

(1)首先我們需要定義一套統一的互動介面。使用@ClassName@MethodName進行修飾。

@ClassName("ComputeService")
public interface IComputeService {
    /**
     * 計算
     * @param value1 值1
     * @param symbol 算數符號
     * @param value2 值2
     * @return
     */
    @MethodName("calculate")
    float calculate(float value1, String symbol, float value2);
}

(2)根據定義的介面,進行具體實現。使用@ClassName@MethodName進行修飾。這裡需要注意註解中的內容要和之前定義的介面一一對應。

@ClassName("ComputeService")
public class ComputeService implements IComputeService {
    @Override
    @MethodName("calculate")
    public float calculate(float value1, String symbol, float value2) {
        float result;
        switch(symbol) {
            case "+":
                result = value1 + value2;
                break;
            case "-":
                result = value1 - value2;
                break;
            case "*":
                result = value1 * value2;
                break;
            case "/":
                result = value1 / value2;
                break;
            default:
                result = value1 + value2;
                break;
        }
        return result;
    }
}

2.註冊

(1)註冊介面和實現類。對於呼叫App而言,只需要註冊介面即可;對於被呼叫App而言,只需要註冊實現類和回撥介面即可。統一在Application的onCreate中進行註冊。

//被呼叫App,無需註冊介面
XIPC.register(UserManager.class);
XIPC.register(LoadingTask.class);
XIPC.register(FileUtils.class);
XIPC.register(LoadingCallback.class);
XIPC.register(ComputeService.class);

//呼叫App,只需要註冊介面和回撥函式
XIPC.register("com.xuexiang.remotedemo.service");//該方法註冊包名下的所有定義的服務介面

(2)被呼叫App需在manifest中註冊IPC通訊服務。可以使用預設的IPCService0服務,也可以繼承IPCService進行自定義通訊服務。

<service
    android:name="com.xuexiang.xipc.core.channel.IPCService$IPCService0"
    android:process=":remote"
    android:exported="true" />

3.服務繫結

(1)在呼叫前,請先進行繫結,繫結IPC通訊服務。

XIPC.connectApp(getContext(), "com.xuexiang.xipcdemo"); //這裡設定的是被呼叫App的包名

(2)當然你也可以設定繫結的監聽回撥,以判斷服務繫結是否成功。

XIPC.setIPCListener(new IPCListener() {
        @Override
        public void onIPCConnected(Class<? extends IPCService> service) {
            ToastUtils.toast("IPC服務已繫結!");
        }
    });

4.獲取例項訪問

XIPC提供三種訪問的方式:

  • getService: 新建獲取一般定義的服務介面。

  • getInstance: 獲取單例。

  • getUtilityClass: 獲取工具類。

IComputeService computeService = XIPC.getService(IComputeService.class);
ToastUtils.toast("3*4=" + computeService.calculate(3 , "*", 4));

5.服務解綁

當不再需要服務訪問時,我們需要及時地進行服務解綁,回收資源。

XIPC.disconnect(getContext());

注意事項

在介面註冊方面

  • 如果兩個程序屬於兩個不同的app(分別叫App A和App B)。App A想訪問App B的一個類,並且App A的介面和App B的對應實現類有相同的包名和類名,那麼就沒有必要在類和介面上加@ClassName註解。但是要注意使用ProGuard後類名和包名仍要保持一致。

  • 如果介面和類裡面對應的方法有相同的名字,那麼也沒有必要在方法上加上@MethodName註解,同樣注意ProGuard的使用後接口內的方法名字必須仍然和類內的對應方法名字相同。

  • 如果介面和實現類中有任意一個使用了@ClassName@MethodName修飾,那麼另一個也一定要使用相同的@ClassName@MethodName修飾,否則將報錯。

  • 假設程序B需要訪問程序A, 如果程序A使用了@ClassName註解標識的類,那麼程序B也要對其對應的介面上加上相同的@ClassName註解,並且程序A在程序B訪問該介面之前,必須要註冊。 否則程序B使用XIPC.getService()XIPC.getInstance()XIPC.getUtilityClass()訪問程序A時,XIPC在程序A中找不到匹配的類。

  • 所有註冊的介面類不可以是匿名類和區域性類。

總之為了防止出現各種各樣不匹配或者找不到的問題,最好還是使用@ClassName@MethodName註解,進行一一對應修飾並在Application的onCreate中進行註冊。

在介面定義方面

  • 如果你不想讓一個類或者函式被其他程序訪問,可以在上面加上@WithinProcess註解。

  • 使用XIPC跨程序呼叫函式的時候,傳入引數的型別可以是原引數型別的子類,千萬注意不可以是匿名類和區域性類,但是回撥函式例外。

  • 在介面的引數方面,如果被呼叫的介面函式的引數型別和返回值型別是int、double等基本型別或者String、Object這樣的Java通用型別無需多餘操作。但是千萬注意,這裡目前不支援引數的型別是陣列。如果需要用到陣列作為引數,可以使用自定義物件去包一下陣列,再進行使用。

  • 對於介面引數型別是自定義的類,並且兩個程序分別屬於兩個不同app,那麼你必須在兩個app中都定義這個類,且必須保證程式碼混淆後,兩個類仍然有相同的包名和類名。不過你可以適用@ClassName@MethodName註解,這樣包名和類名在混淆後不同也不要緊了。

  • 如果被呼叫的函式有回撥引數,那麼函式定義中這個引數必須是一個介面,不能是抽象類。

在介面回撥方面

  • 需要特別注意回撥函式執行的執行緒。如果程序A呼叫程序B的函式,並且傳入一個回撥函式供程序B在程序A進行回撥操作,那麼預設這個回撥函式將執行在程序A的主執行緒(UI執行緒)。如果你不想讓回撥函式執行在主執行緒,那麼在介面宣告的函式的對應的回撥引數之前加上@Background註解。

  • 如果回撥函式有返回值的話,請使用@Background註解讓它執行在後臺執行緒。如果執行在主執行緒,那麼返回值始終為null。

  • 在回撥函式的引用方面,框架持有回撥函式的強引用,這個可能會導致記憶體洩漏。為了解決該問題,你可以在介面宣告的對應回撥引數前加上@WeakRef註解,這樣XIPC持有的就是回撥函式的弱引用。如果程序的回撥函式被回收了,而對方程序還在呼叫這個函式(對方程序並不會知道回撥函式被回收),這個不會有任何影響,也不會造成崩潰。如果回撥函式有返回值,那麼就返回null。

  • @Background@WeakRef註解,必須在介面中對應的函式引數前進行新增。如果加在其他地方,將不會有任何作用。

其他方面

  • 呼叫函式的時候,任何Context在另一個程序中都會變成對方程序的application context。

  • 介面引數的資料傳遞預設是基於Json的。

  • 在使用過程中,出現任何錯誤,都會有相關日誌記錄,你只需要執行XIPC.debug開啟除錯即可看見日誌。

混淆配置

# xipc
-keep @com.xuexiang.xipc.annotation.* class * {*;}
-keep class * {
    @com.xuexiang.xipc.annotation.* <fields>;
}
-keepclassmembers class * {
    @com.xuexiang.xipc.annotation.* <methods>;
}

特別感謝

https://github.com/Xiaofei-it/Hermes

聯絡方式


在這裡插入圖片描述