背景
你可能会好奇,有些手游(比如王者荣耀)是怎么实现资源更新后自动重启的?
这个体验确实不错,因为不需要用户手动点击桌面图标重启App,在一些数据恢复备份的场景中,很实用。比如,从云端拉取SQLite数据库db文件或一些prefs配置文件后,会直接覆盖到本地,但进程不重新启动的话,是不会生效的。
思路
基本思路其实很简单,利用Android应用对多进程的天然支持,来实现双进程互拉。
有的朋友一看见“双进程”、“互拉”这些词汇就会立马联想到保活,注意本文不是讲保活的哦。
为了方便讲解,我们定义主进程之外的另一个进程为
进程B
。大致流程分这么几步:
实现
先在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"
fun launch(activity: FragmentActivity) {
activity.startActivity(
Intent(activity, KillerActivity::class.java).apply {
putExtra(EXTRA_MAIN_PID, Process.myPid())
}
)
activity.finish()
GlobalScope.launch {
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 {
doubleCheckMainProcess()
startActivity(Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
})
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)
即可。
关注我获取更多知识或者投稿