-
前言
做久了App就知道一锅熟大杂烩不好受,所以就探索了一下最简易稳固的方式,将内容剥离主程序。
-
问题
- 疑问:现在的插件化框架那么多为什么还要存在利用无图标App这种低级方式?
这个都明白插件化框架干的什么,好像插件化技术分几个方向:代理,占坑,钩子具体没了解,但是我知道这些毕竟犹如入侵技术不是一个万全之策,而且其稳定性、各家的使用规则性、安全性都不可控,还经常受谷歌政策的影响,如果要做一款稳定多的、安全性可控的、开发方式遵循谷歌爸爸的,那就这种非常实用,譬如公家的项目,最近也发现鲁大师的VR检测模块也是这个路子。 - 疑问:主App死亡,子App在快照内存中运行存在,万一点击内存快照会不会直接唤起子App?
解:原计划子模块App监测主App是否运行,不运行则弹窗拒绝开启并自杀,清理快照,后来发现清理快照不可为;但是惊喜的是主App死亡后,隐式打开的子App并不会存在于快照中,很哈皮,估计是共享一个进程。 - 疑问:主App卸载后,子App如何卸载?
解:原计划每个模块App实现一个静态Service,每个Service监听主App是否卸载,若收到卸载广播则排队卸载,卸载完后Service直接自杀.若Service被不小心清理掉那就GG,不卸载了;后来发现无法这样操作,主App卸载后无法卸载子App,今日鲁大师的VR检测模块也无法卸载,说明真的无法卸载,主要在应用中进行业务提醒与引导,但是如果是使用代码进行卸载则可以进行广播与代码操作(代码所做的系统卸载操不会影响卸载代码后面的操作,现象好似多线程并行运行)。
- 疑问:如何控制模块的版本更新?
获取某个特定子App的版本号
//获取版本号代码
try {
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo("jsnj33.com.sonlauncher1", 0);
String versionName = info.versionName;
int versionCode = info.versionCode;
} catch (Exception e) {
e.printStackTrace();
}
在主App上增加子模块管理并添加检测,如果子模块版本增加则下载子模块,此时会需要用户安装,需要在下载前进行业务引导,用户可能会没有安装并退出App,所以在第二次进入检测后,发现还是旧版本,但是从用户角度来说再下载一遍,有点烦躁,所以对子模块App的名字要进行规则命名严格管控,下载前通过子模块apk包名判断是否该下载。
- 疑问:如何进行模块间传值?
原计划模块间传值,将模块使用与主App一样的签名并sharedUserId,使其在共享同一进程(并不一定要在同一进程),据说这样可以共享数据data目录下的数据或是通过获取目标context访问目标app的一些资源,所有的bean类传值皆以json形式,至于一App是否可以直接访问另一App的内存值就不知道了,但是这些传值方式其实都是够了的,只需要写一个调度管理工具类。
这个博客写的sharedUserId总结不错:https://www.cnblogs.com/mythou/p/3258715.html
猜想总结:
- 猜想子模块App监测主App是否运行不运行则弹窗拒绝开启并自杀(实际运行来看暂时不需要,可以忽略)
- 每个子模块需要记录各自版本用于更新
所遇弊端:
1.跳转时貌似遇到“冷启动慢的问题”,在第一次跳转时会遇到白屏,状态栏都是白的,看起来挺奇怪的,但是第二次打开后应该属于“热启动”没有这些问题,正常如初。
2.由于是几乎完全隔离的两个App,那么第三方包之类的不会进行共用,各个组件包重复率高。
3.通信不便,老生常谈,不作解释。
(这些弊端都可以想办法解决)
-
具体做法:
1.宿主App所做:
//跳转到子模块APP
Intent intent = new Intent();
//EaseConstant.PAGENAME:子模块包名;
//"jsnj33.com.pigapp.MainActivity":子模块具体Activity(完整路径) EaseConstant.PAGENAME为子模块包名
ComponentName cn = new ComponentName(EaseConstant.PAGENAME,"jsnj33.com.pigapp.MainActivity");
intent.setComponent(cn);
intent.setAction("android.intent.action.MAIN");
intent.putExtra("exe","启动了");
try {
startActivityForResult(intent, RESULT_OK);
} catch (Exception e) {
ToastUtil.showToast(context,"暂无该子模块,请下载安装!");
}
2.子模块App所做
a.若在宿主Activty里面点击按钮跳转子模块App 则子模块设置:
<!-- android:host为宿主Activity名 android:scheme为宿主Activity的包名-->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:host="MainActivity" android:scheme="com.danze.im.ui"/>
</intent-filter>
</activity>
b.若在宿主fragment里面点击按钮跳转到子模块App 则子模块App设置
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- android:host:宿主App Fragment类名 android:scheme:宿主App Fragment包名 -->
<data android:host="GridWorkFragment"
android:scheme="com.danze.im.ui.fragment"/>
</intent-filter>
</activity>
网友评论