当应用程序关闭或处于后台时,收到两次GCM推送通知

4
我已在我的应用程序中实现了GCM推送通知。一切正常,我也能收到通知。
问题:
- 当应用程序处于后台或终止状态时,我会同时收到2个通知。 - 当应用程序处于前台时,只会收到1个通知,这正是我想要的。
应用程序应该按照要求只收到1个通知,但不幸的是遇到了未定义的情况。
我的代码如下: GCMPushReceiverService类用于接收消息。
public class GCMPushReceiverService extends GcmListenerService {

//This method will be called on every new message received
@Override
public void onMessageReceived(String from, Bundle data) {
    //Getting the message from the bundle
    String message = data.getString("message");
    //Displaying a notiffication with the message
    Log.e("MeSs",""+message);
    sendNotification(this,message, "Traccar App");
    sendNotification(message);

}

//This method is generating a notification and displaying the notification  //When in front
private void sendNotification(Context context, String notificationText,
                              String notificationTitle) {

    PowerManager pm = (PowerManager) context
            .getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wakeLock = pm.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK, "");
    wakeLock.acquire();

    Intent intent = new Intent(this, Home.class);
    intent.putExtra("ChatFragment", "newChatFound");
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    int requestCode = 0;
    PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
    Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
            context)
            .setSmallIcon(R.drawable.bug_log_two)
            .setColor(Color.RED)
            .setContentTitle(notificationTitle)
            .setContentText(notificationText)
            .setDefaults(Notification.DEFAULT_ALL)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent);


    NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0, notificationBuilder.build()); //0 = ID of notification

    wakeLock.release();
}

private void sendNotification(String message) {
    Intent intent = new Intent(this, Home.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    int requestCode = 0;
    PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
    Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentText(message)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
}

}

manifest文件代码:

 <!-- GCM -->

    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />

            <category android:name="com.vk.trackeruser" />
        </intent-filter>
    </receiver>

    <!-- GCM Receiver Service -->
    <service
        android:name=".Notification.GCMPushReceiverService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>

    <!-- GCM Registration Intent Service -->
    <service
        android:name=".Notification.GCMRegistrationIntentService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID" />
        </intent-filter>
    </service>

GCMRegistrationIntentService类:

public class GCMRegistrationIntentService extends IntentService {
//Constants for success and errors
public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
public static final String REGISTRATION_ERROR = "RegistrationError";
public static final String SenderId = "my id with numeric number ex 9897979";
//Class constructor
public GCMRegistrationIntentService() {
    super("");
}


@Override
protected void onHandleIntent(Intent intent) {
    //Registering gcm to the device
    registerGCM();
}

private void registerGCM() {
    //Registration complete intent initially null
    Intent registrationComplete = null;

    //Register token is also null
    //we will get the token on successfull registration
    String token = null;
    try {
        //Creating an instanceid
        InstanceID instanceID = InstanceID.getInstance(getApplicationContext());

        //Getting the token from the instance id
        token = instanceID.getToken(SenderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

        //Displaying the token in the log so that we can copy it to send push notification
        //You can also extend the app by storing the token in to your server
        Log.w("GCMRegIntentService", "token:" + token);
      String  tokan = token;
        //on registration complete creating intent with success
        registrationComplete = new Intent(REGISTRATION_SUCCESS);

        //Putting the token to the intent
        registrationComplete.putExtra("token", token);
    } catch (Exception e) {
        //If any error occurred
        Log.w("GCMRegIntentService", "Registration error");
        registrationComplete = new Intent(REGISTRATION_ERROR);
    }
    //Sending the broadcast that registration is completed
    LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
    }

GCMTokenRefreshListenerService类:

public class GCMTokenRefreshListenerService extends InstanceIDListenerService{
  //If the token is changed registering the device again
    @Override
    public void onTokenRefresh() {
        Intent intent = new Intent(this, GCMRegistrationIntentService.class);
        startService(intent);
    }
}

用于获取我的GCM令牌的类:

   in oncreate {
    //Initializing our broadcast receiver
    mRegistrationBroadcastReceiver = new BroadcastReceiver() {

        //When the broadcast received
        //We are sending the broadcast from GCMRegistrationIntentService

        @Override
        public void onReceive(Context context, Intent intent) {
            //If the broadcast has received with success
            //that means device is registered successfully
            if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_SUCCESS)){
                //Getting the registration token from the intent
                String token = intent.getStringExtra("token");
                StaticContents.Gcm_token=token;
                Log.e("Token",""+token);
                //Displaying the token as toast
                Toast.makeText(getApplicationContext(), "Registration token:" + token, Toast.LENGTH_LONG).show();

                //if the intent is not with success then displaying error messages
            } else if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_ERROR)){
                //        Toast.makeText(getApplicationContext(), "GCM registration error!", Toast.LENGTH_LONG).show();
            } else {
                //          Toast.makeText(getApplicationContext(), "Error occurred", Toast.LENGTH_LONG).show();
            }
        }
    };

    //Checking play service is available or not
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());

    //if play service is not available
    if(ConnectionResult.SUCCESS != resultCode) {
        //If play service is supported but not installed
        if(GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
            //Displaying message that play service is not installed
            //        Toast.makeText(getApplicationContext(), "Google Play Service is not install/enabled in this device!", Toast.LENGTH_LONG).show();
            GooglePlayServicesUtil.showErrorNotification(resultCode, getApplicationContext());

            //If play service is not supported
            //Displaying an error message
        } else {
            //          Toast.makeText(getApplicationContext(), "This device does not support for Google Play Service!", Toast.LENGTH_LONG).show();
        }

        //If play service is available
    } else {
        //Starting intent to register device
        Intent itent = new Intent(this, GCMRegistrationIntentService.class);
        startService(itent);
    }
}
 //Registering receiver on activity resume
@Override
protected void onResume() {
    super.onResume();
    Log.w("MainActivity", "onResume");
    LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
            new IntentFilter(GCMRegistrationIntentService.REGISTRATION_SUCCESS));
    LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
            new IntentFilter(GCMRegistrationIntentService.REGISTRATION_ERROR));
}

    //Unregistering receiver on activity paused
@Override
protected void onPause() {
    super.onPause();

LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);

}

输出1:当应用程序可见(前台)时,只会收到一条通知。

enter image description here

输出2:当应用程序关闭或应用程序在后台时,会收到2个通知。

enter image description here


你能展示一下你的日志,看看出了什么错误吗?如果可能的话,请使用FCM而不是GCM。 - Jaydip Umaretiya
@JaydipUmaretiya,实际上它运行良好,问题是当应用程序在前台时,我只收到一次通知,但当应用程序在后台或未打开时,我会收到相同的通知两次,先生。 - Abhishek Punia
嗨。你能展示一个示例有效载荷吗?目前,我认为问题是你在onMessageReceived()中调用了两个sendNotification()。我不确定的是为什么它只在后台发生。 - AL.
1
您可以编辑您的帖子并将样本有效载荷作为文本包含其中,然后将其格式化为代码。:) 我明白了。这是发生在多个设备上还是仅发生在特定设备上? - AL.
这很奇怪。你能试试两件事吗?第一是删除/注释掉第一个 sendNotification()。第二是仔细检查你的清单文件是否像文档中所示正确格式化了。但最终,如果还是不行,尝试使用FCM,看看是否出现相同的行为。 - AL.
显示剩余3条评论
2个回答

0

你可以使用 FCM 下行,而不是上行


0
1. 当你从GCM接收到一条消息时,GCMPushReceiverService类中的onMessageReceived函数将被调用。

使用这个:

String message = data.getString("message");

你正在解析并将消息存储在名为message的变量中。

问题在于你正在将message传递给两个函数。

sendNotification(this,message, "Traccar App");
sendNotification(message);

这两个函数都是用于构建通知并将您传递给它们的消息作为2个单独的通知显示。

只需注释掉其中一个函数并进行检查即可。

2. 为了避免重复通知,我们可以采取一种处理方式。 尝试更改此处 -

PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);

PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);

如果问题仍然存在,请发布您正在收到的有效载荷。我建议使用FCM而不是GCM。

我一个一个地注释了代码 sendNotification(this, message, "Traccar App"); sendNotification(message); 但结果是一样的。 - Abhishek Punia
它仍然是同一个兄弟。 - Abhishek Punia
这是一个罕见的问题,我第一次见到它,也是一个有趣的问题。我想要重现它并找出原因。或者您是否尝试使用 FCM?今天您应该选择 FCM 而不是 GCM。 - Asutosh Panda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接