How to get React Native Push Notifications using FCM? - firebase

I'm using React Native Push notifications for my iOS version of my React Native app and I'm trying to send a test notification using Firebase Cloud Messaging.
Here's my code that I have in a PushController.js file that I import into my app.
import React, { Component } from "react";
import PushNotificationIOS from "#react-native-community/push-notification-ios";
import PushNotification from "react-native-push-notification";
// var PushNotification = require("react-native-push-notification");
export default class PushController extends Component {
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,
});
}
render() {
return null;
}
}
It properly initializes and I get the token from onRegister().
But, I can't get the FCM to output a notification to my app; I've added the token to my test but I don't believe it works because it is an FCM token. So my question is how do I send a message using FCM and connect it to the React Native Push Notifications?

Related

Getstream firebase auth react native documentation?

Not sure if anyone has any experience with getstream and react native.
I followed there tutorial to implement getstreams SDK into my existing app and its working great but I'm stuck on tokens. I've successfully set up firebase so when a new user signs up I can see there UID and information over on both firebase auth and getstream but I'm hung up on my frontend getting the user to sign in on the chat with there token. I set up firebase with there extension but still having issues. Works great with dev.tokens but just can't get past this part. Is there any examples out there or better documentation for this? Thank you!
Only documentation I can find.. not specific to react native
https://getstream.io/chat/docs/react/tokens_and_authentication/
This is currently how I initialize my user.. the user token is hard coded in my chat config file.
// useChatClient.js
import { useEffect, useState } from 'react';
import { StreamChat } from 'stream-chat';
import { chatApiKey, chatUserId, chatUserName, chatUserToken } from './chatConfig';
const user = {
id: chatUserId,
name: chatUserName,
};
const chatClient = StreamChat.getInstance(chatApiKey);
export const useChatClient = () => {
const [clientIsReady, setClientIsReady] = useState(false);
useEffect(() => {
const setupClient = async () => {
try {
chatClient.connectUser(user, chatUserToken);
setClientIsReady(true);
// connectUser is an async function. So you can choose to await for it or not depending on your use case (e.g. to show custom loading indicator)
// But in case you need the chat to load from offline storage first then you should render chat components
// immediately after calling `connectUser()`.
// BUT ITS NECESSARY TO CALL connectUser FIRST IN ANY CASE.
} catch (error) {
if (error instanceof Error) {
console.error(`An error occurred while connecting the user: ${error.message}`);
}
}
};
// If the chat client has a value in the field `userID`, a user is already connected
// and we can skip trying to connect the user again.
if (!chatClient.userID) {
setupClient();
}
}, []);
return {
clientIsReady,
};
};
The next step is to request the token from the Firebase cloud function (ext-auth-chat-getStreamUserToken), and then initialise the current user with that token.
There is a guide and video showing how to do this using the Stream Chat Flutter SDK:
https://getstream.io/chat/docs/sdk/flutter/guides/token_generation_with_firebase/
https://youtu.be/Dt_taxX98sg

This operation is not supported in the environment this application is runnung on [duplicate]

I develop a react-native (expo) mobile app and try to sign in with a google account to firebase, but I get an error:
"auth/operation-not-supported-in-this-enviroment. This operation is not supported in the enviroment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled"
Code:
loginGoogle() {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
return true;
}).catch(function(error) {
alert(error.code + '\n' +
error.message + '\n' +
error.email + '\n' +
error.credential);
return false;
});
}
signInWithPopup is not supported in react-native. You will need to use a third party OAuth library to get the OAuth ID token or access token and then sign in with Firebase:
const cred = firebase.auth.GoogleAuthProvider.credential(googleIdToken, googleAccessToken);
firebase.auth().signInWithCredential(cred)
.then((result) => {
// User signed in.
})
.catch((error) => {
// Error occurred.
});
Firebase does not support signInWithPopup in a React Native environment.
You can view a full list of supported environments on this page.
You can also submit a feature request for extended Firebase support for React Native here.
If you are using expo bare workflow or simple React native cli (or in simple words which contain android and ios folder) then simply use "React Native Firebase" library.
Here is the link https://rnfirebase.io/
But if you are using expo managed workflow(which donot contain android and ios folder ) then you have to follow below steps .
1.setup google developer account
use this guide to setup : https://docs.expo.dev/versions/latest/sdk/google/
Note that: use host.exp.exponent as the package name.
Another problem you may face in this step is generation of hash,which I also faced,the reason for that error is java dev kit(JDK) is not install ,so do install it before proceeding to this step.
2.Setup Firebase account
Simply setup firebase project as you set before, enable google sign in service
but this time the only change is you have to add client ID of your google developer account in (safest client id field) which will popup once you click on edit Google signin in firebase
look like this
3.Coding Part
import * as Google from 'expo-google-app-auth'; //imported from expo package
import {
GoogleAuthProvider,getAuth
} from 'firebase/auth';
import { initializeApp } from "firebase/app";
import { firebaseconfig } from '[your firebase credentials]';
const app=intitializeApp(firebaseconfig)
const auth=getAuth(app);
async function signInWithGoogleAsync() {
try {
const result = await Google.logInAsync({
androidClientId: 'cliend id from google dev console',
iosClientId: 'client id from google dev console for ios app(if you setup)',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
console.log(result)
const credential = GoogleAuthProvider.credential(result.idToken, result.accessToken);
// Sign in with credential from the Facebook user.
signInWithCredential(auth, credential)
.then(async result => {
console.log(result)
})
.catch(error => { console.log(error) });
return result.accessToken;
} else {
console.log("cancelled by user")
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}//
}

Remove users who uninstalled app from database [duplicate]

We have developed an app in iOS and Android which stores the FCM tokens in a database in order to send PUSH notifications depending on the user configuration.
Users install the app and the token of every device is stored in the database, so we would like to know what of those tokens are invalid because the app has been uninstalled.
On the other hand, we send the notifications through the website using JSON. Is there any limitation (I mean, is there any limit of elements in a JSON request)?
Thank you very much!
I recently noticed that step 9 in the Cloud Functions codelab uses the response it gets from the FCM API to remove invalid registration tokens from its database.
The relevant code from there:
// Get the list of device tokens.
return admin.database().ref('fcmTokens').once('value').then(allTokens => {
if (allTokens.val()) {
// Listing all tokens.
const tokens = Object.keys(allTokens.val());
// Send notifications to all tokens.
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(allTokens.ref.child(tokens[index]).remove());
}
}
});
return Promise.all(tokensToRemove);
});
}
});
I quickly checked and this same approach is also used in the Cloud Functions sample for sending notifications.

Ionic3 Firebase notification not received on device

In brief: Firebase Notifications sent via Firebase Cloud Functions shows that message is sent. However, message is not received in the device. (Only tested in Android. Don't know about iOS)
Hello, I'm on a Ionic 3 project which uses Firebase Cloud Firestore, Cloud Functions and other Firebase services.
App workflow:
Upon new document creation (as in new reservation), the admin SDK should send push notification to the particular device which should arrive in the device.
Problem:
When checking in the Cloud Functions log, it shows message is successfully sent and the Triggering functions finished without any error. But no message has been received yet. However, when sending message from Firebase Notification Console, each message arrives perfectly.
Code:
index.ts (Cloud Functions)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
exports.notifyOnNewBooking = functions.firestore
.document('users/{userId}/bookings/{bookingId}')
.onCreate( event => {
const bookingData = event.data.data();
// construct notification message here
const message = {
notification: {
title: 'Reservation confirmed!',
body: 'Your reservation at someplace at sometime is confirmed',
icon: 'https://image.ibb.co/iBwekx/icon.png'
}
};
// send notification with message right away
return admin.messaging().sendToDevice(bookingData.deviceFCMToken, message, {priority: 'high'})
.then(resp => {
console.log("sent successfully", resp);
})
.catch(err => {
console.error("could not send notification", err);
});
});
app.component.ts (Ionic)
...
// Ionic Native wrapper
import { FCM } from '#ionic-native/fcm';
....
#Component({
template: `
....
....
`
})
export class MyApp {
...
constructor(..., private fcm: FCM) {}
ngOnInit() {
this.fcm.onNotification()
.subscribe(resp => {});
}
}
Firebase Cloud Functions log shows this:
Ionic CLI info
cli packages: (/usr/local/lib/node_modules)
#ionic/cli-utils : 1.19.1
ionic (Ionic CLI) : 3.19.1
System:
Node : v9.3.0
npm : 5.5.1
OS : macOS High Sierra
Misc:
backend : pro
Cloud Functions package.json dependencies
"dependencies": {
"#google-cloud/functions-emulator": "^1.0.0-beta.3",
"firebase-admin": "~5.8.1",
"firebase-functions": "^0.8.1",
"firebase-tools": "^3.17.4",
"global": "^4.3.2"
},
config.xml
<plugin name="cordova-plugin-fcm" spec="^2.1.2">
<variable name="SENDER_ID" value="845539284400" />
</plugin>
Note: There is only one subscription which is at the root component in the app. And I'm on Firebase Spark plan which is free but often notifies in the log that - Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.
Modified the function in Cloud Functions to this below and now notifications is being received in the Notification tray when the app is in Background and in the subscription response when the app is in Foreground.
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
exports.notifyOnNewBooking = functions.firestore
.document('users/{userId}/bookings/{bookingId}')
.onCreate(event => {
const bookingData = event.data.data();
// construct notification message here
const message: admin.messaging.Message = {
token: bookingData.deviceFCMToken,
android: {
notification: {
title: 'Reservation successful',
body: `Your reservation at ${bookingData.restaurant_name} is confirmed.`,
icon: 'https://image.ibb.co/iBwekx/icon.png'
}
},
apns: {
headers: {
'apns-priority': '10'
},
payload: {
aps: {
alert: {
title: 'Reservation successful',
body: `Your reservation at ${bookingData.restaurant_name} is confirmed.`,
},
badge: 1
}
}
}
};
// send notification with message right away
return admin.messaging().send(message)
.then(resp => {
console.log("sent successfully", resp);
})
.catch(err => {
console.error("could not send notification", err);
});
});

React Native firebase.auth.RecaptchaVerifier

How to set the firebase.auth.RecaptchaVerifier in react native using firebase web method to verify phone number and authenticate by receiving OTP on device.Tried with some Methods but not working on mobile.
Code for react native using Web Method:
var appVerifier = firebase.auth.RecaptchaVerifier;
// window.recaptchaVerifier =
// new firebase.auth.RecaptchaVerifier('recaptcha-container');
firebase.auth().signInWithPhoneNumber('+919843191338', appVerifier)
.then(function (confirmationResult) {
Alert.alert(confirmationResult);
window.confirmationResult = confirmationResult;
}).catch(function (error) {
// Error; SMS not sent
// ...
});
You can enable auto verification by enabling SafetyNet API
Check this for detailed information:
https://firebase.google.com/docs/auth/android/phone-auth

Resources