未获得ACTION_PACKAGE_REMOVED广播-Android 10 /设置

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

我们想知道何时从Android设备上卸载应用程序。我们设置了有关设备应用程序的广播接收器(不在清单中),并在接收到它们时对其进行处理。问题:在卸载应用程序时(使用Android设置->应用程序/通知-> AppYouWantToUninstall->点击垃圾桶),无法接收广播...但是,只有在将应用程序安装在Android 10设备上时,这种情况才会发生。

当然,还有其他两种主要的方法来卸载应用程序:1)点击/按住应用程序,然后弹出“应用程序信息”菜单; 2)进入Play商店。另外两种方法提供了ACTION_PACKAGE_REMOVED的广播。

操作系统(Android 7、8、9和10的所有组合以及三种卸载方法均可提供ACTION_PACKAGE_REMOVED广播当应用程序在Android 10设备上时,设置卸载方法除外。我会怀疑,因此,我将回答几个可能的问题:“是的,如果我们在Android 10上使用Play Store卸载应用程序,则会获得广播”“是的,如果我们使用在Android 7、8、9上为应用卸载设置后,我们确实会广播”

类中的定义:

class AppInstallBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent == null || context == null) return
        when (intent.action) {
            Intent.ACTION_PACKAGE_ADDED ->
                enqueueWork(context, getIntent(context, ACTION_PACKAGE_ADDED, intent.data?.schemeSpecificPart))
            Intent.ACTION_PACKAGE_REPLACED ->
                enqueueWork(context, getIntent(context, ACTION_PACKAGE_REPLACED, intent.data?.schemeSpecificPart))
            Intent.ACTION_PACKAGE_CHANGED ->
                enqueueWork(context, getIntent(context, ACTION_PACKAGE_CHANGED, intent.data?.schemeSpecificPart))
            Intent.ACTION_PACKAGE_REMOVED ->
                enqueueWork(context, getIntent(context, ACTION_PACKAGE_REMOVED, intent.data?.schemeSpecificPart))
            Intent.ACTION_PACKAGE_FULLY_REMOVED ->
                enqueueWork(context, getIntent(context, ACTION_PACKAGE_FULLY_REMOVED, intent.data?.schemeSpecificPart))
                }
    }

...这是我们处理收到的动作的地方

    private suspend fun processAction(action:String, packageName: String, context: Context) {
        when (action) {
            ACTION_PACKAGE_ADDED -> updateAppInfo(context, packageName, false)
            ACTION_PACKAGE_REPLACED -> updateAppInfo(context, packageName, true)
            ACTION_PACKAGE_REMOVED -> deleteAppInfo(context, packageName)
            ACTION_PACKAGE_FULLY_REMOVED -> deleteFullyAppInfo(context, packageName)
        }
    }

这是我们在应用程序中而不是清单中定义接收方的位置:

    private val installBroadcastReceiver = AppInstallBroadcastReceiver()
    private val installReceiverFilter = IntentFilter().apply {
        addAction(Intent.ACTION_PACKAGE_ADDED)
        addAction(Intent.ACTION_PACKAGE_REMOVED)
        addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
        addAction(Intent.ACTION_PACKAGE_CHANGED)
        addAction(Intent.ACTION_PACKAGE_REPLACED)
        addDataScheme("package")
    }

...以及我们注册的地方,过滤器

    private fun registerAppChanges() {
        Timber.d("Registering the installation receiver ..")
        registerReceiver(installBroadcastReceiver, installReceiverFilter)
        registerReceiver(unlockReceiver, unlockReceiverFilter)
    }
android kotlin broadcastreceiver uninstall
1个回答
1
投票

要运行Broadcast receiver,您必须知道其工作方式。以前,当您注册广播接收器时,即使应用程序不在后台,任何注册的操作发生时也会触发它。然后,Android小组进行了一些更改以优化电池。如果您的应用目标为26或更高,则必须动态声明它而不是清单。这是文本

注意:如果您的应用定位到API级别26或更高级别,则不能使用清单以声明用于隐式广播的接收方(广播并不专门针对您的应用),除了一些隐式不受此限制的广播。在大多数情况下,可以改为使用预定的作业。

那么有什么选择?您必须使用context或applicationContext动态注册广播。因此,当您的上下文仍然存在时,应用程序会接收广播事件。这是来自Google的文字:

经上下文注册的接收者只要收到他们的广播,注册上下文有效。例如,如果您在活动上下文,只要活动是没有被摧毁。如果您在Application上下文中注册,则您只要应用程序正在运行,就可以接收广播。

那么,即使您的应用未运行,您如何收听广播事件?

由于广播接收器不可靠,我无法想象任何可行的解决方案,但是您可以一直考虑运行后台服务。这也将是多余的。检查这个答案Making BroadcastReceiver work in the background in API 26 or above

我可以想到的另一种解决方案,如果API级别低于26,它应该可以正常工作,但对于api 26及更高版本,在您的应用程序onResume中,您将检查每次可用的应用程序和当前应用程序列表。然后删除多余的应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.