通过AlarmManager添加定时任务,即使应用被杀死了,也会启动intent
用户静默安装前,定时自启动自身应用。直到应用启动完成,取消其他的定时任务
object InstallAppUtils {const val DEBUG_UPDATE = falseprivate const val PACKAGE_NAME = "com.demo.test"suspend fun installApkCmd(context: Context,filepath: String,onFailed: () -> Unit,onSuccess: () -> Unit) {LogUtils.d("InstallAppUtils installApk filepath=${filepath}")try {val apkFile = File(filepath)scheduleAppRestart(context)MmkvUtils.saveUpdatingApkFilePath(apkFile.absolutePath)delay(500)//延迟执行命令,先做好升级前的准备val process = Runtime.getRuntime().exec(arrayOf("su", "0", "pm", "install", "-r", apkFile.absolutePath))process.waitFor()if (process.exitValue() == 0) {// 安装成功LogUtils.d("APK 静默安装成功")onSuccess.invoke()} else {// 安装失败,可读取错误流以获取详细信息val errorStream = process.errorStream.bufferedReader().readText()LogUtils.d("APK 静默安装失败:$errorStream")apkFile.delete()onFailed.invoke()}} catch (e: Exception) {e.printStackTrace()}}fun clearUpdatingFile() {try {MmkvUtils.getUpdatingApkFilePath()?.let { path ->if (path.isNotEmpty()) {LogUtils.d("InstallAppUtils clearUpdatingFile $path")val file = File(path)if (file.exists()) {file.delete()}}}} catch (e: Exception) {e.printStackTrace()} finally {MmkvUtils.clearUpdatingApkFilePath()}}/*** 通过AlarmManager尝试每隔10秒启动应用*/fun scheduleAppRestart(context: Context) {// 构造启动应用的 Intent,这里假设 MainActivity 为入口var triggerAtMillis = System.currentTimeMillis() + 10_000Lval alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManagerrepeat(6) {triggerAtMillis += 10_000LgetRestartPendingIntent(context, it)?.let { pendingIntent ->// setExactAndAllowWhileIdle 确保在低功耗模式下也能执行alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,triggerAtMillis,pendingIntent)}}}// 取消启动应用的定时任务fun cancelAlarm(context: Context) {val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManagerrepeat(6) {getRestartPendingIntent(context, it)?.let { pendingIntent ->alarmManager.cancel(pendingIntent)}}}private fun getRestartPendingIntent(context: Context, requestCode: Int): PendingIntent? {
// val intent = Intent().apply {
// component = ComponentName(PACKAGE_NAME, LAUNCH_ACTIVITY)
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
// }val launchIntent: Intent? =getPackageManager().getLaunchIntentForPackage(PACKAGE_NAME)return PendingIntent.getActivity(context,requestCode,launchIntent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)}
}