【问题标题】:Receiving broadcast from notification on Android Oreo从 Android Oreo 上的通知接收广播
【发布时间】:2017-09-02 17:33:18
【问题描述】:

我在粘性通知中有一个自定义按钮。
我曾经附加一个PendingIntent 来接收按钮点击:

Intent intent = new Intent();

intent.setAction("com.example.app.intent.action.BUTTON_CLICK");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 2000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
contentViewExpanded.setOnClickPendingIntent(R.id.button, pendingIntent);

当我在 Oreo 上运行此代码时,我在 logcat 中得到 BroadcastQueue: Background execution not allowed 并且没有收到按钮点击。

我用清单注册了接收器:

<receiver
    android:name=".BroadcastReceiver.NotificationActionReceiver"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.intent.action.BUTTON_CLICK"/>
    </intent-filter>
</receiver>

我也尝试在我的代码中注册接收器:

NotificationActionReceiver mMyBroadcastReceiver = new NotificationActionReceiver();
IntentFilter filter = new IntentFilter("com.example.app.intent.action.BUTTON_CLICK");
mContext.registerReceiver(mMyBroadcastReceiver, filter);

这有效,但仅当应用对用户可见时。

感谢您的帮助

【问题讨论】:

  • @UmarHussain 我知道它已经改变了:我已经阅读了文档但没有运气。
  • Ph 好吧,其实我还没有在 oreo 中实现广播,所以不知道为什么会出现这个问题

标签: android broadcastreceiver android-notifications background-process android-8.0-oreo


【解决方案1】:

当显式 Intent 可以工作时,切勿使用隐式 Intent

替换:

Intent intent = new Intent();

intent.setAction("com.example.app.intent.action.BUTTON_CLICK");

与:

Intent intent = new Intent(this, NotificationActionReceiver.class);

并从NotificationActionReceiver &lt;receiver&gt; 元素中删除&lt;intent-filter&gt;

【讨论】:

  • 成功了!谢谢。实际上我认为我的意图已经很明确了,因为它针对的是我自己的应用程序。
  • @BehnamMabodi:显式IntentIntent 知道作为目标的特定组件的情况。通常,您通过采用 Java Class 对象(在本例中为 NotificationActionReceiver.class)的构造函数来创建一个。隐含的Intent 是缺少组件的组件,因此Android 依赖动作字符串等其他内容来为您找到组件。
【解决方案2】:

我在Android 8 - Oreo 上也遇到了这个问题,但鉴于我的库项目要求,我没有明确命名的BroadcastReceiver 类实现,最终客户端将在它的AndroidManifest 中声明。

解决方案:

使用setPackage(String)指定Intent上的应用程序包。

示例

// Application unique intent action String
final String receiverAction = getApplicationContext().getPackageName() 
                             + BaseLibraryReceiver.ACTION_SUFFIX;
// No need for Class definition in the constructor.
Intent intent = new Intent(); 
// Set the unique action.
intent.setAction(receiverAction);
// Set the application package name on the Intent, so only the application
// will have this Intent broadcasted, thus making it “explicit" and secure.
intent.setPackage(getApplicationContext().getPackageName());
...

来自 Android Broadcasts: Security considerations and best practices 文档。

在 Android 4.0 及更高版本中,您可以指定一个包 setPackage(String) 发送广播时。系统限制了 广播到与包匹配的应用集。

以下是在终端客户端应用程序的AndroidManifest 中声明(或合并)的BroadcastReceiver 示例:

 <receiver
        android:name=“com.subclassed.receiver.ReceiverExtendedFromLibrary"
        android:exported="false"
        android:enabled="true">

        <intent-filter>
            <action android:name="${applicationId}.action.MY_UNIQUE_ACTION"/>
        </intent-filter>

 </receiver>

由于我的示例围绕广播Intent 的库项目展开,因此我决定将&lt;intent-filter&gt;&lt;action /&gt; 保留在&lt;receiver&gt; 声明中。否则,将触发非唯一的广播操作,这可能导致多个应用程序接收错误广播的潜在问题。这主要是一种安全预防措施。当然你还需要检查BroadcastReceiver的实现中的action。

希望有人觉得这很有帮助!

【讨论】:

  • 出色的工作!!我实际上是想弄清楚如何使用动态包来做到这一点,并偶然发现了你的帖子。像魅力一样工作谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多