React native firebase push notification not working for iOS - react-native

I have recently upgraded my RN 0.57.1 to RN 0.59.1, Push notification is working properly earlier but now push notification only working when the app installed first time.
package.json:
"react": "16.8.3",
"react-native": "^0.59.1",
"react-native-firebase": "^5.2.0"
I have tried with https://pushtry.com to test the actual issue and it's showing me "NotRegistered". It was working perfect in my old builds but I don't know why it's creating issues.
Here is my code:
info.plist:
<key>FirebaseAppDelegateProxyEnabled</key>
<string>no</string>
<key>FirebaseDataCollectionDefaultEnabled</key>
<string>Yes</string>
<key>LSApplicationQueriesSchemes</key>
app.js:
async componentDidMount() {
this.checkPermission();
this.createNotificationListeners();
}
componentWillUnmount() {
this.notificationListener();
this.notificationOpenedListener();
}
async createNotificationListeners() {
this.notificationListener = firebase.notifications().onNotification((notification) => {
const { title, body} = notification.data;
this.title = title;
this.body = body;
const localNotification = new firebase.notifications.Notification({
sound: 'default',
show_in_foreground: true,
})
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setBody(notification.body)
.setData(notification.data)
.android.setAutoCancel(true)
.android.setChannelId('mybeautysquad') // e.g. the id you chose above
.android.setSmallIcon('ic_launcher') // create this icon in Android Studio
.android.setColor('#000000') // you can set a color here
.android.setPriority(firebase.notifications.Android.Priority.High);
firebase.notifications()
.displayNotification(localNotification)
.catch(err => console.error(err));
});
/*
* If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
* */
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
const { title, body } = notificationOpen.notification.data;
this.title = title;
this.body = body;
});
/*
* If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:
* */
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification.data;
this.title = title;
this.body = body;
}
/*
* Triggered for data only payload in foreground
* */
this.messageListener = firebase.messaging().onMessage((message) => {
//process data message
console.log(JSON.stringify(message));
});
}
async checkPermission() {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
}
async getToken() {
let fcmToken = await AsyncStorage.getItem('fcmToken');
console.log(fcmToken);
if (!fcmToken) {
fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
// user has a device token
await AsyncStorage.setItem('fcmToken', fcmToken);
}
}
}
async requestPermission() {
try {
await firebase.messaging().requestPermission();
// User has authorised
this.getToken();
} catch (error) {
// User has rejected permissions
console.log('permission rejected');
}
}
Also, I am saving sane FCM token on the server when login and check if user FCM token not updated in login then I am also updating their FCM device token when they update their profile.
Please let me know if anyone can help me into this...Thanks!

Related

DeviceNotRegistered: "ExponentPushToken[***]" is not a registered push notification recipient

I'm trying to implement expo push notifications on react native app built with expo !
I did everything mentioned on their docs ! i'm getting the token successfully but when i try sending a push notification to that token using their api or the tool they provide i get this error
DeviceNotRegistered: "ExponentPushToken[***]" is not a registered push notification recipient
This is how i'm getting the token !
export const useNotifications = () => {
const registerForPushNotificationsAsync = async () => {
if (Device.isDevice) {
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
const token = (await Notifications.getExpoPushTokenAsync()).data;
console.log("TOKEN------------", token);
alert(token);
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
};
const handleNotification = (notification = Notifications.Notification) => {
// could be useful if you want to display your own toast message
// could also make a server call to refresh data in other part of the app
};
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
const handleNotificationResponse = (
response = Notifications.NotificationResponse
) => {
const data = ({ url } = response.notification.request.content.data);
if (data?.url) Linking.openURL(data.url);
};
return {
registerForPushNotificationsAsync,
handleNotification,
handleNotificationResponse,
};
};
useEffect(() => {
registerForPushNotificationsAsync();
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
const responseListener =
Notifications.addNotificationResponseReceivedListener(
handleNotificationResponse
);
return () => {
if (responseListener) {
Notifications.removeNotificationSubscription(responseListener);
}
};
}, []);
i run the eas build eas build -p android --profile preview so i can test it on a real device since push notifications works only on real devices and after that i pushed the cloud messaging server key that i got from my firebase project with this command expo push:android:upload --api-key <your-token-here>
As i said i successfully get the token but the i get the error when trying to send the notification!
am i missing a step or something ?
I tried run the build on two devices and both not working !

Expo React native asks for location permissions in simulator but not in built app

App has been working fine for a while but now it's not prompting users for location permission which results in the features using location failing. On both simulator and physical device running expo go, the user is prompted to give permission to location data. (both iOS and Android) All other permissions it needs it asks for (push, camera and calendar)
export default function CheckIn(props) {
const { todayEvents } = useSelector(({ checkin }) => checkin);
const [venueIdd, setVenueId] = useState(0);
const [modalVisible, setModalVisible] = useState(false);
const [status, setStatus] = useState(null);
const [backgroundLocationPermission, setBackgroundLocationPermission] =
useState(null);
const dispatch = useDispatch();
TaskManager.defineTask("updateLocation", ({ data: { locations }, error }) => {
if (error) {
return;
}
dispatch(sendBackgroundLocation(locations[0].coords, venueIdd));
});
async function registerBackgroundFetchAsync() {
return BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
minimumInterval: 60 * 15, // 15 minutes
stopOnTerminate: false, // android only,
startOnBoot: true, // android only
});
}
async function unregisterBackgroundFetchAsync() {
return BackgroundFetch.unregisterTaskAsync(BACKGROUND_FETCH_TASK);
}
React.useEffect(() => {
dispatch(getTodaysEvents());
const askPermission = async () => {
let getForeground = await Location.getForegroundPermissionsAsync();
if (getForeground.status !== "granted") {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
Alert.alert("Permission to access location was denied");
return;
} else {
let backgroundPermissions =
await Location.requestBackgroundPermissionsAsync();
if (backgroundPermissions.status == "granted") {
await AsyncStorage.setItem("background_permission", "true");
}
}
}
};
askPermission();
}, []);
const checkIn = async (index) => {
let temp = [...todayEvents];
temp[index].isCheckedIn = true;
setVenueId(temp[index].venueId);
const backgroundStatus = await AsyncStorage.getItem(
"background_permission"
);
// if (backgroundStatus !== null) {
Location.startLocationUpdatesAsync("updateLocation", {
timeInterval: 120,
distanceInterval: 0.01,
foregroundService: {
notificationTitle: "Company title",
notificationBody:
"Information in body",
},
accuracy: Location.Accuracy.Highest,
}).then((response) => {
// console.log("RESPONSE LOCATION", response);
});
// }
setTimeout(() => {
const stopped = Location.stopLocationUpdatesAsync("updateLocation");
}, 43200000);
let { coords } = await Location.getCurrentPositionAsync();
dispatch(userCheckIn({ lat: coords.latitude, long: coords.longitude }));
};
const checkOut = async (index) => {
const stopped = Location.stopLocationUpdatesAsync("updateLocation");
let temp = todayEvents;
temp[index].isCheckedIn = false;
//dispatch(userCheckOut()); // This is what I commented out
// And the two rows below is added
let { coords } = await Location.getCurrentPositionAsync();
dispatch(userCheckOut({ lat: coords.latitude, long: coords.longitude }));
};
const review = (index, value) => {
setModalVisible(true);
setTimeout(() => {
setModalVisible(false);
setTimeout(() => {
props.navigation.goBack();
}, 300);
}, 1500);
let temp = todayEvents;
temp[index].review = value;
dispatch(giveEventFeedBack(temp[index]));
};
From the app.json following iOS Location permissions are defined:
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
And for Android:
ACCESS_BACKGROUND_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
There's a scenario when the user recently choose the NEVER ASK AGAIN option for that permission. The next time the app attempt to ask it, the request resolves in denied status silently without launching the request permission popup modal.
If this is the case, the app can force the user to grant permission manually in app settings
You can handle this situation like this
const permission = await Location.getForegroundPermissionsAsync();
// Detect if you can request this permission again
if (!permission.canAskAgain || permission.status === "denied") {
/**
* Code to open device setting then the user can manually grant the app
* that permission
*/
Linking.openSettings();
} else {
if (permission.status === "granted") {
// Your actually code require this permission
}
}
While the solution above doesn't work, Review this ongoing issue in Expo SDK 44 - https://github.com/expo/expo/issues/15273

Notifications are not showing while the app is in foreground

I am trying to send push notifications using react-native-firebase through firebase console when my app is closed or in the background, the notifications are received and shown as a pop-up but if my app is in the foreground the notifications are not appearing
I have been trying to do some code in on notification method as suggested in the docs but it's not working
please suggest something that my app can show notifications in foreground
Please refer following link.
https://rnfirebase.io/docs/v5.x.x/messaging/android#(Optional)-Background-Messages
If you added, remove following line from your AndroidManifest.xml.
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
create a new notifactionHandler.js and import the code below.
import firebase from 'react-native-firebase';
exports.setNotificationListener = () => {
return new Promise((resolve, reject) => {
// triggers when notifiaction received while app on foreground
this.notificationListener = firebase.notifications().onNotification((notification) => {
console.log(notification.data);
setNotification({notification})
});
resolve(true);
})
};
const setNotification = ({notification}) => {
firebase.notifications().displayNotification(notification);
}
then import it on your splash or main page.
then call setNotificationListener function. basicly firebase.notifications().onNotification catches notifications while app on foreground, and displays it with firebase.notifications().displayNotification
in my case:
import firebase from 'firebase';
import * as Notice from "react-native-firebase";
componentDidMount() {
const firebaseConfig = {
apiKey: "**********",
authDomain: "**********",
databaseURL: "**********",
projectId: "**********",
storageBucket: "**********",
messagingSenderId: "**********",
appId: "**********"
};
this.mNotifiConfig()
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
}
mNotifiConfig = async() => {
Notice.messaging().hasPermission()
.then(enabled => {
console.log('HAS PERMISS: ', enabled)
if (enabled) {
Notice.messaging().getToken().then(token => {
console.log("LOG: ", token);
}).catch(err=> console.log(err))
} else {
Notice.messaging().requestPermission()
}
});
const notificationOpen = await Notice
.notifications()
.getInitialNotification();
if (notificationOpen) {
const action = notificationOpen.action;
const notification = notificationOpen.notification;
var seen = [];
// this.onActionWithNotification(notification)
console.log('NOTIFICATION IS OPNE')
}
// config android
const channel = new Notice.notifications.Android.Channel(
"test-channel",
"Test Channel",
Notice.notifications.Android.Importance.Max
).setDescription("My apps test channel");
// Create the channel
Notice.notifications().android.createChannel(channel);
this.notificationDisplayedListener = Notice
.notifications()
.onNotificationDisplayed((notification: Notification) => {
console.log('CREATED CHANNEL')
// 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 = Notice
.notifications()
.onNotification((notification: Notification) => {
console.log('HAS Notification: ', notification)
// Process your notification as required
// notification.android
// .setChannelId("test-channel")
// .android.setSmallIcon("ic_launcher");
// firebase.notifications().displayNotification(notification).catch(err => console.error(err));
let notification_to_be_displayed = new Notice.notifications.Notification({
data: notification.data,
sound: 'default',
show_in_foreground: true,
title: notification.title,
body: notification.body,
});
if(Platform.OS == "android") {
notification_to_be_displayed
.android.setPriority(Notice.notifications.Android.Priority.High)
.android.setChannelId("test-channel")
.android.setSmallIcon("ic_launcher")
.android.setVibrate(1000);
}
Notice.notifications().displayNotification(notification_to_be_displayed);
});
this.notificationOpenedListener = Notice
.notifications()
.onNotificationOpened((notificationOpen) => {
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification = notificationOpen.notification;
var seen = [];
console.log('notification Day nay', notification)
Notice
.notifications()
.removeDeliveredNotification(notification.notificationId);
// this.onLinkingtoApp()
});
this.onMessageListener = Notice.messaging().onMessage((message: RemoteMessage) => {
const {data} = message
const showNotif = new Notice.notifications.Notification()
.setNotificationId('notificationId')
.setTitle(data.title || 'Thông báo')
.setBody(data.content || 'Bạn có một thông báo mới')
.setData(data)
.android.setChannelId('test-channel')
.android.setSmallIcon('ic_launcher')
Notice.notifications().displayNotification(showNotif)
})
}

When receiving messages from firebase console, app crashes(<appName> has stopped)

When I send test message from firebase console to my device, the app crashes without any console log.
Installed packages:
"react": "16.6.3"
"react-native": "^0.59.8"
"react-native-device-info": "^1.4.3"
"react-native-firebase": "^5.3.1"
"react-native-paper": "^2.12.0"
"react-native-vector-icons": "^6.3.0"
build.gradle
// Firebase dependencies
implementation "com.google.android.gms:play-services-base:16.1.0"
implementation "com.google.android.gms:play-services-auth:16.0.1"
implementation "com.google.firebase:firebase-core:16.0.9"
implementation "com.google.firebase:firebase-messaging:18.0.0"
Things already tried:
adb logcat - no use
adb logcat *:S ReactNative:V ReactNativeJS:V - no use
//App.js code for receiving remote notification
async componentDidMount() {
this.checkPermission();
this.onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => {
// Process your token as required
Alert.alert(fcmToken);
});
this.messageListener = firebase.messaging().onMessage((message) => {
console.log("JSON.stringify:", JSON.stringify(message));
Alert.alert(message);
});
this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
const { title, body } = notification;
console.log('onNotification:');
const localNotification = new firebase.notifications.Notification({
show_in_foreground: true,
})
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setBody(notification.body)
.android.setChannelId('fcm_FirebaseNotifiction_default_channel') // e.g. the id you chose above
.android.setSmallIcon('#drawable/ic_launcher') // create this icon in Android Studio
.android.setColor('#000000') // you can set a color here
.android.setPriority(firebase.notifications.Android.Priority.High);
firebase.notifications()
.displayNotification(localNotification)
});
this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
console.log("test");
});
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 = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
console.log('getInitialNotification:');
Alert.alert(title, body)
}
}
componentWillUnmount() {
try {
this.onTokenRefreshListener();
this.messageListener();
this.notificationListener();
this.notificationOpenedListener();
} catch (error) {
console.error(error)
}
}
async checkPermission(){
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
}
async getToken(){
const fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log("FCMToken:"+fcmToken);
this.setState({test:fcmToken})
} else {
// user doesn't have a device token yet
}
}
async requestPermission(){
try {
await firebase.messaging().requestPermission();
// User has authorised
} catch (error) {
// User has rejected permissions
}
}
I missed out the code in AndroidManifest.xml file. If any one facing same issue do check this file.

react-native-linkdin-login is not working in ios?

I am using react-native-linkdin-login library to support linkding sigin in my application.It is working properly in android but in iOS it always ask to download an application rather than application already exist in device and redirect to the APP store. When I open and login to linkdin account, I can't come back to my react-native application, with user profile details.
Give me any suggestion as soon as possible.
async componentWillMount() {
LinkedinLogin.init(
[
'r_emailaddress',
'r_basicprofile'
]
);
}
async handleLinkedinLogin(){
LinkedinLogin.login().then((user) => {
alert("linkdin");
this.setState({ user : user });
this.getUserProfile();
}).catch((e) => {
var err = JSON.parse(e.description);
alert("ERROR: " + err.errorMessage);
alert('Error', e);
});
return true;
}
getUserProfile(user) {
LinkedinLogin.getProfile().then((data) => {
const userdata = Object.assign({}, this.state.user, data);
this.setState({ user: userdata });
const Email = userdata.emailAddress;
const Fullname = userdata.firstName+' '+userdata.lastName;
const SocialAppId = userdata.id;
const SignupType = 'Linkedin';
alert("Please wait....")
this.socialLogin(Fullname,Email,'null',SignupType);
}).catch((e) => {
alert(e);
});
}