android 跨进程 android:process,ProcessRoute for Android 跨进程事件路由框架

ProcessRoute for Android 跨进程事件路由框架

用于解决安卓组件化下各组件间交叉通讯的问题

支持插件化和组件化(注意:插件化需要引导用户安装插件,介意的话可以无视插件化)

与ARoater不同的是,ProcessRoute是依托AIDL作为通讯纽带,以接口协议为中间件,采取事件机制进行通讯的框架

支持跨进程发送消息,且自由回调

通讯协议为Interface接口,可指定通讯进程、输入参数(数量最大10个)、回调参数

全程对象化传输,无需关注对象的序列化问题(前提:各组件共同依赖于模型包)

自动处理跨进程多线程异步问题

可跟踪通讯过程中及接口协议关联的独立组件执行过程中所有异常

无需配置,只需在各组件依赖的Common包引入即可集成

更新日志

2019-04-24

更新了processroute到1.0.15,修复了部分已知bug

2019-04-23

更新了hookgradle到1.0.2,修复了部分已知bug

2019-03-20

更新了processroute到1.0.13,新增了【组件化 转 插件化】解决方案

2019-03-19

更新了hookgradle插件,新增了组件化R非常量解决方案

2019-02-27

优化了错误日志的输出方式,可通过控制台看到错误信息

修复了部分已知bug

使用方式

【前提】

组件单独打包测试时,测试机请关闭链式启动的控制

您将各组件包括主工程均引用了一个公用库(下面统称:Common)

您将各组件包括主工程的模型均放入了引用的Common包中

您创建了一个组件名为Plug1,并以独立运行APK的方式配置好了

【Let`s start】

通过接口约束远程方法、请求参数、回调参数为双方共同遵守的协议

//在Common中新建一个接口协议RemoteServiceOfPlug1,可以对外曝光很多功能,这里已登录为例

//login:该方法名用于外部组件访问时识别其调用的功能

//String username / String password: 这是实现登录需要的参数,参数支持[0-10]个,类型不限(基本类型必须换成其包装类)

//CallbackProcessor callbackProcessor: 这是回调处理器,协议的所有方法都必须将该参数放置最前,是必输参数

//CallbackProcessor callbackProcessor: 用于约束回调的类型,类型不限

//void:协议无需返回参数,无论返回什么值均为无效,所有回调均使用CallbackProcessor处理

public interface RemoteServiceOfPlug1 {

/**

* 登录

* @param username 姓名

* @param password 密码

* @param callbackProcessor @String 回调返回token

*/

void login(CallbackProcessor callbackProcessor,String username, String password);

}

通过在组件内实现协议来与宿主的解耦

//在Plug1中新建一个接口协议RemoteServiceOfPlug1Impl实现RemoteServiceOfPlug1协议

//在这里你可以尽情的玩耍了

//callbackProcessor.callback(): 改方法用于回调,如果你需要在别的地方回调可将callbackProcessor传递过去而无需关心序列化问题

//"Hello!": 该参数与依赖,您必须使用相同的类型进行回调

public class RemoteServiceOfPlug1Impl implements RemoteServiceOfPlug1 {

@Override

public void login(CallbackProcessor callbackProcessor,String username, String password) {

System.out.print("username=>"+ username);

System.out.print("password=>"+ password);

callbackProcessor.callback("Hello!");

}

}

通过@ProcessId、RemoteServiceImpl搭建组件通讯桥梁

//我们需要对RemoteServiceOfPlug1设置依赖关系

//ProcessId: 用于指定该协议从属于哪个组件,注意是组件以Application方式编译时的ApplicationId

//RemoteServiceImpl: 用于指定该协议的实现类,需输入实现类的全路径

//RemoteServiceImpl: APT注解可自动生成方法RemoteServiceOfPlug1Impl.class(需要Make一下工程),在需要传方法名的地方建议使用该自动生成的类取值,以达到规范的目的

//ProcessId, RemoteServiceImpl:缺一不可。当然你也不用太担心,如果协议上有任何的地方有问题,框架都会在调用方回调错误信息以提示您

@ProcessId("com.demo.plug1")

@RemoteServiceImpl("com.demo.plug1.PlugRemoteService")

public interface RemoteServiceOfPlug1 {

/**

* 登录

* @param username 姓名

* @param password 密码

* @param callbackProcessor @String 回调返回token

*/

void login(CallbackProcessor callbackProcessor,String username, String password);

}

在Common包中的Application中注册

//我们需要在公共的Application中注册

... extends Application {

@Override

public void onCreate() {

super.onCreate();

//isModuleAsApk: 组件是否以独立APK编译(建议配置到gradle中)

ProcessRoute.ini(Application application, boolean isModuleAsApk);

}

}

简洁高效的使用协议进行组件间通讯

//假设您在某个组件中需要Plug1模块的登录功能,使用ProcessRoute发送一个进程事件消息即可

//context:上下文

//RemoteServiceOfPlug1Impl.login: APT生成的类,可直接访问协议类的login方法名

//"18800000000", "198123545masd": 与通讯协议的login功能中要求的参数一样,但必须确保参数数量、类型、顺序一致

//RouteListener(): 与通讯协议的login功能中要求的回调参数一样

//prepare(): 事件已发出但尚且没有回调

//callback(): 事件回调了,且成功带回需要的数据。注意:只有Plug1模块调用了callbackProcessor.callback()才会回调

//fail(): 事件回调了,但失败了。如Plug1未安装、连接失败、未遵守协议、Plug1的实现过程报错都会在这个方法中将详细错误信息带过来

RouteReq.create(RemoteServiceOfPlug1Impl.login, "18800000000", "198123545masd")

.routeListener(new RouteListener() {

//可选实现

@Override

public void prepare() {}

@Override

public void callback(String obj) {}

}).send()

【end】

进阶

1.实现各组件的Application共享

在Plug1模块中新建Plug1Application 并实现ApplicationDelegate协议,并添加RegistApplication注解,框架将自动将注册共享Application

@RegistApplication

public class Plug1Application implements ApplicationDelegate {

@Override

public void onCreate(Application application) {

}

@Override

public void onTerminate(Application application) {

}

}

在Common包中的Application中注册组件的ApplicationDelegate

public class BaseApplication extends Application {

public static Application application;

@Override

public void onCreate() {

super.onCreate();

ProcessRoute.ini(this, BuildConfig.isPlugMode);

ProcessRoute.onApplicationCreate();//必须先初始化后再调用

}

@Override

public void onTerminate() {

super.onTerminate();

ProcessRoute.onApplicationTerminate();

}

}

2.实现RemoteService的远程方法AOP编程

以会话拦截为例。在Plug1模块中新建LoginProcessor 并继承RemoteServiceProcessor协议

public class LoginProcessor extends RemoteServiceProcessor {

/**

* AOP处理器

* @param method 对应RemoteService的远程方法名

* @param callbackProcessor 对应RemoteService的callbackProcessor回调处理器,即您也可以在拦截器中回调数据

* @param params 对应RemoteService的远程方法参数

* @return 是否继续执行RemoteService的远程方法,返回false则被拦截

*/

@Override

public boolean process(Method method, CallbackProcessor callbackProcessor, Object... params) {

return true;

}

}

在Plug1模块的RemoteServiceOfPlug1远程协议实现类中,在需要拦截的远程方法中加入@Processor({LoginProcessor.class})即可实现拦截

public class RemoteServiceOfPlug1Impl implements RemoteServiceOfPlug1 {

@Processor({LoginProcessor.class})//AOP处理器支持多个,以","号隔开即可。如多个处理器中有1个返回false,则被拦截

@Override

public void login(CallbackProcessor callbackProcessor,String username, String password) {

System.out.print("username=>"+ username);

System.out.print("password=>"+ password);

callbackProcessor.callback("Hello!");

}

}

3.快捷部署组件化Moudule

在Project的classpath中去掉com.android.tools.build:gradle:x.x.x,替换为com.fanjun.hookgradle:1.0.3

dependencies {

//当前插件版本基于【classpath:gradle:3.2.0】 + 【gradle-wrapper.properties:gradle-4.6-all.zip】构建

classpath 'com.fanjun:hookgradle:1.0.3'

}

与原生gradle一样,通过apply plugin: 'com.android.application' 或 'com.android.library'切换组件运行模式

1.Module无需动态设置applicationId,建议像开发Application一样设置上applicationId(无需关注运行模式)

2.Module无需动态设置sourceSets.main.manifest.srcFile,插件会自动配置

3.Module无需再创建一个Manifest.xml文件用于适配运行模式,插件会自动生成并自动关联切换

4.Module默认的Manifest.xml将用于Application模式时加载,您可以像写Application一样的编写Manifest.xml文件

4.组件化Moudule的R文件非常量解决方案

在Project的classpath中去掉com.android.tools.build:gradle:x.x.x,替换为com.fanjun.hookgradle:1.0.3

dependencies {

//当前插件版本基于【classpath:gradle:3.2.0】 + 【gradle-wrapper.properties:gradle-4.6-all.zip】构建

classpath 'com.fanjun:hookgradle:1.0.3'

}

在组件化Moudule的build.gradle文件中 apply plugin: 'com.fanjun.autor'

apply plugin: 'com.fanjun.autor'

android {

//...

}

在所有类的外部访问R文件资源id的地方使用R_访问(如 R_.layout.activity_main ),类的内部随您的喜好。(请忽略EActivity注解,这只是用于举例)

@EActivity(R_.layout.activity_ba)

public class BActivity extends Activity {

}

与原生R文件一样,插件生成的 R_ 文件会实时同步最新的id信息,并自动根据组件运行模式读取Moudule的R或者宿主的R

您无需关注R_文件的生成情况,即无需clean、build、sync等操作

注意1:当您的Moudule以Library运行时,插件默认认为它的宿主Moudule的名称为app(切记切记!!!)

注意2:您的组件Moudule的名字不要以a或A开头

5.组件化 转 插件化的解决方案

在你的需要以插件打包的组件Moudule的Manifest文件中,使用以下activity作为入口应用入口Activity

tools:ignore="AppLinkUrlError"/>

这样设置后打包成APK即可作为宿主的插件使用

1.在开发阶段你可以暂时屏蔽这段代码,使用你期望的那个activity作为启动页面,但是在打包成插件APK时一定要改回来

2.该方案是类似支付宝安装指纹支付插件的方式,用户需要像安装普通应用一般的安装你的插件,但是该插件并不会用户的手机桌面上显示图标

3.该方案的通讯机制与组件化一模一样,您无需担心切换后产生通讯问题

4.框架已绕过AIDL通讯引发手机的反链式启动程序的限制,可以自由自在的进行通讯

混淆方式

-keepattributes Signature

-keepattributes *Annotation*

-keep class sun.misc.Unsafe { *; }

-keep class com.google.gson.stream.** { *; }

-keep class com.google.gson.examples.android.model.** { *; }

-keep class com.google.gson.* { *;}

-dontwarn com.google.gson.**

-keepclassmembers class * {

public (org.json.JSONObject);

}

-keep class **.R_$* {

*;

}

-keep @com.fanjun.processroute.annotation.RemoteServiceImpl class * {*;}

-keepnames class com.fanjun.processroute.apt.** { *; }

-keepnames class * implements com.fanjun.processroute.application.ApplicationDelegate { *; }

-keep public class * extends com.fanjun.processroute.processors.RemoteServiceProcessor { *; }

依赖

Gradle 在各个组件中引入processroute框架及配套的annotationProcessor处理器

implementation 'com.fanjun:processroute:1.0.15'

annotationProcessor 'com.fanjun:processroutecompiler:1.0.6'

联系我

我的博客:https://blog.csdn.net/qwe112113215

我的邮箱:810343451@qq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值