Pushwoosh and Android Phonegap App not communicating - android
The Problem
Okay so I have a Phonegap (2.3.0) android application with Pushwoosh to manage the push notifications. I followed the instructions, and got an app with only a few wording errors working. The app itself seems to run perfectly fine, however it doesn't seem like Pushwoosh is pushing anything to GCM (Google Cloud Messanger), which it turn isn't pushing anything to the app. Now that is what I think is wrong, however this is my first time using GCM and Pushwoosh.
On the Pushwoosh console page it shows each "push" as completed with no errors, but then on my GCM console it doesn't show any requests, nor do any notification pop up on my phone.
I have the GCM API key (server key) in my XML and my Pushwoosh is the correct XXXXX-XXXXX key. Here is my code to better outline how my code is setup (and maybe someone can see what I'm missing).
The Code
Here is the AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--library-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- GCM connects to Google Services. -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!--
Creates a custom permission so only this app can receive its messages.
NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
where PACKAGE is the application's package name.
-->
<permission
android:name="com.springmobile.employee.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission
android:name="com.springmobile.employee.permission.C2D_MESSAGE"/>
<!-- This app has permission to register and receive data message. -->
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE"/>
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name" android:allowBackup="true">
<!--
Service for sending location updates
-->
<service android:name="com.arellomobile.android.push.GeoLocationService"/>
<intent-filter>
<action android:name="com.springmobile.employee.MESSAGE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<activity android:name="com.arellomobile.android.push.PushWebview"/>
<activity android:name="com.arellomobile.android.push.MessageActivity"/>
<activity android:name="com.arellomobile.android.push.PushHandlerActivity"/>
<!--
BroadcastReceiver that will receive intents from GCM
services and handle them to the custom IntentService.
The com.google.android.c2dm.permission.SEND permission is necessary
so only GCM services can send data messages for the app.
-->
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.springmobile.employee"/>
</intent-filter>
</receiver>
<!--
Application-specific subclass of PushGCMIntentService that will
handle received messages.
-->
<service android:name="com.arellomobile.android.push.PushGCMIntentService"/>
<activity android:name="org.apache.cordova.example.cordovaExample" android:label="#string/app_name"
android:theme="#android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Here is my Phonegap plugin config.XML
<plugins>
<plugin name="PushNotification" value="com.pushwoosh.plugin.pushnotifications.PushNotifications" onload="true"/>
</plugins>
Here is the JS for my Phonegap page to initialize and listen for the Pushwoosh Notification.
function initPushwoosh()
{
var pushNotification = window.plugins.pushNotification;
pushNotification.onDeviceReady();
pushNotification.registerDevice({ projectid: "I_HAVE_MY_PROJECT_ID_HERE", appid : "THIS_IS_MY_PUSHWOOSH_ID" },
function(status) {
var pushToken = status;
console.warn('push token: ' + pushToken);
},
function(status) {
console.warn(JSON.stringify(['failed to register ', status]));
}
);
document.addEventListener('push-notification', function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
if(typeof(userData) != "undefined") {
console.warn('user data: ' + JSON.stringify(userData));
}
navigator.notification.alert(title);
});
}
function init() {
document.addEventListener("deviceready", initPushwoosh, true);
//rest of the code
document.addEventListener('push-notification', function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
console.warn('user data: ' + JSON.stringify(userData));
navigator.notification.alert(title);
});
}
function initPushwoosh()
{
var pushNotification = window.plugins.pushNotification;
pushNotification.onDeviceReady();
document.addEventListener('push-notification', function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
if(typeof(userData) != "undefined") {
console.warn('user data: ' + JSON.stringify(userData));
}
navigator.notification.alert(title);
pushNotification.stopGeoPushes();
});
}
function registerPushwoosh()
{
var pushNotification = window.plugins.pushNotification;
//projectid: "GOOGLE_PROJECT_ID", appid : "PUSHWOOSH_APP_ID"
pushNotification.registerDevice({ projectid: "1039894503284", appid : "EE861-B95A3" },
function(token) {
alert(token);
onPushwooshInitialized(token);
},
function(status) {
alert("failed to register: " + status);
console.warn(JSON.stringify(['failed to register ', status]));
});
}
function unregisterPushwoosh()
{
var pushNotification = window.plugins.pushNotification;
pushNotification.unregisterDevice(function(token) {
alert("unregistered, old token " + token);
},
function(status) {
alert("failed to unregister: " + status);
console.warn(JSON.stringify(['failed to unregister ', status]));
});
}
//set the settings for Pushwoosh or set tags, this must be called only after successful registration
function onPushwooshInitialized(pushToken)
{
//output the token to the console
console.warn('push token: ' + pushToken);
var pushNotification = window.plugins.pushNotification;
//set multi notificaiton mode
//pushNotification.setMultiNotificationMode();
//set single notification mode
//pushNotification.setSingleNotificationMode();
//disable sound and vibration
//pushNotification.setSoundType(1);
//pushNotification.setVibrateType(1);
pushNotification.setLightScreenOnNotification(false);
//goal with count
//pushNotification.sendGoalAchieved({goal:'purchase', count:3});
//goal with no count
//pushNotification.sendGoalAchieved({goal:'registration'});
//setting list tags
//pushNotification.setTags({"MyTag":["hello", "world"]});
//settings tags
pushNotification.setTags({deviceName:"hello", deviceId:10},
function(status) {
console.warn('setTags success');
},
function(status) {
console.warn('setTags failed');
});
function geolocationSuccess(position) {
pushNotification.sendLocation({lat:position.coords.latitude, lon:position.coords.longitude},
function(status) {
console.warn('sendLocation success');
},
function(status) {
console.warn('sendLocation failed');
});
};
// onError Callback receives a PositionError object
//
function geolocationError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
function getCurrentPosition() {
navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError);
}
//greedy method to get user position every 3 second. works well for demo.
// setInterval(getCurrentPosition, 3000);
//this method just gives the position once
// navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError);
//this method should track the user position as per Phonegap docs.
// navigator.geolocation.watchPosition(geolocationSuccess, geolocationError, { maximumAge: 3000, enableHighAccuracy: true });
//Pushwoosh Android specific method that cares for the battery
pushNotification.startGeoPushes();
}
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicity call 'app.receivedEvent(...);'
onDeviceReady: function() {
initPushwoosh();
app.receivedEvent('deviceready');
//optional: create local notification alert
//var pushNotification = window.plugins.pushNotification;
//pushNotification.clearLocalNotification();
//pushNotification.createLocalNotification({"msg":"message", "seconds":30, "userData":"optional"});
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
};
Here is the PushWoosh.js code
(function(cordova) {
function PushNotification() {}
// Call this to register for push notifications and retreive a deviceToken
PushNotification.prototype.registerDevice = function(config, success, fail) {
cordova.exec(success, fail, "PushNotification", "registerDevice", config ? [config] : []);
};
// Call this to set tags for the device
PushNotification.prototype.setTags = function(config, success, fail) {
cordova.exec(success, fail, "PushNotification", "setTags", config ? [config] : []);
};
// Call this to send geo location for the device
PushNotification.prototype.sendLocation = function(config, success, fail) {
cordova.exec(success, fail, "PushNotification", "sendLocation", config ? [config] : []);
};
//Android Only----
PushNotification.prototype.unregisterDevice = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "unregisterDevice", []);
};
//config params: {msg:"message", seconds:30, userData:"optional"}
PushNotification.prototype.createLocalNotification = function(config, success, fail) {
cordova.exec(success, fail, "PushNotification", "createLocalNotification", config ? [config] : []);
};
PushNotification.prototype.clearLocalNotification = function() {
cordova.exec(null, null, "PushNotification", "clearLocalNotification", []);
};
//advanced background task to track device position and not drain the battery
PushNotification.prototype.startGeoPushes = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "startGeoPushes", []);
};
PushNotification.prototype.stopGeoPushes = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "stopGeoPushes", []);
};
//sets multi notification mode on
PushNotification.prototype.setMultiNotificationMode = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "setMultiNotificationMode", []);
};
//sets single notification mode
PushNotification.prototype.setSingleNotificationMode = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "setSingleNotificationMode", []);
};
//type: 0 default, 1 no sound, 2 always
PushNotification.prototype.setSoundType = function(type, success, fail) {
cordova.exec(success, fail, "PushNotification", "setSoundType", [type]);
};
//type: 0 default, 1 no vibration, 2 always
PushNotification.prototype.setVibrateType = function(type, success, fail) {
cordova.exec(success, fail, "PushNotification", "setVibrateType", [type]);
};
PushNotification.prototype.setLightScreenOnNotification = function(on, success, fail) {
cordova.exec(success, fail, "PushNotification", "setLightScreenOnNotification", [on]);
};
//set to enable led blinking when notification arrives and display is off
PushNotification.prototype.setEnableLED = function(on, success, fail) {
cordova.exec(success, fail, "PushNotification", "setEnableLED", [on]);
};
//{goal:'name', count:3} (count is optional)
PushNotification.prototype.sendGoalAchieved = function(config, success, fail) {
cordova.exec(success, fail, "PushNotification", "sendGoalAchieved", config ? [config] : []);
};
//Android End----
//iOS only----
PushNotification.prototype.onDeviceReady = function() {
cordova.exec(null, null, "PushNotification", "onDeviceReady", []);
};
// Call this to get a detailed status of remoteNotifications
PushNotification.prototype.getRemoteNotificationStatus = function(callback) {
cordova.exec(callback, callback, "PushNotification", "getRemoteNotificationStatus", []);
};
// Call this to set the application icon badge
PushNotification.prototype.setApplicationIconBadgeNumber = function(badge, callback) {
cordova.exec(callback, callback, "PushNotification", "setApplicationIconBadgeNumber", [{badge: badge}]);
};
// Call this to clear all notifications from the notification center
PushNotification.prototype.cancelAllLocalNotifications = function(callback) {
cordova.exec(callback, callback, "PushNotification", "cancelAllLocalNotifications", []);
};
//iOS End----
// Event spawned when a notification is received while the application is active
PushNotification.prototype.notificationCallback = function(notification) {
var ev = document.createEvent('HTMLEvents');
ev.notification = notification;
ev.initEvent('push-notification', true, true, arguments);
document.dispatchEvent(ev);
};
cordova.addConstructor(function() {
if(!window.plugins) window.plugins = {};
window.plugins.pushNotification = new PushNotification();
});
})(window.cordova || window.Cordova || window.PhoneGap);
Screenshots of GCM, Pushwoosh and Eclipse
Sorry this is lengthy but I want to make sure I have everything here. Also not enough rep to post images so links below.
GCM API server key, Pushwoosh Control Panel, and Eclipse setup
Thanks!
lets check your configuration and setup is proper for push woosh notification .Other Push notification service is also work in phone-gap you can check it out.You can find phone gap code(zip),proper documentation for configuration and setup and how to use their API using Java script
The Pushwoosh version is very important while configuring it with a phonegap application, so you need to be sure that your Pushwoosh script is compatible with Phonegap 2.3.0. If the Pushwoosh script is not correct, it will not work with your Phonegap version and I think that they only support the latest Phonegap available right now.
The GCM API key must be for Android Application, not server
I had this issue because my bundle id wasn't correct.
Be sure that your app name and the bundle id are the same in xcode and your iOS app Indentifier in https://developer.apple.com/account/ios/identifiers.
Related
React Native Push Notifications not working in Android but works fine on iOS
I've recently set up push notifications in my React Native app and it's working fine in iOs, but failing to pop up in Android. Here is the function that I'm calling to trigger the notification. function pushNotif(){ PushNotification.localNotification({ channelId: "specialid", // (required) channelId, if the channel doesn't exist, notification will not trigger. title: "hello", message: "test message" }) } and here is where I configure the push notification above // Must be outside of any component LifeCycle (such as `componentDidMount`). PushNotification.configure({ // (optional) Called when Token is generated (iOS and Android) onRegister: function (token) { console.log("TOKEN:", token); }, // (required) Called when a remote is received or opened, or local notification is opened onNotification: function (notification) { console.log("NOTIFICATION:", notification); // process the notification // (required) Called when a remote is received or opened, or local notification is opened notification.finish(PushNotificationIOS.FetchResult.NoData); }, // (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android) onAction: function (notification) { console.log("ACTION:", notification.action); console.log("NOTIFICATION:", notification); // process the action }, // (optional) Called when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a simulator. (iOS) onRegistrationError: function(err) { console.error(err.message, err); }, // IOS ONLY (optional): default: all - Permissions to register. permissions: { alert: true, badge: true, sound: true, }, // Should the initial notification be popped automatically // default: true popInitialNotification: true, /** * (optional) default: true * - Specified if permissions (ios) and token (android and ios) will requested or not, * - if not, you must call PushNotificationsHandler.requestPermissions() later * - if you are not using remote notification or do not have Firebase installed, use this: * requestPermissions: Platform.OS === 'ios' */ requestPermissions: true, }); As I said it's working fine on iOS, and when I remove the channelId (which I know is required for android) I get this message... No Channel ID Passed. Notification may not work This leads me to believe it's being configured somehow but not fully. Here are the rest of my configuration files after following this: https://github.com/zo0r/react-native-push-notification In android/build.gradle buildscript { ext { googlePlayServicesVersion = "+" // default: "+" firebaseMessagingVersion = "+" // default: "21.1.0" buildToolsVersion = "29.0.3" minSdkVersion = 21 compileSdkVersion = 30 targetSdkVersion = 30 ndkVersion = "20.1.5948944" } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:4.1.0") classpath 'com.google.gms:google-services:4.3.10' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } In android/app/src/main/AndroidManifest.xml ... <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application android:name=".MainApplication" android:label="#string/app_name" android:icon="#mipmap/ic_launcher" android:roundIcon="#mipmap/ic_launcher_round" android:allowBackup="false" android:theme="#style/AppTheme"> <!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) --> <meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground" android:value="false"/> <!-- Change the resource name to your App's accent color - or any other color you want --> <meta-data android:name="com.dieam.reactnativepushnotification.notification_color" android:resource="#color/white"/> <!-- or #android:color/{name} to use a standard color --> <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" /> <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" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/> </intent-filter> </receiver> <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService" android:exported="false" > <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> ... In android/app/src/main/java/com/{app_name}/MainActivity.java ... import com.facebook.react.ReactActivity; import android.content.Intent; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. */ #Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); } #Override protected String getMainComponentName() { return "cjcChatApp"; } } How can I get this to work on Android?
i think you forgot for create chanel, you can try this : function pushNotif(){ PushNotification.createChannel( { channelId: "specialid", // (required) channelName: "Special messasge", // (required) channelDescription: "Notification for special message", // (optional) default: undefined. importance: 4, // (optional) default: 4. Int value of the Android notification importance vibrate: true, // (optional) default: true. Creates the default vibration patten if true. }, (created) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed. ); PushNotification.localNotification({ channelId:'specialid', //his must be same with channelid in createchannel title:'hello', message:'test message' }) }
Push notification not showing in Android foreground
I've used react-native-fcm for remote notification in android and iPhone. react-native-fcm In Android foreground I'm not be able to getting remote notification in notification bar. In background mode I'm able to getting notification successfully but some how in foreground doesn't. Android Manifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nusape"> <application> <receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/> <receiver android:enabled="true" android:exported="true" android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.QUICKBOOT_POWERON"/> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#mipmap/ic_launcher"/> <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="my_default_channel"/> <service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true"> <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> <activity android:launchMode="singleTop" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="fcm.ACTION.HELLO" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> </application> </manifest> App.js async componentDidMount() { // create NotificationChannel for future use! FCM.createNotificationChannel({ id: 'my_default_channel', name: 'Default', description: 'used for example', priority: 'high' }); // initially user get InitialNotification frim the app if any pending FCM.getInitialNotification().then(notif => { console.log("getInitialNotification Notification : => ", notif); // if notif.targetScreen is details screen then it will redirect to details screen directly! if (notif && notif.targetScreen === "detail") { setTimeout(() => { this.props.navigation.navigate("Detail"); }, 500); } }); // added notification listener for getting any notification called below function then this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => { console.log("FCMEvent.Notification Notification : => ", notif); if (Platform.OS === 'ios' && notif._notificationType === NotificationType.WillPresent && !notif.local_notification) { notif.finish(WillPresentNotificationResult.All); return; } // if user tap to notification bar then open app then below condition will follow up and redirect to details screen! if (notif.opened_from_tray) { if (notif.targetScreen === 'detail') { setTimeout(() => { navigation.navigate('Detail') }, 500) } setTimeout(() => { alert(`User tapped notification\n${JSON.stringify(notif)}`) }, 500) } // check whether app is in background or foreground for generate notification if (AppState.currentState !== 'background'){ this.showLocalNotification(notif); }); // getting user permission for sending notification or not ? try { let result = await FCM.requestPermissions({ badge: true, sound: true, alert: true }); console.log("Notification requestPermissions : => ", result) } catch (e) { console.error(e); } // Generating token for particular user wise send notification FCM.getFCMToken().then(token => { FCM.subscribeToTopic("channelToTopic"); console.log("Notification token : => ", token); this.setState({ token: token || "" }); }); // Get APNSTOKEN for only ios if (Platform.OS === "ios") { FCM.getAPNSToken().then(token => { console.log("APNS TOKEN (getFCMToken)", token); }); } } // show notification when app is in foreground and getting any new notification showLocalNotification = (notif) => { FCM.presentLocalNotification({ channel: 'my_default_channel', id: new Date().valueOf().toString(), title: notif.fcm.title, body: notif.fcm.body, priority: "high", badge: 1, number: 1, ticker: "My Notification Ticker", auto_cancel: true, big_text: "Show when notification is expanded", sub_text: "This is a subText", wake_screen: true, group: "group", icon: "ic_launcher", ongoing: true, my_custom_data: "my_custom_field_value", lights: true, show_in_foreground: true }); }; I'm suffering this issue from last 2 months and not get it well solution for the same as i doing so many new attempt to resolve issue but at the end not getting any succeed.
According to the official Github of react-native-fcm, this library is depreciated. You can use the react-native-firebase for generating notification. I was able to get the notifications working in about 2 hours for android. If you want the code I can share it. good luck. Update - Sorry I couldn't answer earlier because of my office account. This is my code for showing android foreground notifications. firebase.messaging() .subscribeToTopic(this.state.user.user_name) .then(response => console.log('response from FCM TOPIC' + response)) .catch(error => console.log('error from FCM TOPIC'+ error)); this.notificationListener = firebase.notifications().onNotification(notification => { let notificationMessage = notification._android._notification._data.action; let recordId = notification._android._notification._data.recordID; let { title, body } = notification; // console.log('ttttt', notification) // notification.android.setAutoCancel(false) console.log(title, body, notificationMessage, recordId); const channelId = new firebase.notifications.Android.Channel( 'Default', 'Default', firebase.notifications.Android.Importance.High ); firebase.notifications().android.createChannel(channelId); let notification_to_be_displayed = new firebase.notifications.Notification({ data: notification._android._notification._data, sound: 'default', show_in_foreground: true, title: notification.title, body: notification.body, }); if (Platform.OS == 'android') { notification_to_be_displayed.android .setPriority(firebase.notifications.Android.Priority.High) .android.setChannelId('Default') .android.setVibrate(1000); } console.log('FOREGROUND NOTIFICATION LISTENER: \n', notification_to_be_displayed); firebase.notifications().displayNotification(notification_to_be_displayed); });
As per the library issues listed here you can try two things: just pass show_in_foreground in your data property in remote notification android shows notification only when app state is killed or background. To display notifications in app foreground, you need to show local notification. Sample code: FCM.on(FCMEvent.Notification, notif => { if (!notif.opened_from_tray) { showLocalNotification(); } }); showLocalNotification() { FCM.presentLocalNotification({ id: new Date().valueOf().toString(), // (optional for instant notification) title: "Test Notification with action", // as FCM payload body: "Force touch to reply", // as FCM payload (required) show_in_foreground: true // notification when app is in foreground (local & remote) }); } Full code is here
Which API level you are testing on ? Android API 26 and above requires channels to be created in order to receive notifications in foreground. please read this for more information. react-native-fcm is also updated to include channels too, refer this though the library should not be used anymore as the library is not maintained anymore, a good alternative is react-native-firebase.
Unable to get notification data,body when app is in background or closed in React-native-firebase android
Im using react-native-firebase in my app for cloud messanging + notification. it get all body and data when app is in use but it cant get anything when app is closed or in background .... I tried Headless JS but thats also not working when i click on notification and when it open's the app its shows this {"google.priority":"high"} thnaks in advance.... this is my android mainfest <application android:name=".MainApplication" android:label="#string/app_name" android:icon="#mipmap/ic_launcher" android:allowBackup="false" android:theme="#style/AppTheme" android:largeHeap="true"> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#drawable/ic_stat_ic_notification" /> <activity android:name=".MainActivity" android:label="#string/app_name" android:launchMode="singleTop" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!---firebase --> <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <!-- <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="#string/default_notification_channel_id"/> --> <service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" /> <!---firebase end--> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> </application> this is my componentdidmount() function async componentDidMount() { this.getValueLocally(); requestCameraLOCATION() const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification(); if (notificationOpen) { const action = notificationOpen.action; const notification: Notification = notificationOpen.notification; var seen = []; alert(JSON.stringify(notification.data, function(key, val) { if (val != null && typeof val == "object") { if (seen.indexOf(val) >= 0) { return; } seen.push(val); } return val; })); } const channel = new firebase.notifications.Android.Channel('test-channel', 'Test Channel', firebase.notifications.Android.Importance.Max) .setDescription('My apps test channel'); // Create the channel firebase.notifications().android.createChannel(channel); this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => { // Process your notification as required // ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification. }); this.notificationListener = firebase.notifications().onNotification((notification: Notification) => { // Process your notification as required notification .android.setChannelId('test-channel') .android.setSmallIcon('ic_launcher'); firebase.notifications() .displayNotification(notification); }); this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => { // Get the action triggered by the notification being opened const action = notificationOpen.action; // Get information about the notification that was opened const notification: Notification = notificationOpen.notification; var seen = []; alert(JSON.stringify(notification.data, function(key, val) { if (val != null && typeof val == "object") { if (seen.indexOf(val) >= 0) { return; } seen.push(val); } return val; })); firebase.notifications().removeDeliveredNotification(notification.notificationId); }); } async checkPermission() { firebase.messaging().hasPermission() .then(enabled => { if (enabled) { this.getToken(); } else { this.requestPermission(); } });} async getToken() { let fcmToken = await AsyncStorage.getItem('fcmToken'); if (!fcmToken) { fcmToken = await firebase.messaging().getToken(); if (fcmToken) { // user has a device token await AsyncStorage.setItem('fcmToken', fcmToken); } } } async requestPermission() { firebase.messaging().requestPermission() .then(() => { this.getToken(); }) .catch(error => { console.warn(error); }); } and this is my bgMessaging.js import firebase from 'react-native-firebase'; import type { RemoteMessage } from 'react-native-firebase'; import type { Notification,NotificationOpen} from 'react-native-firebase'; export default async (message: RemoteMessage) => { const newNotification = new firebase.notifications.Notification() .android.setChannelId(message.data.channelId) .setNotificationId(message.messageId) .setTitle(message.data.title) .setBody(message.data.body) .setSound("default") .setData(message.Data) .android.setAutoCancel(true) .android.setSmallIcon('ic_notification') .android.setCategory(firebase.notifications.Android.Category.Alarm) // Build a channel const channelId = new firebase.notifications.Android.Channel(message.data.channelId, channelName, firebase.notifications.Android.Importance.Max); // Create the channel firebase.notifications().android.createChannel(channelId); firebase.notifications().displayNotification(newNotification) return Promise.resolve(); }
there are two types of messages: notification + data messages that will be handled by the FCM while in the background (so your code will not have access to the notification), and will call onNotification while in the foreground, data-only messages will call headlessjs while in the background/closed and will call onMessage while in the foreground. note: if you remove the title and body, your message will be categorized as the second one. also, data is optional in the first category. to recap: for data-only messages: App in foreground : onMessage triggered App in background/App closed : Background Handler (HeadlessJS) for notification + data messages: App in foreground : onNotification triggered App in background/App closed : onNotificationOpened triggered if the notification is tapped for more information and for iOS read the official docs for data-only messages and notification+data messages
It seems that RN firebase did not support this functionality on Android. Please refer below: https://rnfirebase.io/docs/v5.x.x/notifications/receiving-notifications#4)-Listen-for-a-Notification-being-opened On Android, unfortunately there is no way to access the title and body of an opened remote notification. You can use the data part of the remote notification to supply this information if it's required.
react native firebase push notification when app is closed/swiped from list
I'm trying to show push notification when app is closed so I'm setting up the push notification with react-native-firebase with this docs I set AndroidManifest.xml as described in docs <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.moonsite.sqlivetrivia" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" /> <application android:name=".MainApplication" android:allowBackup="true" android:label="#string/app_name" android:icon="#mipmap/ic_launcher" android:theme="#style/AppTheme"> <receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/> <receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.QUICKBOOT_POWERON"/> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#drawable/ic_stat_ic_notification" /> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="#color/colorAccent" /> <!-- <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="#string/default_notification_channel_id"/> --> <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> <service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" /> <activity android:name=".MainActivity" android:label="#string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize" android:launchMode="singleTop" > <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> </application> </manifest> then I wrote the code in react native import React, { Component } from 'react' import { View } from 'react-native' import { Input, Text, Button } from '../Components' import type { RemoteMessage } from 'react-native-firebase' import firebase from 'react-native-firebase' import type { Notification, NotificationOpen } from 'react-native-firebase'; export default class TestComponent extends Component { async componentDidMount() { await this.SetUpAuth(); await this.SetUpMessaging(); this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => { // Get the action triggered by the notification being opened const action = notificationOpen.action; // Get information about the notification that was opened const notification: Notification = notificationOpen.notification; }); const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification(); if (notificationOpen) { console.log(notificationOpen) // App was opened by a notification // Get the action triggered by the notification being opened const action = notificationOpen.action; // Get information about the notification that was opened const notification: Notification = notificationOpen.notification; } } componentWillUnmount() { } async SetUpAuth() { const credential = await firebase.auth().signInAnonymouslyAndRetrieveData(); if (credential) { console.log('default app user ->', credential.user.toJSON()); } else { console.error('no credential'); } } async SetUpMessaging() { this.notification2 = new firebase.notifications.Notification() .setNotificationId('notificationId') .setTitle('My notification title') .setBody('My notification body') .android.setChannelId('test') .android.setClickAction('action') .setData({ key1: 'value1', key2: 'value2', }); this.notification2 .android.setChannelId('channelId') .android.setSmallIcon('ic_launcher'); console.log('assa') onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => { console.log('token generated ->', fcmToken); // store.dispatch(DeviceActions.SetFCMToken(fcmToken)); }); const fcmToken = await firebase.messaging().getToken(); if (fcmToken) { // user has a device token console.log('has token ->', fcmToken); console.log(firebase.auth().currentUser._user) firebase.database().ref(`/users/${firebase.auth().currentUser._user.uid}`).set({ pushToken: fcmToken }) // store.dispatch(DeviceActions.SetFCMToken(fcmToken)); } else { // user doesn't have a device token yet console.error('no messaging token'); } const messagingEnabled = await firebase.messaging().hasPermission(); if (messagingEnabled) { // user has permissions console.log('User has FCM permissions'); } else { // user doesn't have permission console.log('User does not have FCM permissions'); await this.RequestMessagePermissions(); } messageListener = firebase.messaging().onMessage((message: RemoteMessage) => { console.log(`Recieved message - ${JSON.stringify(message)}`); }); notificationDisplayedListener = firebase .notifications() .onNotificationDisplayed(notification => { // Process your notification as required // ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification. console.log(`Recieved notification 1`); }); notificationListener = firebase .notifications() .onNotification(notification => { console.log(notification) firebase.notifications().displayNotification(this.notification2) // Process your notification as required console.log(`Recieved notification 2`); }); } async RequestMessagePermissions() { console.log('request') console.log('Requesting FCM permission'); await firebase .messaging() .requestPermission() .catch(err => console.err(err)); } render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> </View> ) } } then I created firebase http function just for test export const sendNotification = functions.https .onRequest(async (req, res) => { try { const { token } = req.query; let tokens = 'fyTfgNZAUBA:APA91bGnx9Vp9MwRA4ohVKcNOM8d5s4a4TXdtI0KTSzcWEgZX1WoLGpofcVQFTCdSbnbqObkukzJEXF3cbmvENYD5pr2MrukjqUNy_bclDuM3rJsV5iSU1vWywL2ZVijJ3s0E9GNfRRe' var payload = { notification: { title: 'Urgent action needed!', body: 'Urgent action is needed to prevent your account from being disabled!', sound: 'default', color: '#84B2D9', icon: 'ic_notification', click_action: 'OPEN_MAIN_ACTIVITY' } }; // Set the message as high priority and have it expire after 24 hours. var options = { priority: 'high', timeToLive: 60 * 60 * 24 }; console.log('token',token) let d = await admin.messaging().sendToDevice(tokens, payload,options); return res.status(200).send({ success: d}) } catch (e) { console.info(e) return res.status(400).send({ error: 0 }) } }) in the response from http function I get success(as you can see here) { "success": { "results": [ { "messageId": "0:1525112032423298%a0cec506a0cec506" } ], "canonicalRegistrationTokenCount": 0, "failureCount": 0, "successCount": 1, "multicastId": 5934848553304349000 } } and in my debugger in console log I get the notification as I want but the issue I don't get push notification when app is closed. I want to get any notification when I'm not into the app. in addition when I use to display the notification when I get any notification notificationListener = firebase .notifications() .onNotification(notification => { console.log(notification) firebase.notifications().displayNotification(this.notification2) // Process your notification as required console.log(`Recieved notification 2`); }); } so it not display my details here this.notification2 = new firebase.notifications.Notification() .setNotificationId('notificationId') .setTitle('My notification title') .setBody('My notification body') .android.setChannelId('test') .android.setClickAction('action') .setData({ key1: 'value1', key2: 'value2', }); so do i need to save it on state and then in title to display the data?
Permissions to include in Android Manifest for GCM Push Notifications
Im trying to develop a cross platform application which will receive push notifications from Amazon SNS. The push notifications are working just fine for iOS, but for Android, im kind of at cross roads currently. The push notifications are viewable when the Android App is focussed. However, no matter what variables related to ti.cloudpush i set(listed below). The issue is - i am not able to get the push notifications to be shown in the notification tray. CloudPush.showAppOnTrayClick = true; CloudPush.showTrayNotification = true; CloudPush.showTrayNotificationsWhenFocused= false; CloudPush.singleCallback = true; I guess this is related to Permissions that i might have to set iin the tiapp.xml for the Android Manifest section. I have included the list of permissions currently used below - <android xmlns:android="http://schemas.android.com/apk/res/android"> <uses-sdk>14</uses-sdk>> <manifest> <uses-sdk android:minSdkVersion="14"/> <permission android:name="com.test.push.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="com.test.push.permission.C2D_MESSAGE"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.USE_CREDENTIALS"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application> <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> <!-- Start receiver on boot --> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.USER_PRESENT"/> <category android:name="android.intent.category.HOME"/> </intent-filter> <!-- Receive the actual message --> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <category android:name="com.test.push"/> </intent-filter> <!-- Receive the registration id --> <intent-filter> <action android:name="com.google.android.c2dm.intent.REGISTRATION"/> <category android:name="com.test.push.permission"/> </intent-filter> </receiver> </application> </manifest> </android> Could someone please let me know what i am doing wrong/ How to get this right ? Any information/permissions related link would be highly appreciated.
Try this code : app.js class : /* Push notifications through device token. Steps : 1) Retrieve device token 2) Subscribe for receiving notifications 3) Notify 4) Unsubscribe from receiving notifications */ Titanium.UI.setBackgroundColor('#000'); var GcmWin = Ti.UI.createWindow({ backgroundColor : '#ccc', title : 'Android Cloud Push Notification' }); var CloudPush = require('ti.cloudpush'); CloudPush.debug = true; CloudPush.enabled = true; CloudPush.showTrayNotificationsWhenFocused = true; CloudPush.focusAppOnPush = false; var deviceToken; var Cloud = require('ti.cloud'); Cloud.debug = true; var submit = Ti.UI.createButton({ title : 'Retrieve Device token', color : '#000', height : 80, width : 200, top : 50 }); var subscribe = Ti.UI.createButton({ title : 'Subscribe', color : '#000', height : 80, width : 200, top : 150 }); subscribe.addEventListener('click', subscribeToChannel); GcmWin.add(subscribe); var notify = Ti.UI.createButton({ title : 'Notify', color : '#000', height : 80, width : 200, top : 250 }); notify.addEventListener('click', sendTestNotification); GcmWin.add(notify); var unsubscribe = Ti.UI.createButton({ title : 'Unsubscribe', color : '#000', height : 80, width : 200, top : 350 }); unsubscribe.addEventListener('click', unsubscribeToChannel); GcmWin.add(unsubscribe); GcmWin.add(submit); submit.addEventListener('click', function(e) { CloudPush.retrieveDeviceToken({ success : function deviceTokenSuccess(e) { alert('Device Token: ' + e.deviceToken); deviceToken = e.deviceToken; }, error : function deviceTokenError(e) { alert('Failed to register for push! ' + e.error); } }); }); function subscribeToChannel() { // Subscribes the device to the 'test' channel // Specify the push type as either 'android' for Android or 'ios' for iOS Cloud.PushNotifications.subscribeToken({ device_token : deviceToken, channel : 'test', type : Ti.Platform.name == 'android' ? 'android' : 'ios' }, function(e) { if (e.success) { alert('Subscribed'); } else { alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e))); } }); } function sendTestNotification() { // Sends an 'This is a test.' alert to specified device if its subscribed to the 'test' channel. Cloud.PushNotifications.notifyTokens({ to_tokens : deviceToken, channel : 'test', payload : 'This is a test.' }, function(e) { if (e.success) { alert('Push notification sent'); } else { alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e))); } }); } function unsubscribeToChannel() { // Unsubscribes the device from the 'test' channel Cloud.PushNotifications.unsubscribeToken({ device_token : deviceToken, channel : 'test', }, function(e) { if (e.success) { alert('Unsubscribed'); } else { alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e))); } }); } CloudPush.addEventListener('callback', function(evt) { //alert(evt); alert(evt.payload); }); CloudPush.addEventListener('trayClickLaunchedApp', function(evt) { Ti.API.info('Tray Click Launched App (app was not running)'); //alert('Tray Click Launched App (app was not running'); }); CloudPush.addEventListener('trayClickFocusedApp', function(evt) { Ti.API.info('Tray Click Focused App (app was already running)'); //alert('Tray Click Focused App (app was already running)'); }); In tiapp.xml just check this below lines.Add it, if not there : <modules> <module platform="commonjs">ti.cloud</module> <module platform="android">ti.cloudpush</module> </modules> This works for me. Hope this helps.