区分隐式广播接收器与清单中的显式广播接收器

Gau*_*ier 20 android android-manifest android-intent android-broadcast android-8.0-oreo

根据Google提供给Android O的迁移指南,大多数隐式广播意图不应在Manifest中注册(减去此处的一些例外情况),但显式广播意图仍未触及.

我们希望将任何所需的广播从清单中移除.但是我们如何识别接收器是否隐含?有一般规则吗?

以下是我们在清单中注册的广播示例.我们应该只查看"action"标记,看看它是否被列入白名单以便将其保留在清单中?

<receiver
    android:name=".receiver.ImageBroadcastReceiver"
    android:enabled="true" >
    <intent-filter>
        <action android:name="android.hardware.action.NEW_PICTURE" />
        <category android:name="android.intent.category.OPENABLE" />
        <data android:mimeType="image/*" />
    </intent-filter>
</receiver>

<receiver
    android:name=".receiver.InstallReferrerReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
    </intent-filter>
</receiver>

<receiver android:name=".receiver.JoinEventReceiver" >
    <intent-filter>
        <action android:name="JOIN_ACTION" />
        <action android:name="CANCEL_ACTION" />
        <action android:name="DECLINE_ACTION" />
    </intent-filter>
</receiver>
Run Code Online (Sandbox Code Playgroud)

例如,"com.android.vending.INSTALL_REFERRER"意图未列入白名单.我们应该在活动中注册吗?如果是这样,它不会被解雇,因为当我们注册它时,应用程序已经安装?当我试图理解广播接收器是隐式的还是显式的时,这让我感到困惑,因为我认为我只需要检查"动作"标签.

Com*_*are 31

但是我们如何识别接收器是否隐含?

如果Intent有a ComponentName,那Intent就是明确的.否则,它是隐含的.

ComponentName可以通过以下几种方式之一获得,包括:

  • 它可以直接放在Intent(例如new Intent(this, TheReallyAwesomeReceiver.class)

  • 它可以直接放在Intent使用后,PackageManagerqueryIntentReceivers()根据动作字符串等找到正确的.

  • 它可以由系统从动作字符串等加上通过定义的包来导出 setPackage()

我们应该只查看"action"标记,看看它是否被列入白名单以便将其保留在清单中?

不需要.您还需要考虑广播的性质:它是针对任何已注册的接收者,还是仅针对特定应用?

例如,"com.android.vending.INSTALL_REFERRER"意图未列入白名单.我们应该在活动中注册吗?

不.那个广播只会转到最近安装的应用程序,因此必须是明确的Intent.动作字符串等可以帮助系统确定哪些已注册的接收器是相关的接收器.

与之形成鲜明对比ACTION_PACKAGE_ADDED.这是向任何注册接收者广播的; 它不会只是一个特定的应用程序.因此,这Intent必须是隐含的(否则它将ComponentName识别特定应用程序中的特定接收器).并且,由于ACTION_PACKAGE_ADDED不在白名单上,因此假设您无法在Android 8.0+的清单中注册此广播.