react-native-push-notification: Can't receive notifications when app is closed or in background

manifest file:

<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
        android:name="co.my.packagename.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
<uses-permission android:name="co.my.packagename.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

in the application: <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

    `<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="co.my.packagename" />
        </intent-filter>
    </receiver>`

    <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
    <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>


    <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>

    <service
            android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
            android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>

settings.gradle:

include ':app' ... include ':react-native-push-notification' project(':react-native-push-notification').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-push-notification/android')

build.gradle:

dependencies {
    classpath 'com.android.tools.build:gradle:1.2.0'

}

`

app/build.gradle ` dependencies { compile fileTree(dir: “libs”, include: [“*.jar”]) compile “com.android.support:appcompat-v7:23.0.1” compile ‘com.android.support:support-v4:19.1.+’ … compile project(‘:react-native-push-notification’)

compile ('com.google.android.gms:play-services-gcm:8.1.0')

}

Mainapp.java

import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;

@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), ... new ReactNativePushNotificationPackage() ); } };

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 34 (4 by maintainers)

Commits related to this issue

Most upvoted comments

My app receives GCM push notifications when it is in the background, tested on Android 4.1 and 5.1.

It doesn’t receive push notifications when its not running though. Although, I’m not sure that feature is supported yet.

bump

I had the same problem when I was testing PN. Logcat error:

Cannot send to notification centre because there is no 'message' field in: Bundle

Just added message field and it worked.

Finally solved the sh*t out of this ! I know it’s probalbly very hacky but it works. Modify the content of node_modules/react-native-push-notification/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java as follow :

package com.dieam.reactnativepushnotification.modules;

import android.app.Activity;
import android.app.Application;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import com.dieam.reactnativepushnotification.helpers.ApplicationBadgeHelper;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class RNPushNotification extends ReactContextBaseJavaModule implements ActivityEventListener {
    public static final String LOG_TAG = "RNPushNotification";// all logging should use this tag

    private RNPushNotificationHelper mRNPushNotificationHelper;
    private final Random mRandomNumberGenerator = new Random(System.currentTimeMillis());
    private RNPushNotificationJsDelivery mJsDelivery;

    private Bundle savedBundle = null;

    public RNPushNotification(ReactApplicationContext reactContext) {
        super(reactContext);

        reactContext.addActivityEventListener(this);

        Application applicationContext = (Application) reactContext.getApplicationContext();
        // The @ReactNative methods use this
        mRNPushNotificationHelper = new RNPushNotificationHelper(applicationContext);
        // This is used to delivery callbacks to JS
        mJsDelivery = new RNPushNotificationJsDelivery(reactContext);

        registerNotificationsRegistration();
    }

    @Override
    public String getName() {
        return "RNPushNotification";
    }

    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();

        return constants;
    }

    public void onNewIntent(Intent intent) {
        if(intent.hasExtra("google.message_id")){
            Bundle bundle = intent.getExtras();
            bundle.putBoolean("foreground", false);
            intent.putExtra("notification", bundle);
            this.savedBundle =  bundle;
            mJsDelivery.notifyNotification(bundle);
        }

        if (intent.hasExtra("notification")) {
            Bundle bundle = intent.getBundleExtra("notification");
            bundle.putBoolean("foreground", false);
            intent.putExtra("notification", bundle);
            mJsDelivery.notifyNotification(bundle);
        }
    }

    private void registerNotificationsRegistration() {
        IntentFilter intentFilter = new IntentFilter(getReactApplicationContext().getPackageName() + ".RNPushNotificationRegisteredToken");

        getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String token = intent.getStringExtra("token");
                WritableMap params = Arguments.createMap();
                params.putString("deviceToken", token);

                mJsDelivery.sendEvent("remoteNotificationsRegistered", params);
            }
        }, intentFilter);
    }

    private void registerNotificationsReceiveNotificationActions(ReadableArray actions) {
        IntentFilter intentFilter = new IntentFilter();
        // Add filter for each actions.
        for (int i = 0; i < actions.size(); i++) {
            String action = actions.getString(i);
            intentFilter.addAction(getReactApplicationContext().getPackageName() + "." + action);
        }
        getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Bundle bundle = intent.getBundleExtra("notification");

                // Notify the action.
                mJsDelivery.notifyNotificationAction(bundle);

                // Dismiss the notification popup.
                NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
                int notificationID = Integer.parseInt(bundle.getString("id"));
                manager.cancel(notificationID);
            }
        }, intentFilter);
    }

    @ReactMethod
    public void requestPermissions(String senderID) {
        ReactContext reactContext = getReactApplicationContext();

        Intent GCMService = new Intent(reactContext, RNPushNotificationRegistrationService.class);

        GCMService.putExtra("senderID", senderID);
        reactContext.startService(GCMService);
    }

    @ReactMethod
    public void presentLocalNotification(ReadableMap details) {
        Bundle bundle = Arguments.toBundle(details);
        // If notification ID is not provided by the user, generate one at random
        if (bundle.getString("id") == null) {
            bundle.putString("id", String.valueOf(mRandomNumberGenerator.nextInt()));
        }
        mRNPushNotificationHelper.sendToNotificationCentre(bundle);
    }

    @ReactMethod
    public void scheduleLocalNotification(ReadableMap details) {
        Bundle bundle = Arguments.toBundle(details);
        // If notification ID is not provided by the user, generate one at random
        if (bundle.getString("id") == null) {
            bundle.putString("id", String.valueOf(mRandomNumberGenerator.nextInt()));
        }
        mRNPushNotificationHelper.sendNotificationScheduled(bundle);
    }

    @ReactMethod
    public void getInitialNotification(Promise promise) {
        WritableMap params = Arguments.createMap();
        Activity activity = getCurrentActivity();
        if (activity != null) {
            Intent intent = activity.getIntent();
            Bundle bundle = null;

            if (intent.hasExtra("notification")) {
                bundle = intent.getBundleExtra("notification");
            } else if (intent.hasExtra("google.message_id")) {
                bundle = intent.getExtras();
            }

            if (this.savedBundle != null){
                bundle = savedBundle;
                this.savedBundle = null;
            }

            if (bundle != null) {
                bundle.putBoolean("foreground", false);
                String bundleString = mJsDelivery.convertJSON(bundle);
                params.putString("dataJSON", bundleString);
            }
        }
        promise.resolve(params);
    }

    @ReactMethod
    public void setApplicationIconBadgeNumber(int number) {
        ApplicationBadgeHelper.INSTANCE.setApplicationIconBadgeNumber(getReactApplicationContext(), number);
    }

    // removed @Override temporarily just to get it working on different versions of RN
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        onActivityResult(requestCode, resultCode, data);
    }

    // removed @Override temporarily just to get it working on different versions of RN
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Ignored, required to implement ActivityEventListener for RN 0.33
    }

    @ReactMethod
    /**
     * Cancels all scheduled local notifications, and removes all entries from the notification
     * centre.
     *
     * We're attempting to keep feature parity with the RN iOS implementation in
     * <a href="https://github.com/facebook/react-native/blob/master/Libraries/PushNotificationIOS/RCTPushNotificationManager.m#L289">RCTPushNotificationManager</a>.
     *
     * @see <a href="https://facebook.github.io/react-native/docs/pushnotificationios.html">RN docs</a>
     */
    public void cancelAllLocalNotifications() {
        mRNPushNotificationHelper.cancelAllScheduledNotifications();
        mRNPushNotificationHelper.clearNotifications();
    }

    @ReactMethod
    /**
     * Cancel scheduled notifications, and removes notifications from the notification centre.
     *
     * Note - as we are trying to achieve feature parity with iOS, this method cannot be used
     * to remove specific alerts from the notification centre.
     *
     * @see <a href="https://facebook.github.io/react-native/docs/pushnotificationios.html">RN docs</a>
     */
    public void cancelLocalNotifications(ReadableMap userInfo) {
        mRNPushNotificationHelper.cancelScheduledNotification(userInfo);
    }

    @ReactMethod
    public void registerNotificationActions(ReadableArray actions) {
        registerNotificationsReceiveNotificationActions(actions);
    }
}


Maybe I’ll do a proper PR when I have time.

This turned out to be very simple. PushNotification.configure goes into componentDidMount inside your index.js. This will generate a unique device token that you can copy from the console log and use in the server code to send notification to this specific device.

The trick is to add PushNotification.localNotification() inside onNotification, so that once a remote notif is received, it is converted into local one. Unfortunately, the documentation doesn’t make this part clear but a remote notif won’t go into the device notifs centre unless it’s converted to local.

componentDidMount(){
PushNotification.configure({
      // (optional) Called when Token is generated (iOS and Android)
      onRegister: function(token) {
         // alert('TOKEN:' + JSON.stringify(token) );
          console.log(token);
      },
      onNotification: function(notification) {
          console.log( 'NOTIFICATION:', notification );
          //alert(JSON.stringify(notification));

        PushNotification.localNotification({
          title: notification['gcm.notification.title'],
          message: notification['gcm.notification.body'], // (required)
          subText: notification['gcm.notification.subText'],
          tag: notification['gcm.notification.tag'],
          group: notification['gcm.notification.group'],
        });
      },
      senderID: "your_fcm_senderID",
      popInitialNotification: true,
      requestPermissions: true,
    });
    
  }

I can see the notification when the app is closed but as soon as I click on it and open the app the onNotification doesn’t fire again. I have everything set like the instructions.

@npomfret do you got it working?

Neither I get notifications when the app is closed. I get them when the app is in the foreground or in the background, but not when it is closed.

When the app is closed, adb logcat spits out:

11-02 20:05:10.578 11769 11769 W GCM-DMM : broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.CENSORED (has extras) }

Does it matter if I’m using local notification?

Done! Push Notifications are showing up, even when app is completely closed. Just had to update to the current version of this module, react and react-native and then import and place PushNotification.configure directly inside the index.android.js (even before the component class), similar to the link @oddball posted.