接收来自 Android Oreo 通知的广播
Receiving broadcast from notification on Android Oreo
我在置顶通知中有一个自定义按钮。
我曾经在其上附加一个 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);
这有效,但仅当应用对用户可见时。
感谢帮助
当显式 Intent
有效时,切勿使用隐式 Intent
。
替换:
Intent intent = new Intent();
intent.setAction("com.example.app.intent.action.BUTTON_CLICK");
与:
Intent intent = new Intent(this, NotificationActionReceiver.class);
并从 NotificationActionReceiver
<receiver>
元素中删除 <intent-filter>
。
我 运行 也在 Android 8 - Oreo
上解决了这个问题,但是考虑到我的图书馆项目要求,我没有明确命名的 BroadcastReceiver
class 实现, end-client 将在 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 文档。
In Android 4.0 and higher, you can specify a package with
setPackage(String) when sending a broadcast. The system restricts the
broadcast to the set of apps that match the package.
下面是 BroadcastReceiver
声明(或合并)到 end-client 应用程序的 AndroidManifest
中的示例:
<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
的库项目展开,因此我决定在 <receiver>
声明中保留 <intent-filter>
和 <action />
。否则,将触发 non-unique 个广播操作,这 可能 导致多个应用程序收到错误广播的潜在问题。这主要是一种安全预防措施。当然你还需要检查BroadcastReceiver
.
中执行的action
希望有人觉得这有用!
我在置顶通知中有一个自定义按钮。
我曾经在其上附加一个 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);
这有效,但仅当应用对用户可见时。
感谢帮助
当显式 Intent
有效时,切勿使用隐式 Intent
。
替换:
Intent intent = new Intent();
intent.setAction("com.example.app.intent.action.BUTTON_CLICK");
与:
Intent intent = new Intent(this, NotificationActionReceiver.class);
并从 NotificationActionReceiver
<receiver>
元素中删除 <intent-filter>
。
我 运行 也在 Android 8 - Oreo
上解决了这个问题,但是考虑到我的图书馆项目要求,我没有明确命名的 BroadcastReceiver
class 实现, end-client 将在 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 文档。
In Android 4.0 and higher, you can specify a package with setPackage(String) when sending a broadcast. The system restricts the broadcast to the set of apps that match the package.
下面是 BroadcastReceiver
声明(或合并)到 end-client 应用程序的 AndroidManifest
中的示例:
<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
的库项目展开,因此我决定在 <receiver>
声明中保留 <intent-filter>
和 <action />
。否则,将触发 non-unique 个广播操作,这 可能 导致多个应用程序收到错误广播的潜在问题。这主要是一种安全预防措施。当然你还需要检查BroadcastReceiver
.
希望有人觉得这有用!