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

背景

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

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

思路

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

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

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

  • 在主进程执行完一系列业务逻辑后,欲重启,先拉起进程B
  • 进程B启动后,主进程kill掉自己
  • 接着,进程B拉起主进程,然后再kill掉自己,此时主进程完成自动重启

实现

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

xml 复制代码
        <activity
            android:name=".KillerActivity"
            android:exported="false"
            android:launchMode="singleTask"
            android:process=":killer" />

关键实现来了:

kotlin 复制代码
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的哪个进程,就理解了。在任意一个需要重启当前进程(可以不只是主进程)的地方,调用:

kotlin 复制代码
KillerActivity.launch(this)  

即可。

相关推荐
奈斯先生Vector5 小时前
当模型版本不断变化,RelayRouter 能否帮助 AI 应用摆脱深度绑定
android·java·人工智能·开源·aigc
TimeFine5 小时前
让强模型做“总工”,让高性价比模型写代码
android
又见情义6 小时前
RK3568 Android 13 屏蔽 healthd 电池日志经验分享
android
古法安卓9 小时前
Android-Fork 机制详解
android·java·android studio
JMchen9 小时前
第 12 篇|项目整合与打包发布 —— 从 Demo 到可安装 APK 的完整收官指南
kotlin·android studio
Android打工仔9 小时前
不要在 Data 层随意把 Cold Flow 转换成 Hot Flow
android·架构·kotlin
峥嵘life10 小时前
2026免费的 opencode 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言
杉氧10 小时前
拒绝重复造轮子:我写了一个生产级的 Kotlin 协程与 Flow 工具库(CoroutineKit)
android·kotlin·workflow
恋猫de小郭11 小时前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter
2501_9159090611 小时前
怎么用 FlutterFlow 把应用发布到 App Store?
android·ios·小程序·https·uni-app·iphone·webview