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

Android 区分清单中的隐式广播接收器与显式广播接收器,android,android-intent,android-manifest,android-broadcast,android-8.0-oreo,Android,Android Intent,Android Manifest,Android Broadcast,Android 8.0 Oreo,根据谷歌提供的安卓O迁移指南,大部分隐含的广播意图不应该在清单中注册(除了发现的少数例外),但显式广播意图保持不变 我们希望将任何需要的广播从舱单上移开。但我们如何识别接收者是否是隐性的呢?有一般规则吗 下面是我们在清单中注册的广播示例。我们是否应该只查看“action”标记,并查看它是否被列入白名单以将其保留在清单中 <receiver android:name=".receiver.ImageBroadcastReceiver" android:enabled="tru

根据谷歌提供的安卓O迁移指南,大部分隐含的广播意图不应该在清单中注册(除了发现的少数例外),但显式广播意图保持不变

我们希望将任何需要的广播从舱单上移开。但我们如何识别接收者是否是隐性的呢?有一般规则吗

下面是我们在清单中注册的广播示例。我们是否应该只查看“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>

例如,“com.android.vending.INSTALL\u referer”意图没有被列入白名单。我们应该在活动中注册它吗?如果是这样的话,当我们注册应用程序时,它不会被触发吗?当我试图理解广播接收器是隐式的还是显式的时,这让我感到困惑,因为我认为我只需要检查“action”标签

但我们如何识别接收者是否是隐性的呢

如果
意图
具有
组件名称
,则
意图
是明确的。否则,它是隐含的

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

  • 它可以直接放在
    Intent
    上(例如,
    新Intent(这就是Wesomereceiver.class

  • 使用
    PackageManager
    querytentReceivers()
    根据动作字符串等找到正确的接收者后,可以直接将其放在
    Intent

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

我们是否应该只查看“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>
不。你还需要考虑广播的性质:它是发送给任何注册的接收者,还是只发送给特定的应用程序

例如,“com.android.vending.INSTALL\u referer”的意图没有被列入白名单。我们应该在活动中注册它吗

否。该广播将只发送到最近安装的应用程序,因此它必须是明确的
意图
。操作字符串等用于帮助系统确定哪个注册的接收者是相关的接收者


与添加的
ACTION\u PACKAGE\u
相比,它被广播到任何注册的接收者;它不仅仅是一个特定的应用程序。因此,
Intent
必须是隐式的(否则它将有一个
ComponentName
标识特定应用程序中的特定接收者)。而且,由于添加的
ACTION\u PACKAGE\u
不在白名单上,因此假设您无法在Android 8.0+上的清单中注册此广播。

setClassName是另一个选项,对吗?还有其他选项吗?@FlorianWalther:
setComponent()
。可能还有其他问题;我没有把它们全部记住。你在一年多前的博客上发布了一个使用PackageManager的解决方案。到目前为止,你是否遇到过任何问题?它是否完全替代了静态隐式接收器?@FlorianWalther:我不知道这项技术有任何问题,尽管我没有必要个人使用。有关更多信息,请参阅此相关问题,包括一些代码: