如何实现应用重启
1. 前言
在一些手游中经常会有资源更新后自动重启应用的功能,这个是怎么实现的呢?
2. 实现思路
主要思路就是利用Android对多进程
的支持,实现双进程互相拉起。
假设在主进程A
外还有另外一个进程B
。主要的流程如下:
- 在主进程A执行完一些列业务逻辑后,如果想要重启,先拉起进程B
- 进程B启动后,主进程A kill掉自己
- 进程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)
}
}
}
}
简述上述代码:
- 启动
KillerActivity
并关闭主进程 Activity:当需要重启主进程时,launch 方法启动KillerActivity
并关闭主进程的 Activity。- 延迟终止主进程:启动后,通过协程延迟
500
毫秒,确保KillerActivity
启动成功后再结束主进程。- 双重检查主进程状态:在
KillerActivity
中的onCreate
方法启动后,使用doubleCheckMainProcess
方法检查主进程是否已关闭,如果没有,则强制结束该进程。- 重启主界面:确认主进程已关闭后,重新启动应用的主界面 MainActivity。
最后,只要搞清楚 killProcess 方法哪些时候是kill的哪个进程,就理解了。在任意一个需要重启当前进程(可以不只是主进程)的地方,调用:KillerActivity.launch(this)