点击android通知图标不会触发广播接收器

gmm*_*mmo 2 notifications android push-notification android-intent android-pendingintent

我有一个与推送通知挂钩的应用程序.当用户点击通知时,我希望触发广播接收器而不是活动.

我看了这些线程,看起来这是完全可能和常见的.

未触发Android通知操作(PendingIntent)

通知点击发送广播

但是我无法让它发挥作用.我看到了通知,但是当我点击它时它从未触发我的广播接收器.

在这里我尝试过:

  1. 我创建了一个自定义接收器

    public class NotificationOnClickReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(final Context context, Intent intent) {
            Log.d(Constants.Engine.LOGGER_TAG_GCM,
                    NotificationOnClickReceiver.class.toString() + " triggered");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我在我的全局应用程序(非活动)上动态注册了此接收器

    mNotificationOnClickReceiver = new NotificationOnClickReceiver();
    IntentFilter intentFilterOnClick = new IntentFilter(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);
    getApplicationContext().registerReceiver(mNotificationOnClickReceiver, intentFilterOnClick);
    Log.e(Constants.Engine.LOGGER_TAG_DBG, "mNotificationOnClickReceiver = " + mNotificationOnClickReceiver.toString());
    
    Run Code Online (Sandbox Code Playgroud)

过滤器只是一个字符串常量(我想知道这是不是问题)

    public static final String BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK = "push_notification.onclick";
Run Code Online (Sandbox Code Playgroud)
  1. 接收方意图设置:

    // When the user taps on the notification bar, this is the receiver that I want to be called
    Intent pushNotificationIntent;
    Log.e(Constants.Engine.LOGGER_TAG_DBG, "Notification called!");
    pushNotificationIntent = new Intent(this, NotificationOnClickReceiver.class);
    // Not sure if this causing the problem
    pushNotificationIntent.setAction(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);
    // ensures that each notification and intent are unique
    int uniqueCode = new Random().nextInt(Integer.MAX_VALUE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            context,
            uniqueCode,
            pushNotificationIntent, // Receiver Intent
            PendingIntent.FLAG_CANCEL_CURRENT);
    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
            .setSmallIcon(mIconId)
            .setContentTitle(context.getString(R.string.myString))
            .setContentText("My GCM Alert!")
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 从日志中看,除了我的广播接收器永远不会被调用之外,事情似乎有效:

    02-22 15:47:47.092 16863-16863/com.myapp.test E/MYAPP_DBG: mNotificationOnClickReceiver = mytest.broadcastreceivers.NotificationOnClickReceiver@d78f559
    02-22 15:47:53.312 16863-17038/com.myapp.test E/MYAPP_DBG: Notification called!
    
    Run Code Online (Sandbox Code Playgroud)

如果有人有这个工作,你能指出一个示例代码吗?我没看到我的bug在哪里.

谢谢!

Mik*_* M. 8

这似乎是问题所在:

pushNotificationIntent = new Intent(this, NotificationOnClickReceiver.class);
Run Code Online (Sandbox Code Playgroud)

你实际上正在Intent为广播创建一个明确的PendingIntent.显式Intents不适用于动态注册的Receiver,因为它们的目标是Receiver类,而不是实例.

您需要使用隐式Intent,而您可以通过简单地Intent使用操作实例化String而不是使用Context和来实现Class.例如:

pushNotificationIntent = new Intent(Constants.Engine.BROADCAST_RECEIVER_FILTER_NOTIFICATION_ONCLICK);
Run Code Online (Sandbox Code Playgroud)

请注意,如果您的应用程序的进程在Notification单击之前被终止,那么该动态注册的Receiver实例也将会死亡,并且该Notification广播将不会真正执行任何操作.

根据所需的行为,最好在清单中静态注册Receiver类,并保持显式Intent.这样做将允许您的应用程序接收Notification广播,即使其进程已被终止.

要做到这一点,您只需要在清单中<receiver>为您添加一个元素NotificationOnClickReceiver.

<receiver android:name="NotificationOnClickReceiver" />
Run Code Online (Sandbox Code Playgroud)

虽然你仍然可以在该广播上设置一个动作Intent,但你<intent-filter>在这里不需要它,因为显式Intent是直接针对该类.如果Receiver仅用于该功能,则您不一定需要该操作,并且可以完全删除它.

然后,您可以删除步骤2中的代码,因为您不再需要动态注册的实例.