GCM:如果应用程序不可见,则不会收到 IntentService.sentBroadcast 的消息

Posted

技术标签:

【中文标题】GCM:如果应用程序不可见,则不会收到 IntentService.sentBroadcast 的消息【英文标题】:GCM: messages by IntentService.sentBroadcast are not received if application is not visible 【发布时间】:2013-10-24 10:03:32 【问题描述】:

我正在尝试实现 GCM 客户端和服务器架构。到目前为止一切正常。

例外:当我的活动关闭并且我收到 GCM 的新通知时,通知会显示在通知栏中。到现在为止还挺好。但是当我点击通知时,我的活动被打开,但我的BroadcastReceiveronReceive 事件没有被触发。 :( 如果Activity打开了,onReceive就完美触发了。

你知道这里有什么问题吗?

干杯

克里斯

这就是我的服务:

package xy;

import ...;

public class GcmIntentService extends IntentService

  private NotificationManager mNotificationManager;
  NotificationCompat.Builder builder;


  public GcmIntentService()
  
    super("GcmIntentService");
  


  @Override
  protected void onHandleIntent(Intent intent)
  
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    String messageType = gcm.getMessageType(intent);

    if (!extras.isEmpty())  // has effect of unparcelling Bundle

     final int notificationID = (int) (Math.random() * 100000000);

     if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) 
        sendNotification("GCM notification: Send error", extras.toString(), notificationID);
      else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) 
       sendNotification("Deleted messages on server", extras.toString(), notificationID);
      // If it's a regular GCM message, do some work.
       else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) 
       sendNotification(extras.getString(Utils.TICKER_TITLE_MESSAGE_KEY), extras
            .getString(Utils.TICKER_TEXT_MESSAGE_KEY), notificationID);
        Intent intentToBroadCast = new Intent(Utils.DISPLAY_MESSAGE_ACTION);
        intentToBroadCast.putExtra(Utils.MESSAGE_EXTRA_BUNDLE_KEY, extras);
        intentToBroadCast.putExtra(Utils.NOTIFICATION_ID_KEY, notificationID);
        sendBroadcast(intentToBroadCast);
      
    
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    GcmBroadcastReceiver.completeWakefulIntent(intent);
  


  private void sendNotification(final String aTitle, final String aText, final int aNotificationID)
  
    mNotificationManager = (NotificationManager) this
        .getSystemService(Context.NOTIFICATION_SERVICE);

    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this,
        DemoActivity.class), 0);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(
        R.drawable.ic_stat_gcm).setContentTitle(aTitle).setStyle(
        new NotificationCompat.BigTextStyle().bigText(aText)).setContentText(aText);

    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(aNotificationID, mBuilder.build());
  

这是我活动中的接收器,用于显示传入的消息:

public class GcmResultReceiver extends BroadcastReceiver

  @Override
  public void onReceive(Context context, Intent intent)
  
    Bundle extras = intent.getBundleExtra(Utils.MESSAGE_EXTRA_BUNDLE_KEY);
    String s = extras.getString(Utils.CONTENT_TITLE_MESSAGE_KEY) + "\n"
        + extras.getString(Utils.CONTENT_TEXT_MESSAGE_KEY);
    mDisplay.setText(s);

    int notificationID = intent.getIntExtra(Utils.NOTIFICATION_ID_KEY, -1);
    if (-1 != notificationID) m_SentNotificationIDs.add(notificationID);

    if (m_IsVisible) 
      clearNotifications();
    
  
;

所有内容都是从 Google android 教程中的 GCM 示例复制和改编的。

【问题讨论】:

【参考方案1】:

在通知栏显示通知之前触发 BroadcastReceiver。它包含显示通知并在被点击时打开 Activity 的代码(除非它正在启动执行该工作的 Intent 服务)。

因此,如果您看到通知,则表示已触发 BroadcastReceiver。

您不需要额外的 BroadcastReceiver 来将通知数据从第一个接收器传递到您的应用程序。如果您希望在点击通知时将通知数据传递给正在启动的 Activity,您可以将其传递给用于启动该 Activity 的 Intent。

假设您将sendNotification 调用更改为:

sendNotification(extras, notificationID);

然后你可以这样实现:

  private void sendNotification(Bundle extras, final int aNotificationID)
  
    mNotificationManager = (NotificationManager) this
        .getSystemService(Context.NOTIFICATION_SERVICE);

    Intent demoIntent = new Intent(this, DemoActivity.class);
    demoIntent.putExtras (extras);
    demoIntent.putExtra (Utils.NOTIFICATION_ID_KEY, notificationID);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, demoIntent, 0);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(
        R.drawable.ic_stat_gcm).setContentTitle(extras.getString(Utils.TICKER_TITLE_MESSAGE_KEY)).setStyle(
        new NotificationCompat.BigTextStyle().bigText(extras.getString(Utils.TICKER_TEXT_MESSAGE_KEY))).setContentText(extras.getString(Utils.TICKER_TEXT_MESSAGE_KEY));

    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(aNotificationID, mBuilder.build());
  

这样,您的DemoActivity 将获得通知 ID 和所有保存通知数据的附加信息。 您可以在您的活动的onCreate 中访问它们(或者最好在onResume 中进行,以防您的活动已经开始)。

【讨论】:

那么,我该如何调试呢?如果我在 Eclipse 中设置断点以在我的三星上进行调试,这就是我所看到的:派生的 WakefulBroadcastReceiver 类中的 onReceive 对于每条消息总是触发两次。然后派生的IntentService 类中的onHandleIntent 总是被触发一次。但是派生的BroadcastReceiver 类中的onReceive 只有在应用在屏幕上时才会触发。 顺便说一句:我把sendBroadcast 放在派生的IntentService.onHandleIntent 中。这是正确的吗? @ChristianGraf 我看不出有任何理由从意图服务发送广播。你发送什么广播,它的目的是什么?至于调试,如果应用程序在收到通知之前没有运行,我不确定如何将应用程序连接到调试器。尝试添加调试打印并检查您的 logcat。 好吧,我想,我们要说到点子上了。我在 ònHandleIntent 中收到 GCM 消息。我尝试将此消息发送到我的应用程序/活动。为此,我使用了 sendBroadcast 调用。显然这不是正确的方法?!明天要附上日志和打印件。 @ChristianGraf 但是如果您已经在显示通知,并且点击通知会打开您的活动,为什么不直接(通过意图)将消息数据传递给该活动?

以上是关于GCM:如果应用程序不可见,则不会收到 IntentService.sentBroadcast 的消息的主要内容,如果未能解决你的问题,请参考以下文章

iOS 推送通知和 GCM

当应用程序一天不活动时,GCM 推送通知不会出现在 iPhone 上

即使所有消息都从服务器成功,某些设备也不会收到 GCM 推送

GCM 无法使用公司 Google 帐户

如果我强制停止应用程序,GCM 会收到推送通知

未收到 Ionic Cloud 推送 GCM 通知