# HotModule

这是Ratel热发模块，主要用于远程下发模块插件。我们之前使用xposed模块的时候，都是需要手动下载模块，然后手动安装模块，并在管理器中配置生效。这对于普通玩机用户来说，基本不影响用于体验。不过Ratel的主要场景偏向于B端，所以大多数情况存在很多手机，每台手机都有类似的配置流程，这会导致线下运维工作比较多。另一方面B端业务大多自有模块开发者，而且随着业务迭代模块逻辑经常发生变更。

总结起来需求如下：

1. 对于多台手机，安装相同的模块，并配置模块生效，启动app.
2. 对于某个业务，需要对多台手机更新模块，且保证每台手机模块版本号一致。
3. 正在启用的模块，由于开发人员写出了bug，部署到所有机器之后触发，然后需要晋级回退到老版本的模块，并且保证所有机器操作都一致(没有手机遗漏操作模块降级动作)

考虑Ratel框架B端需求偏向行，我们设计了热发模块功能，他主要解决上述三个需求问题。

## 基本概念
由于ratel需要考虑ratel用户管理、不同app管理、同一个app在不同手机上面作用不同等复杂维度隔离问题，我们在设计之前就需要考虑好插件加载的资源隔离。这也引出本功能下定义的各种基本概念，用于方便描述我们的需求。

### ratelApp
表示一个被ratel感染过的应用，一般来说是想要被我们通过模块控制的app，他可能加载多个插件。

### HotModule
我们为RatelApp编写的模块，它是一个基本的ratel模块，也是一个基本的Xposed模块，在此基础上做了更为深度定义，然后变成了Ratel的HotModle，主要增加三个特殊概念

### for_ratel_app
一个HotMoule仅仅可以作用在某个特定的ratelApp上。这个特定的ratelApp就是上面提到的ratelApp
### certificateId
ratel通过证书控制用户使用ratel产品的行为，所以certificate也作为我们区分ratel用户的标记，也就是说certificateId可以等价于用户ID。只要某个用户在ratel网站上面上传了我们颁发的某个证书，那么就会就会有权限控制这个证书所有签发的apk
(所以特别说明的一点，我们颁发的证书，用户尽量不要共享给其他用户，热发模块功能上线之后，基本上拿到你证书的人就有权利任意控制你在ratel系统下的app)

### group
如果你的手机分为各种不同的用处，但是他们部署的都是同一个app。那么通过group来区分。这也不同group下面的模块只会下发到对应的手机下面


## 使用

首先，热发插件就是普通的模块，所以依然可以正常安装在手机里面或者通过emble模式植入到apk中。在此基础上我们增加了刚刚描述的概念
```
       <meta-data
            android:name="xposedminversion"
            android:value="54" />

        <meta-data
            android:name="xposedmodule"
            android:value="true" />
        <meta-data
            android:name="for_ratel_apps"
            android:value="com.txxxt.mm" />
        <meta-data
            android:name="ratel_certificate_id"
            android:value="3c2c1260-c83e-4645-870f-19ca551f9c77" />
        <meta-data
            android:name="xposeddescription"
            android:value="first demo for ratel hot module" />
```
这里``for_ratel_apps=com.txxxt.mm``说明本模块指定作用在``com.txxxt.mm``这个apk上面。``ratel_certificate_id=3c2c1260-c83e-4645-870f-19ca551f9c77``说明这个模块针对于使用``3c2c1260-c83e-4645-870f-19ca551f9c77``这个证书的用户。

证书id在ratel网站后台可以查看到，group是可选值，正常情况下可以不填，不填写group含义为所有机器都会被下发。

模块编写好之后，通过ratel网站上传即可，并注意本模块被启用即可。app会在十分钟内下载最新的模块apk，并且重启app加载最新插件。

### faq
#### 关于模块升级
你需要修改Android构建文件中，apk的VersionCode,ratel服务器以最新版本的启用状态apk作为将要被加载的模块
#### 关于模块回滚
你只需要在网站启用某个特定版本的模块，然后同一个账户，同一个targetApp下面的所有其他模块都会被置为禁用状态
#### 关于group设定
你需要在构建app的时候，加入附加参数``ratel_properties_hot_module_group=theGroup``
#### 私有化部署下，如果修改RatelServer的URL地址?
在构建app的时候，加入附加参数:``ratel_properties_RATEL_SERVER_URL=http://ratel.virjar.com/``
#### 大文件模块
一半情况，尽量不要让模块大小大于10M，由于RatelEngine下载热发模块需要连接互联网，如果模块太大，那么可能存在不稳定性。同时如果模块文件大于10M，Engine会调用系统的DownloadManager，这在有些Rom上面会弹出流量下载提醒，可能会阻断系统自动化流程。模块大于10M的时候，且处于移动网络的时候，可能需要手动配置等待WLAN网络下载的设置。

#### 不同类型插件如果同时部署，会发生什么？
ratel系统存在三种类型插件，普通插件、embed插件、热发插件。插件依靠pkgName区分。任何时刻，如果三种插件任意多种同时配置，那么只会有一种生效，他们按照如下优先级: 热发插件 > 普通插件 > embed插件

原则为，插件加载优先级按照ratel工作生命周期逆序，即embed插件产生与apk构建时期，伴随ratelApp产生而产生。普通插件在RatelApp安装后安装生效。热发插件在RatelApp运行之后的任意时刻下发

### 注意事项
RatelEngine 1.3.7之后，所有ratel产生的apk都会启用热发模块功能