111 lines
4.8 KiB
Kotlin
111 lines
4.8 KiB
Kotlin
package com.yzx.kiosk.receiver
|
|
|
|
import android.app.ActivityManager
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Build
|
|
import android.os.Handler
|
|
import android.os.Looper
|
|
import com.yzx.kiosk.SplashActivity
|
|
import com.yzx.kiosk.utils.LogUtils
|
|
|
|
/**
|
|
* 开机自启动广播接收器
|
|
* 接收系统开机完成广播,自动启动应用
|
|
*/
|
|
class BootReceiver : BroadcastReceiver() {
|
|
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
try {
|
|
val action = intent.action
|
|
LogUtils.d("BootReceiver", "收到广播: $action, package: ${context.packageName}")
|
|
|
|
// 检查是否是开机完成广播
|
|
// 注意:ACTION_MY_PACKAGE_REPLACED 和 ACTION_PACKAGE_REPLACED 应该由 VersionUpdateManager 处理
|
|
// 这里只处理真正的开机完成广播,避免与应用更新重启冲突
|
|
if (Intent.ACTION_BOOT_COMPLETED == action ||
|
|
Intent.ACTION_LOCKED_BOOT_COMPLETED == action) {
|
|
|
|
LogUtils.d("BootReceiver", "检测到开机完成,准备启动应用")
|
|
|
|
// 使用 goAsync() 保持 receiver 活跃,避免在 Handler 执行前被销毁
|
|
val pendingResult = goAsync()
|
|
|
|
// 延迟启动,确保系统完全启动
|
|
Handler(Looper.getMainLooper()).postDelayed({
|
|
try {
|
|
// 检查应用是否已经在前台运行
|
|
if (isAppInForeground(context)) {
|
|
LogUtils.d("BootReceiver", "应用已在前台运行,无需启动")
|
|
} else {
|
|
startApp(context)
|
|
LogUtils.d("BootReceiver", "应用启动完成")
|
|
}
|
|
} catch (e: Exception) {
|
|
LogUtils.e("BootReceiver", "启动应用异常: ${e.message}")
|
|
e.printStackTrace()
|
|
} finally {
|
|
// 完成异步操作
|
|
pendingResult.finish()
|
|
}
|
|
}, 2000) // 延迟2秒启动,确保系统服务已就绪
|
|
} else if (Intent.ACTION_MY_PACKAGE_REPLACED == action ||
|
|
(Intent.ACTION_PACKAGE_REPLACED == action &&
|
|
intent.dataString?.contains(context.packageName) == true)) {
|
|
// 应用更新广播,由 VersionUpdateManager 处理,这里只记录日志
|
|
LogUtils.d("BootReceiver", "检测到应用更新广播,但由 VersionUpdateManager 处理,不执行启动")
|
|
} else {
|
|
LogUtils.d("BootReceiver", "广播不匹配,忽略: $action")
|
|
}
|
|
} catch (e: Exception) {
|
|
LogUtils.e("BootReceiver", "处理开机广播异常: ${e.message}")
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查应用是否在前台运行
|
|
*/
|
|
private fun isAppInForeground(context: Context): Boolean {
|
|
return try {
|
|
val appProcessInfo = ActivityManager.RunningAppProcessInfo()
|
|
ActivityManager.getMyMemoryState(appProcessInfo)
|
|
val isForeground = appProcessInfo.importance ==
|
|
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
|
|
LogUtils.d("BootReceiver", "应用前台状态检查: $isForeground (importance: ${appProcessInfo.importance})")
|
|
isForeground
|
|
} catch (e: Exception) {
|
|
LogUtils.e("BootReceiver", "检查应用前台状态失败: ${e.message}")
|
|
e.printStackTrace()
|
|
// 如果检查失败,默认返回 false,允许启动应用
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 启动应用
|
|
*/
|
|
private fun startApp(context: Context) {
|
|
try {
|
|
val intent = Intent(context, SplashActivity::class.java).apply {
|
|
// 添加标志,确保在新任务栈中启动
|
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
// 对于 Android 8.0 及以上版本,需要显式设置组件
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
setPackage(context.packageName)
|
|
}
|
|
}
|
|
|
|
context.startActivity(intent)
|
|
LogUtils.d("BootReceiver", "应用启动成功 - SplashActivity")
|
|
} catch (e: Exception) {
|
|
LogUtils.e("BootReceiver", "启动应用失败: ${e.message}")
|
|
e.printStackTrace()
|
|
throw e
|
|
}
|
|
}
|
|
}
|