Skip to content

如何实现应用重启

1. 前言

在一些手游中经常会有资源更新后自动重启应用的功能,这个是怎么实现的呢?

2. 实现思路

主要思路就是利用Android对多进程的支持,实现双进程互相拉起。

假设在主进程A外还有另外一个进程B。主要的流程如下:

  1. 在主进程A执行完一些列业务逻辑后,如果想要重启,先拉起进程B
  2. 进程B启动后,主进程A kill掉自己
  3. 进程B拉起主进程,再kill掉自己。

这样,主进程就完成了自动重启。

3. 实践

xml
<activiy
    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@KillerActivity, 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)
            }
        }
    }
}

简述上述代码:

  1. 启动 KillerActivity 并关闭主进程 Activity:当需要重启主进程时,launch 方法启动 KillerActivity 并关闭主进程的 Activity。
  2. 延迟终止主进程:启动后,通过协程延迟 500 毫秒,确保 KillerActivity 启动成功后再结束主进程。
  3. 双重检查主进程状态:在 KillerActivity 中的 onCreate 方法启动后,使用 doubleCheckMainProcess 方法检查主进程是否已关闭,如果没有,则强制结束该进程。
  4. 重启主界面:确认主进程已关闭后,重新启动应用的主界面 MainActivity。

最后,只要搞清楚 killProcess 方法哪些时候是kill的哪个进程,就理解了。在任意一个需要重启当前进程(可以不只是主进程)的地方,调用:KillerActivity.launch(this)

Released under the MIT License.