evollu / react-native-fcm

react native module for firebase cloud messaging and local notification
MIT License
1.73k stars 682 forks source link

How can I access the notification data #58

Closed miczed closed 6 years ago

miczed commented 8 years ago

Hi

First of all I'd like to thank you for developing this project! I am currently getting started with react-native / firebase development and so far I am amazed by the amount of available open source code and the community.

However since I am only getting started I am quite confused with the whole push notification / FCM concept.

I followed this tutorial and the one in the readme of this repo. I am able to send notifications from the firebase console and they are displayed as a notification on the iPhone but only if the app is running in the background.

I've read the readme and had a look at your code sample but couldn't figure it out on my own. Any help or a link for further reading would be highly appreciated.

Thanks, Michael

evollu commented 8 years ago
miczed commented 8 years ago

Thank you evollu for your response.

I implemented FCM.on('notification',this._onNotification); and tried to log the notification to the console which didn't work. The function is called and I am passing notif as a parameter however if I am trying to access notif.data or notif.notification I am getting undefined.

_onNotification(notif) {
    console.log('Got Notification!');
    console.log(notif.data);
    console.log(notif.notification);
}

I am sorry if I am getting something wrong but some example code would really help me or is there another documentation somewhere?

evollu commented 8 years ago

console.log(notif) to see what is inside. Data structure is different from your payload sent to FCM server

miczed commented 8 years ago

Ok, that did the trick, thank you very much! I could access the data with notif.aps.alert.title and notif.aps.alert.body.

One more question: How and when can I access FCM.initialData? I tried to log it to the console in my componentDidMount() function but I am getting null even if I sent a push notification and the app was closed.

evollu commented 8 years ago

it contains data when you init the application by clicking push notification

evollu commented 8 years ago

if you want to add some logic based on notification, use data object or click_action field. Don't rely on title and body because Android version doesn't supply that

miczed commented 8 years ago

Ok, thanks again and thanks for the information about data and click_action.

So when my app is closed and I click on a notification the app is opened and I can access the data. But what happens when the user opens the app after he got a notification but doesn't actually click on the notification? Is there a way to catch that case too?

The notification gets deleted automatically when I open the app by clicking on the app icon on the homescreen but FCM.initialData is still null.

evollu commented 8 years ago

nope :) what are you trying to do with the notification?

miczed commented 8 years ago

I need to send a message to the user whenever some event on the server happens and the user should be able to read the message even when he opens the app without clicking on the notification.

So basically the following is possible:

and the following isn't:

So in the latter cases the information from the push notification is lost? The notification isn't displayed by iOs anymore aswell...

evollu commented 8 years ago

I don't know any app is doing the last case. If you have received multiple notifications regarding messages, which message do you show then? What if user cleared all notifications before opening the app?

miczed commented 8 years ago

I thought apps like WhatsApp / Telegram are doing it like this but I guess they have some additional logic running in the app to fetch the data from the server. I thought I could send all the data over push notifications but obviously that's not possible.

So the data from the notification is actually lost when the user deletes it or opens the app without clicking it? Sounds kinda strange to me but if it is that way then I'll need to find another way to inform my user in the app itself after opening it.

evollu commented 8 years ago

right, that is the case. You can consider using background sync

studiobrain commented 8 years ago

Pardon the interruption! By the way, excellent package, and much appreciated!

I am having a similar issue, so I wanted to bring some of my own experiences to maybe shed some new light.

currently via Android:

componentDidMount() {
    FCM.on('notification', (notif) => {
      console.log(notif)  //{ Item: 'cool', Another: 'cooler' }
    })
}

logs only the custom data (key/value pairs). Is it not possible to retrieve the Message text and Message label via Android?

I am using only react-native log-android for logs, so possibly it doesnt give all of the params from notif? Also, I am only receiving the log, no push notification received, but that could be due to running in develop mode (device plugged in) and not as an actual application. Any direction or point of reference you can offer is greatly appreciated, so thanks in advance and thanks for the hard work!

evollu commented 8 years ago

it is possible only when app is in foreground, otherwise no. Notification data is processed by FCM and gone.

studiobrain commented 8 years ago

Thanks for the quick response! I have the app in the foreground but the log is still only the portion sent from firebase: advanced options/custom data. Is there a way to grab: onMessageReceived() response, or is there something more I am missing?

evollu commented 8 years ago

I didn't expose them to JavaScript because I didn't find usage of it. you can get it in message.getNotification().getTitle()

evollu commented 8 years ago

@studiobrain if you need it, a pull is welcomed

studiobrain commented 8 years ago

Sorry, I got caught up in another project (day job stuff). I would be glad to. Let me get it out to you. I havent been able to get the title or body via:

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "Remote message received");
        Intent i = new Intent("com.evollu.react.fcm.ReceiveNotification");
        i.putExtra("data", remoteMessage.getNotification().getTitle());
        sendOrderedBroadcast(i, null);
    }
evollu commented 8 years ago

that looks good. can you put the parse logic into module.java file and put the information into the fcm property together with action?

studiobrain commented 8 years ago

Update:

private void registerMessageHandler() {
        Log.d(TAG, "registerMessageHandler");
        IntentFilter intentFilter = new IntentFilter("com.evollu.react.fcm.ReceiveNotification");

        getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
            if (getReactApplicationContext().hasActiveCatalystInstance()) {
                RemoteMessage message = intent.getParcelableExtra("data");
                String title = message.getNotification().getTitle();
                String body = message.getNotification().getBody();
                WritableMap params = Arguments.createMap();
                if (message.getData() != null){
                    Map data = message.getData();
                    WritableMap wrapper = Arguments.createMap();
                    Set<String> keysIterator = data.keySet();
                    for(String key: keysIterator){
                        wrapper.putString(key, (String) data.get(key));
                    }
                    params.putMap("data", wrapper);
                }
                if (title != null) {
                    params.putString("title", title);
                }
                if (body != null) {
                    params.putString("body", body);
                }
                Log.d(TAG, "FCMNotificationReceived: " + String.valueOf(params));
                sendEvent("FCMNotificationReceived", params);
                abortBroadcast();
            }
          }
        }, intentFilter);
    }

The above updates expose the title, body and data (key, value) pairs to javascript for app in the foreground and wraps the data when in the background:

FCM.on('notification', (notif) => {
    console.log(notif)
})

// { 
//   body: 'Firebase console Message text',
//   title: 'Firebase console Advanced options Title',
//   data: {
//     key: 'value',
//     key: 'vale'
//   }
// }

...

sajjad26 commented 8 years ago

Hi, I am using this with ReactNative 0.31 on Android and the FCM.on('notification', (notif) => { console.log(notif) }) is simply not working at all, i have tried in with app in the background, foreground or killed. However the FCM.initialData seems to be working as it receives the data when the app is not in foreground and the notification is clicked. This is my manifest file, please point me in the right direction if I am doing something wrong.

<!-- React Native FCM -->
        <intent-filter>
          <action android:name="fcm.ACTION.HELLO" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <service android:name="com.evollu.react.fcm.MessagingService">
          <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
          </intent-filter>
        </service>
        <service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
          <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
          </intent-filter>
        </service>
        <!-- React Native FCM END -->
componentDidMount(){
    var self = this;
    FCM.getFCMToken().then(token => {
      console.log(token) // works
    });
    FCM.on('notification', (notif) => { console.log(notif) }); // does not work
    console.log(FCM.initialData); // works
  }
evollu commented 8 years ago

@sajjad26 FCM.on('notification' only gets triggered when you have data property. I assume you are sending with firebase console which only has notification property by default?

sajjad26 commented 8 years ago

@evollu no I am sending the extra data from the advanced tab in the firebase console. Plus I was using gcm push notifications before and I have a bunch of those tokens, Will those old tokens work with firebase or not, off topic but just asking since you are the expert :)

evollu commented 7 years ago

sorry for so late reply. GCM token are different from FCM token. closing this. reopen if you have further questions

kaberibasu commented 7 years ago

I dont know what i am doing wrong, but I am not getting any data when i click on notification in android. My setting is- `FCM.requestPermissions(); // for iOS FCM.getFCMToken().then(token => { let tokenData: FirebaseToken = { firebaseToken: token }; storeFireBaseToken(tokenData).then((done) => { }); console.log(token); // store fcm token in your server }); FCM.getInitialNotification().then(notif => { // for android only console.log(notif);

    });

    this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => {
        // there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
        if (notif.local_notification) {
            // iOS only
            // this is a local notification
        }
        if (notif.fcm) {
            FCM.presentLocalNotification({                               // (optional for instant notification)
                title: notif.senderName,                     // as FCM payload
                body: notif.fcm.body,                    // as FCM payload (required)
                sound: "default",                                   // as FCM payload
                priority: "high",                                   // as FCM payload// Android only, LED blinking (default false)
                show_in_foreground: true                                 // notification when app is in foreground (local & remote)
            });
        }
    });
    this.refreshTokenListener = FCM.on(FCMEvent.RefreshToken, (token) => {
        console.log(token);
        // fcm token may not be available on first load, catch it here
    });`

When I recieve notification, I get a call here "FCM.on(FCMEvent.Notification, async (notif)" and in notif i get data. have to implement this- FCM.presentLocalNotification({ // (optional for instant notification) title: notif.senderName, // as FCM payload body: notif.fcm.body, // as FCM payload (required) sound: "default", // as FCM payload priority: "high", // as FCM payload// Android only, LED blinking (default false) show_in_foreground: true // notification when app is in foreground (local & remote) }); to show a local notification when ap is foreground.

But when user clicks on the notification, whether the app is in BACKGROUND or FOREGROUND or KILLED, i get a call in getInitialNotification, and in its callback, i get no data. @evollu please tell me what I am doing wrong.

MbF-Sathya commented 6 years ago

how can i access the response data in react native android

firebase.messaging().onMessage((message) => { alert(2) console.log(message); AsyncStorage.setItem('xxxxId', message._data.xxxxId.toString()); setTimeout(() => { Actions.screeThree({type:'replace'}); }, 500); });

i dont think its correct but i am not getting anything related to that @evollu here is my stack question link

https://stackoverflow.com/questions/47672334/react-native-handling-data-in-react-native-android-notification

evollu commented 6 years ago

@MbF-Sathya firebase.messaging() you are using react-firebase-stack?

this is how to listen on events using this library.

FCM.on(FCMEvent.Notification, (notif)=>{
  //logic
}
MbF-Sathya commented 6 years ago

@evollu did you see my stack link... for android is this right method to handle data? for iOS its coming exactly what i expect....it says FCM is not defined .... i need to import anything with FCM related? here is my

firebase.js

file

`import RNFirebase from 'react-native-firebase';

const config = {
    apiKey: 'sampleapikey', 
    authDomain: 'com.sample.example.com',
    messagingSenderId: '123456789 ',
    debug: true,
    promptOnMissingPlayServices: true,
};

const firebase = RNFirebase.initializeApp(config)`

i am importing this file to my

app.js

like this

import firebase from '../../firebase'; @evollu

evollu commented 6 years ago

@MbF-Sathya this library is react-native-fcm, not react-native-firebase

MbF-Sathya commented 6 years ago

@evollu so i am using react-native-firebase npm can i get any reference for this?

evollu commented 6 years ago

@MbF-Sathya https://github.com/invertase/react-native-firebase

prasanthyejje commented 6 years ago

i'm using https://github.com/evollu/react-native-fcm for FCM. Now i am able to receive notifications but i want to prevent the notifications displaying in mobile notification bar ..how Can i do this.. please help me @evollu

evollu commented 6 years ago

@prasanthyejje what OS

prasanthyejje commented 6 years ago

@evollu Targeting Mobile OS: Android RN version:0.51 My PC :Windows7, 64 bit, Dependencies: compile 'com.google.firebase:firebase-core:11.8.0'

evollu commented 6 years ago

if you want to not showing the banner, you can set priority: 'low' if you don't want it to show in notification tray, I don't know... perhaps delete it after you receive it?

prasanthyejje commented 6 years ago

thanks @evollu for your response . And one more thing, is there any possibility to set a tone for notification(it should be same for every user.. ) ..??. if it is please let me know ..

Thank you,

evollu commented 6 years ago

yes, though sound property

Keyur-Rao commented 9 months ago

Issue: I was getting remoteData from messaging().getInitialNotification() and messaging().setBackgroundHandler() also not register. solution: https://github.com/react-native-firebase, @react-native-firebase/messaging is conflict with https://github.com/notifee i simplly remove notifee module and it's works for me..