1

I'm trying to push notifications to the end-users of the app when post is uploaded. It works fine when the app is in foreground and background but doesn't show up when then the app is killed or closed(not in background and foreground). Is there any way to show the notifications when the app is closed. Here is the index.js code which i deployed to firebase functions.

const functions = require('firebase-functions');
let admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendPush = functions.database.ref('/promos').onWrite(event => {
var topic = "deals_notification";
let projectStateChanged = false;
let projectCreated = false;
let projectData = event.data.val();

if (((event.data.numChildren())-(event.data.previous.numChildren()))>0) {
    let msg="notification arrived"
  let payload = {
        data: {
             "msg":msg
        }
    };

admin.messaging().sendToTopic(topic, payload).then(function(response) {
console.log("Successfully sent message:", response);
}).catch(function(error) {
console.log("Error sending message:", error);
});
}
});

and here is the MyFirebaseMessageService:

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessageService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);

    sendnotification(remoteMessage.getData().get("msg"));
}
private void sendnotification(String body){
    Intent intent = new Intent(this, MainActivity.class);

  PendingIntent pIntent = PendingIntent.getActivity(this,0, intent, 0);
    Notification.Builder n  = new Notification.Builder(this)
            .setContentTitle("Best Deals")
            .setContentText(body)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pIntent)
            .setAutoCancel(true);

    NotificationManager manager = (NotificationManager) 
    getSystemService(Context.NOTIFICATION_SERVICE);
    manager.notify(0, n.build());
}
}

edit:Here is Manifest file.

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.priya.bestdeals">

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<application
    android:name=".Application"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.NoActionBar"></activity>
    <activity android:name=".LoginActivity" />
    <activity android:name=".RegisterActivity" />
    <activity android:name=".Details">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="MainActivity" />
    </activity>
    <activity android:name=".Posts" />
    <activity android:name=".Settings" />
    <activity android:name=".Postdetails" />
    <activity android:name=".IntroActivity" />
    <activity
        android:name=".SplashScreen"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Black.NoTitleBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".WriteActivity">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="MainActivity" />
    </activity>
    <activity android:name=".DeleteActivity">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="MainActivity" />
    </activity>
    <activity android:name=".EditProfile"></activity>
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_notifications_black_24dp" />

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />
    <service
        android:name=".MyFirebaseInstanceIdService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>
    <service
        android:name=".MyFirebaseMessageService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

</application>

Thanks.

AL.
  • 36,815
  • 10
  • 142
  • 281
maneesh
  • 216
  • 3
  • 14
  • Make sure to register your receiver in your manifest – portfoliobuilder Jun 21 '17 at 17:45
  • Thanks for the support. I have added manifest in the edit. I'm new to using firebase notifications. Can you mention what changes should i make to manifest so that notification is received when app is closed. @portfoliobuilder – maneesh Jun 21 '17 at 17:56
  • See my answer [here](https://stackoverflow.com/a/39505298/4625829) (also included in @BobSnyder's answer). – AL. Jun 22 '17 at 02:47

2 Answers2

1

You need to specify priority: "high" in an options object for your call to sendToTopic(). This will wake the device up to receive the message if it is in idle/Doze mode:

const options = {
  priority: "high"
};

admin.messaging().sendToTopic(topic, payload, options).then(...);

If sending the message with high priority doesn't help, then you may be testing on one of the models of phones that puts an app in Stopped State when it is killed in certain ways (such as swiping from the recent tasks list). See this answer for more details.

This answer contains a solution for Huawei/EMOI devices. You can whitelist your app to exempt it from being force-stopped: Advanced Settings > Battery > Protected Apps.

Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • I updated code according to your suggestions.But still app doesn't show any notifications when it is closed. I tried this in 3 different mobiles but still the result is same. Could you please suggest any more changes so that app shows notification even when it is closed. – maneesh Jun 22 '17 at 07:08
0

Actually you accessing RemoteMessage in wrong way.

 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getFrom());

        if (remoteMessage == null)
            return;

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
            handleNotification(remoteMessage.getNotification().getBody());
        }
}

private void handleDataMessage(JSONObject json) {
        Log.e(TAG, "push json: " + json.toString());

        try {
            JSONObject data = json.getJSONObject("data");

            String title = data.getString("title");
            String message = data.getString("message");
            boolean isBackground = data.getBoolean("is_background");
            String imageUrl = data.getString("image");
            String timestamp = data.getString("timestamp");
            JSONObject payload = data.getJSONObject("payload");

            Log.e(TAG, "title: " + title);
            Log.e(TAG, "message: " + message);
            Log.e(TAG, "isBackground: " + isBackground);
            Log.e(TAG, "payload: " + payload.toString());
            Log.e(TAG, "imageUrl: " + imageUrl);
            Log.e(TAG, "timestamp: " + timestamp);


            sendNotification(title,message);


            } catch (JSONException e) {
            Log.e(TAG, "Json Exception: " + e.getMessage());
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
}
private void sendNotification(String title,String message) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .setContentTitle(title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

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

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

For more detail see official example by google

https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java#L45-L82

Mahesh Lad
  • 1,997
  • 1
  • 9
  • 8