I use Expo push Notifications to send Notifications to GSM using push token.
My code is :
registerForPush = async () => {
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS,
);
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(
Permissions.NOTIFICATIONS,
);
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
const gsm = await Notifications.getExpoPushTokenAsync();
this._storeData('TOKEN_GSM', gsm);
} else {
alert('Must use physical device for Push Notifications');
}
};
async componentDidMount() {
this.registerForPush();
}
When i use Expo to run the App i granted manually the permissions to get the token, but now i ejected to app to run IOS project with Xcode.
I got an error that i can't get push token :
Failed to get push token for push notification
Expo Ejected Apps need to use react-native libraries for notifications.
I recommend: https://github.com/zo0r/react-native-push-notification
There are currently, expo-kit solutions. But those will be depreciated soon in favor of the bare workflow. https://blog.expo.io/expo-sdk-34-is-now-available-4f7825239319
Deprecating ExpoKit in favor of the bare workflow.
We’re continuing to invest in building tooling and documentation around the bare workflow. We believe that this workflow is strictly better than ExpoKit and has lots of advantages for developers, such as full compatibility with libraries in the React Native ecosystem, easier upgrades, and more modular native code that doesn’t include all of the libraries in the Expo monolith. The bare workflow is the easiest and quickest way to achieve optional modules — that is, including native code for only the Expo modules you actually use.
The function getExpoPushTokenAsync() is for Expo app.
If you eject your app, she will no longer depends on Expo and will no longer have access to expo specific function.
you may read :
https://forums.expo.io/t/expokit-push-notifications-on-ejected-app-lots-of-misinformation-even-in-expo-docs-need-clarity/14670
an easy way to make push notification on react-native is to use firebase cloud messaging.
Related
Im implementing Firebase Cloud Messaging notification for my React Native app. For Android, the notification works great, however, for the ios, I faced an error of unable to get the token, too many server request. Here is my snippet of code for getting FCM token + request user's notification permission
const getFcmToken = async () => {
let fcmToken = await AsyncStorage.getItem("fcmToken");
console.log("fcmToken", fcmToken);
if (!fcmToken) {
try {
fcmToken = await messaging().getToken();
if (fcmToken) {
// user has a device token
await AsyncStorage.setItem("fcmToken", fcmToken);
}
} catch (err) {
console.log("Unable to get messaging token.", err);
}
}
};
export async function requestUserPermission() {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
getFcmToken();
} else {
console.log("not enabled");
}
}
When opening the app, the notification permission work fine, just the get FCM Token failed. Please help me with this issues.
I faced a similar issue where my app successfully retrieved FCM tokens for Android devices, whereas iOS responded with a Too many server requests error.
I solved it by re-downloading the GoogleService-Info.plist file from the Firebase Console for the iOS app.
I am not sure why, but it seemed my API key had been blocked or was invalid. After re-downloading the GoogleService-Info.plist file, the API key was updated and everything started working again.
The steps for adding the GoogleService-Info.plist to your React Native project can be found in the Getting Started part of the React Native Firebase Docs where you set up your iOS credentials.
Hope this helps.
I had this issue after I restricted the Firebase APIs to my iOS app.
To fix it I had to add the Firebase Installations API as this one uses the FID (Firebase installation ID) to target devices for message deliveries.
The Firebase installations service (FIS) provides a Firebase installation ID (FID) for each installed instance of a Firebase app.
And
Firebase Cloud Messaging uses Firebase installation IDs to target devices for message delivery.
All the APIs I had enabled were as follow:
FCM Registration API
Firebase App Distribution API
Firebase Cloud Messaging API
Firebase Installations API
Firebase Remote Config API
Mobile Crash Reporting API
Source:
https://firebase.google.com/docs/projects/manage-installations
I'm working with Ionic3 and using FirebaseX Cordova Plugin (because firebase plugin it's not working at all) and when the App is foreground (opened) the message get in the App (not as a notification) perfect, but when in background (using another app) the notification don't show... when I open back the App, the message get in the App (not as a notification)...
I'm using the Author example EXACTLY (only changed the bundle id so I could register as a Firebase Project)
I use a paid developer account, I have defined a APN, uploaded to firebase etc.
Activate the Remote Notification in Capabilities (both on Push and Background)
But still...
Something strange is that when the App opens, it says in the log:
2019-10-25 11:20:50.152424-0300 FirebaseX Ionic 3 Example[560:180512] FCM direct channel = true
and when the App goes background, the login says:
2019-10-25 11:20:50.152424-0300 FirebaseX Ionic 3 Example[560:180512] FCM direct channel = false
And when I open the App again it goes back to true again, and receive the notification!
I know that FCM is Firebase Cloud Messagin, so... but I don't know why it turns false
Please, help! Thanks!
I found the solution! Maybe it helps someone... Now with the FirebaseX Cordova Plugin You need to ask for permission explicitly (with the old firebase cordova plugin, was automaticly asked...)
insert this code:
this.firebasePlugin.grantPermission(function(hasPermission){
console.log("Permission was " + (hasPermission ? "granted" : "denied"));
});
and that's it (if the user say 'yes'!)
In firebasex cordova plugin you have to ask for permission like this.
You can only call grantPermission() if hasPermission() returns false:
window.FirebasePlugin.hasPermission(function(hasPermission){
if(!hasPermission){
window.FirebasePlugin.grantPermission(function(permissionGranted){
if(permissionGranted){
console.log("Permission granted");
}else{
console.warn("Permission denied");
}
});
}else{
console.log("Permission already granted");
}
});
I've just started testing Firebase for website push notifications. The basic code seems to work perfectly well on many Android-based browsers (Chrome, Firefox...) apps but not those installed on iOS such Chrome on my iPad or iPhone. I couldn't find any information related to this issue. Am I missing something?
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function () {
console.log('Notification permission granted.');
// TODO(developer): Retrieve an Instance ID token for use with FCM.
// ...
})
.catch(function (err) {
console.log('Unable to get permission to notify.', err);
});
Chrome on iOS is built on top of the same basic web view as Safari. Since that underlying component doesn't support Web Push, FCM push notifications cannot be delivered to Chrome on iOS.
For future reference, if you get a blank page on your website on iOS browsers.
just wrap your server worker in an if statement by checking if FCM is supported in that browser firebase.messaging.isSupported()
if (firebase.messaging.isSupported()) {
firebase.initializeApp({
'messagingSenderId': 'your code here'
});
...
}
I am really struggling to add push notification support to my Ionic application. My current issue is related to the documentation, which states that I need to add a cordova push plugin (which I have) and then to add the following event handler:
this.push.on('notification', function (data) {
// do something with the push data
// then call finish to let the OS know we are done
push.finish(function () {
console.log("processing of push data is finished");
}, function () {
console.log("something went wrong with push.finish for ID = " + data.additionalData.notId)
}, data.additionalData.notId);
});
However, I am getting an on property not found the error. How do I fix this issue?
That's correct. The browser outputs that this.push.on is not a function. Probably has to do with the browser not supporting Push and it's native capabilities.
However, using it in your mobile applicationw ill work just fine. If you want to make the error go away because it is confusing you could check on which OS the user currently is or check if he has cordova.
This can be done by wrapping your push.on in a if(this.platform.is('cordova')){} or if(platform.is('cordova')) (not sure about the this.) Source: How to detect if I am in browser (local development) in Ionic 2
I am currently working on a small app project to learn and try out react-native on iOS. I have some experience with parse (parse.com) and would love to integreate parse in the new app. Currently, I have no problems including parse js into react-native. I am able to log in with accounts etc. Now I need to send push notifications to a certain number of users (not all users).
What I don't understand is how push notifications should work with react-native and parse. Usually, I would connect a device installation with a user ID and then send a push to a certain number of users (which means to the devices with the corresponding installation). The react-native guide (https://facebook.github.io/react-native/docs/pushnotificationios.html#content) doesn't mention anything like that. And even though it gives the parse guide as a reference, I fail to see how I should be able to send pushes via parse. The guide leaves a lot of information to be desired too. To what source do these "Listeners" subscribe to? From which server am I going to send notifications etc?
As I understand, parse js is not able to read the current installation. I hesitate to add Parse iOS to the project too. This feels unnatural and shouldn't be a required thing to do although it would allow me to read the current installation. (but still parse js is not able to register that installation in order to subscribe to push notifications).
At this point, I feel a little bit lost. This piece of information (https://news.ycombinator.com/item?id=9271687) tells me that it should be possible somehow. I just can't figure out how :(
Hope someone can help me with that. Some advice would be truely appreciated.
EDIT: react-native implements this behavior by default now. The interesting part is the event listener for the register event which now returns the device token. Procedure is pretty straight forward now. Just have a look at the docs Also check out the answer by JWindey. Has some very important points in them that are needed to actually trigger the events.
After a while and a lot of trying things out, we came up with an answer today. This is our solution and it seems to be working pretty good.
We use the following resources:
react-native
parse-js
Parse Rest API
react-native-remote-push (https://github.com/darylrowland/react-native-remote-push)
Follow the parse guide for push notifications (https://parse.com/tutorials/ios-push-notifications) and get everything set up correctly (profiles, certificates etc.). Using the react-native-remote-push component later on, you don't have to follow the steps 5 and 6.
Now add react-native-remote-push to you project. We had to make some minor adjustments to the code (mainly dealing with legacy objC code), but that may depend on your own project.
Our project has some kind of "starting page" that is shown every time the app is opened. On this page, we deal with push notification permissions as well as with the registration of the device token and the listener for push notifications. Our goal is to mimic the same behavior that we would receive with the parse iOS SDK.
We need to register the device and subscribe to a push channel first. react-native-remote-push allows us to handle the permissions and receive a device token. We then proceed to use this device token to register this installation via the Rest API. This code is part of our componentDidMount() call.
var PushManager = require('./RemotePushIOS');
var registerInstallation = require('./Installation');
componentDidMount() {
PushManager.requestPermissions(function(err, data) {
if (err) {
console.log("Could not register for push");
} else {
registerInstallation({
"deviceType": "ios",
"deviceToken": data.token,
"channels": ["global"]
});
}
});
PushManager.setListenerForNotifications(this.receiveRemoteNotification);
}
PushManager is the required component from react-native-remote-push and registerInstallation is the function containing the Rest API call.
/**
* registers an installation
* data should look like the following:
* {
* "deviceType": "ios", // or "android"
* // if android is targeted set
* // "pushType": "gcm",
* // "GCMSenderId": "56712320625545", // whatever the later means
* "deviceToken": "29e32a686fd09d053e1616cb48",
* "channels": [
* ""
* ]
* };
* for more information visit:
* https://www.parse.com/docs/rest#installations-uploading
*/
var registerInstallation = function(data) {
var url = "https://api.parse.com";
url += "/1/installations";
fetch(url, {
method: 'post',
headers: {
'Accept': 'application/json',
'X-Parse-Application-Id': PARSE_APP_ID,
'X-Parse-REST-API-Key': PARSE_REST_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(processStatus)
.then(parseJson)
.catch(error);
};
module.exports = registerInstallation;
"processStatus", "parseJson" and "error" are just some small functions that handle the result of the API call. I can provide more details if necessary. This function allows us to add a lot of information via the "data" object, such as userid, app version, parse version etc., just as you're used to from the iOS SDK. We only have a basic example working right now, but it should be easy to extend on this basis. This step was very important for us, because we need to associate every installation with a certain user.
You should be able to receive push notifications by now. You can handle them in a "receiveRemoteNotification" function that acts as a listener. A basic function is provided on the website of the react-native-remote-push component.
I hope I could share some insight about this topic. If I should go into more detail on certain parts, I'll gladly add some more information.
I did some investigation with the Parse + react-native combination and have it working.
You have to add the Parse SDK (follow the guide) to your project, and link all the necessary libraries.
Don't forget to add the steps on point 5: https://parse.com/tutorials/ios-push-notifications.
Then add RCTPushNotificationManager.h + m (from react-native/Libraries) to your project. After that, add the following in AppDelegate.m:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[NSNotificationCenter defaultCenter] postNotificationName:#"RemoteNotificationReceived"
object:self
userInfo:userInfo];
}
That should do it.
The official PushNotificationIOS has register event, which we can obtain token from. So, with having #MrMuetze's REST API, I could install the device to Parse.
PushNotificationIOS.addEventListener('register', function(token){
registerInstallation({
"deviceType": "ios",
"deviceToken": token,
"channels": ["global"]
})
});