Google自动更新WebView后应用被强制关闭的问题求助
我开发的是一款混合应用,通过WebView展示全部内容,要求始终保持前台运行,部署在第三方厂商的Android 10英寸房间面板(Android 11)上,无需考虑电池续航问题。
核心问题:Google的WebView自动更新(出于安全必须保留)会直接强制关闭我的应用,且不会触发Activity的onPause、onDestroy等生命周期方法,类似崩溃但无Crashlytics/Sentry报错。
通过连续5天ADB日志监控,捕获到应用被关闭的关键日志:
2024-01-11 07:51:56.665 ActivityManager system_server I Killing 4372:com.example.myapp/u0a167 (adj 0): stop com.google.android.webview due to installPackageLI 2024-01-11 07:51:56.670 ActivityTaskManager system_server W Force removing ActivityRecord{7fad574 u0 com.example.myapp/.ui.MainActivity t100 f}}: app died, no saved state
我已实现一个粘性前台服务用于检测应用后台状态并唤回,普通场景下正常工作,但WebView更新强制杀进程时,因Activity生命周期未触发,服务无法感知应用已退出,无法执行唤回操作。
前台检查服务(ForegroundCheckService.kt)
class ForegroundCheckService : Service() { private val handler = Handler(Looper.getMainLooper()) private val foregroundCheckRunnable = object : Runnable { override fun run() { val isAppInForeground = OBApp.instance.isAppInForeground() if (!isAppInForeground) { bringAppToForeground() } handler.postDelayed(this, TimeUnit.MINUTES.toMillis(Constants.FOREGROUND_CHECK_INTERVAL)) } } override fun onCreate() { super.onCreate() startForeground(1, createForegroundNotification()) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { handler.post(foregroundCheckRunnable) } catch (e: Exception) { Log.e("ForegroundCheckService", "Error in onStartCommand: $e") } return START_STICKY } override fun onDestroy() { super.onDestroy() handler.removeCallbacks(foregroundCheckRunnable) } private fun createForegroundNotification(): Notification { return NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("App Foreground Service") .setContentText("Running in the background") .setSmallIcon(R.drawable.ic_launcher_foreground) .setSilent(true) .build() } private fun bringAppToForeground() { val intent = Intent(this, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } override fun onBind(intent: Intent?): IBinder? { return null } companion object { const val CHANNEL_ID = "ForegroundServiceChannel" } }
AndroidManifest.xml配置
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" /> <service android:name=".helper.ForegroundCheckService" android:foregroundServiceType="dataSync" android:stopWithTask="false" />
前台状态管理器(ForegroundManager.kt)
class ForegroundManager : Application.ActivityLifecycleCallbacks { private var isForeground = false fun isForeground(): Boolean { return isForeground } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { // No-op } override fun onActivityStarted(activity: Activity) { // No-op } override fun onActivityResumed(activity: Activity) { if (activity::class.java == MainActivity::class.java) { isForeground = true Log.d(Constants.TAG, "App to foreground (onResume)}") } } override fun onActivityPaused(activity: Activity) { if (activity::class.java == MainActivity::class.java) { isForeground = false Log.d(Constants.TAG, "App to background (onPause)}") } } override fun onActivityStopped(activity: Activity) { if (activity::class.java == MainActivity::class.java) { isForeground = false Log.d(Constants.TAG, "App to background (onStop)}") } } override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { // No-op } override fun onActivityDestroyed(activity: Activity) { // No-op } }
Application类(OBApp.kt)
class OBApp : DaggerApplication() { companion object { lateinit var instance: OBApp } private val foregroundManager = ForegroundManager() override fun onCreate() { super.onCreate() Log.d("OBApp", "OnCreate() ") instance = this registerActivityLifecycleCallbacks(foregroundManager) createNotificationChannel() } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( ForegroundCheckService.CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT ) channel.setSound(null, null) val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } override fun onTerminate() { super.onTerminate() unregisterActivityLifecycleCallbacks(foregroundManager) } override fun applicationInjector(): AndroidInjector<out DaggerApplication> { return DaggerAppComponent.factory().create(this) } fun isAppInForeground(): Boolean { return foregroundManager.isForeground() } }
现有代码的缺陷
当前isAppInForeground()仅依赖Activity生命周期回调判断状态,但WebView更新是直接杀进程,Activity的生命周期方法完全不会触发,导致isForeground仍保持true,服务不会执行唤回操作。另外,前台服务类型设置为dataSync,与"保持应用前台"的场景匹配度较低。
解决方案
1. 改进前台状态检测逻辑:直接检查进程/Activity存活状态
替换原有依赖生命周期的判断,改为直接查询系统进程信息确认应用是否在前台:
修改OBApp中的isAppInForeground():
fun isAppInForeground(): Boolean { val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val appProcesses = activityManager.runningAppProcesses ?: return false for (processInfo in appProcesses) { if (processInfo.processName == packageName && processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { // 进一步确认MainActivity是否在栈顶 val tasks = activityManager.getRunningTasks(1) if (tasks.isNotEmpty()) { val topActivity = tasks[0].topActivity return topActivity?.className == MainActivity::class.java.name } return true } } return false }
在Manifest中添加必要权限:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
2. 让前台服务在进程重启后立即唤醒应用
修改服务的onStartCommand,返回START_REDELIVER_INTENT确保重启后恢复任务,并在启动时立即检查应用状态:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { // 服务启动/重启时立即检查并唤醒 checkAndBringToForeground() handler.post(foregroundCheckRunnable) } catch (e: Exception) { Log.e("ForegroundCheckService", "Error in onStartCommand: $e") } return START_REDELIVER_INTENT } private fun checkAndBringToForeground() { val isAppInForeground = OBApp.instance.isAppInForeground() if (!isAppInForeground) { bringAppToForeground() } } // 同步修改Runnable逻辑 private val foregroundCheckRunnable = object : Runnable { override fun run() { checkAndBringToForeground() handler.postDelayed(this, TimeUnit.MINUTES.toMillis(Constants.FOREGROUND_CHECK_INTERVAL)) } }
3. 优化前台服务配置
将服务类型改为更匹配的specialUse,如果设备是厂商定制面板,可申请将应用设为系统应用并添加android:persistent="true",降低被系统杀死的概率:
<service android:name=".helper.ForegroundCheckService" android:foregroundServiceType="specialUse" android:stopWithTask="false" android:persistent="true" />
4. 添加进程重启后的自动唤醒逻辑
在OBApp的onCreate中判断是否为进程重启,直接启动主Activity:
override fun onCreate() { super.onCreate() Log.d("OBApp", "OnCreate() ") if (!::instance.isInitialized) { instance = this registerActivityLifecycleCallbacks(foregroundManager) createNotificationChannel() // 进程重启后直接唤醒主Activity val intent = Intent(this, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } }
- 联系设备厂商将应用加入系统白名单,禁止WebView更新时杀死应用进程。
- 手动触发WebView更新(通过ADB安装更新包),验证服务唤回逻辑是否生效。
- 缩短前台检查间隔至30秒以内,提高检测及时性。
内容的提问来源于stack exchange,提问作者Parissa Kalaee

