Google 自动更新后 Webview 停止工作

问题描述 投票:0回答:1

我正在开发一个应用程序,它实际上是一个混合应用程序,只是在 webView 中显示所有细节,所以我只想将应用程序保留在前台。它是Android 11 10英寸房间面板(来自第三方公司),所以我的电池使用没有任何问题。

我的主要问题是关于 Google 的 webview 自动更新(这在某种程度上很重要,主要是为了安全),尽管没有点击 onPause 或 onDestroy 它关闭了我的应用程序,类似于崩溃,但没有任何线索发送到 Crashlytics或哨兵。

我运行了大约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

我搜索了很多,发现了很多关于这个问题的类似报道:

Google Play 服务的终止应用程序在更新时发出第 9 项信号,而不调用 onPause 和 onStop

自动更新Android系统Webview导致活动的Android应用程序在没有警告的情况下退出

如何阻止 Chrome 后台更新杀死我的应用程序?

我的应用程序因服务应用程序更新而被终止

所以在其中一篇中,我注意到了这个评论:

就我而言,我创建了一个粘性前台服务,即使 Chrome 更新我的手机并崩溃,我的应用程序也会重新启动。

伊戈尔·加纳波尔斯基

2020 年 10 月 6 日 19:48

我的代码中还有一个 Sticky ForegroundService,用于检查应用程序是否在后台,将其带回到前台。

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
    }
}

以及应用程序活动:

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()
    }

}

但问题出在 ForegroundManager.kt 中,我设置了一个标志 isForeground true 或 false 来了解应用程序何时进入后台,并稍后在 ForegroundCheckService 中使用它来将应用程序带回前台。

而且它确实工作得很好,每当应用程序进入后台时,除了这种自动更新 webview 的情况之外,它不会进入 onActivityPaused 或 onActivityStopped 的整个生命周期!

所以我想知道我在定义 ForegroundService 的任何步骤中是否犯了错误,因为我只需要让应用程序返回前台,无论它为什么不在那里。

感谢您的帮助。

android webview foreground-service
1个回答
0
投票

你可以按照这个步骤吗

  1. 更新您的 ForegroundService 以在应用程序未运行时重新启动

  2. ForegroundCheckService中,修改onStartCommand

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    if (!isAppRunning()) {
        restartApp()
    }
    return START_STICKY
}

private fun isAppRunning(): Boolean {
    // Implement logic to check if app is running
}

private fun restartApp() {
    val restartIntent = Intent(this, MainActivity::class.java)
    restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    startActivity(restartIntent)
}

  1. 实现 isAppRunning 来检查应用程序的主要 Activity 是否正在运行。
© www.soinside.com 2019 - 2024. All rights reserved.