专栏名称: Android技术之家
主要分享Android相关技术文章、移动互联网的相关产品和资讯。关注你将学习到更多基础以及框架相关的知识,为您的工作助力!
目录
相关文章推荐
51好读  ›  专栏  ›  Android技术之家

双进程交互实现App自动重启

Android技术之家  · 公众号  ·  · 2024-04-24 17:23

正文

请到「今天看啥」查看全文


背景

你可能会好奇,有些手游(比如王者荣耀)是怎么实现资源更新后自动重启的?

这个体验确实不错,因为不需要用户手动点击桌面图标重启App,在一些数据恢复备份的场景中,很实用。比如,从云端拉取SQLite数据库db文件或一些prefs配置文件后,会直接覆盖到本地,但进程不重新启动的话,是不会生效的。

思路

基本思路其实很简单,利用Android应用对多进程的天然支持,来实现双进程互拉。

有的朋友一看见“双进程”、“互拉”这些词汇就会立马联想到保活,注意本文不是讲保活的哦。

为了方便讲解,我们定义主进程之外的另一个进程为 进程B 。大致流程分这么几步:

  • 在主进程执行完一系列业务逻辑后,欲重启,先拉起进程B

  • 进程B启动后,主进程kill掉自己

  • 接着,进程B拉起主进程,然后再kill掉自己,此时主进程完成自动重启

实现

先在Manifest中声明进程B,为了良好的交互体验,需要实现一个Activity,进程名称自定义,比如此处叫“killer”,是不是很贴切?

   <activity            android:name=".KillerActivity"            android:exported="false"            android:launchMode="singleTask"            android:process=":killer" />

关键实现来了:

class KillerActivity : FragmentActivity() {
companion object { private const val EXTRA_MAIN_PID = "extra_main_pid"
// 当主进程需要重启时,就直接调用此方法启动KillerActivity fun launch(activity: FragmentActivity) { activity.startActivity( Intent(activity, KillerActivity::class.java).apply { putExtra(EXTRA_MAIN_PID, Process.myPid()) } ) activity.finish() // 主进程的Activity先关闭 GlobalScope.launch { // 稍作延迟后,主进程kill掉自己 delay(500L) killProcess() } }
fun killProcess(pid: Int = Process.myPid()) { Process.killProcess(pid) exitProcess(0) }
fun isMainProcessAlive(context: Context): Boolean = runCatching { (context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) .runningAppProcesses.find { it.processName == context.packageName } != null }.getOrDefault(false) }
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycleScope.launch { // 此处可以插入一些Loading的UI显示,比如ProgressDialog之类的 // ... // 二次检查,防止主进程没杀掉 doubleCheckMainProcess() // 稍作等待后,再次启动主进程的Activity startActivity(Intent(this, MainActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) }) // 进程B的KillerActivity先关闭,再kill掉自己 finish() killProcess() } }
private suspend fun doubleCheckMainProcess() { delay(1500L) if (isMainProcessAlive(this)) { val mainPid = intent.getIntExtra(EXTRA_MAIN_PID, 0) if (mainPid != 0) { killProcess(mainPid) delay(1500L) } } }}

整个代码非常简单,只要搞清楚 killProcess 方法哪些时候是kill的哪个进程,就理解了。在任意一个需要重启当前进程(可以不只是主进程)的地方,调用:

KillerActivity.launch(this)  

即可。


作者:针叶链接:https://juejin.cn/post/7350126677572304907

关注我获取更多知识或者投稿








请到「今天看啥」查看全文