Cannot retrieve ExpoPushToken on IOS - react-native

ExpoSDK Version - 42
Bare workflow
EAS version - 0.39.0
I have an react-native expo app build with eas build --profile preview --platform all, and on IOS i cannot seem to retrieve the ExpoPushToken. On Android it works just fine. I tried to fix the issue by removing the APN push key, the Provisioning Profile and the Distribution Certificate, and creating them again from the EAS prompts, but the problem persists.
The code I’m using for retrieving the Push token is the one from the Expo Documentation.
async function registerForPushNotificationsAsync() {
let token;
if (Constants.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;
}
token = await Notifications.getExpoPushTokenAsync();
} else {
alert("Must use physical device for Push Notifications");
return;
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
return token;
}
I’m calling this function inside a useEffect, and sending the token to the server, to store it in the users data, but on IOS the token returned is undefined.

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 !

React Native Facebook User Photos is Denied

I have a react native app and i can login with facebook. However I can't get the users photo. First of all FB hash key is correct and my app is in live mode. I sent the app to APP REVIEW and the photos are always denied by team and they are telling me they can't get the photos of the users. I use "react-native-fbsdk-next": "^4.3.0" and we use our own api url for photos, not using Graph Api of FB. There is [user_photos] as well beside public_profile. Does anyone know the reason for this ? After I login to Facebook, i try to upload photo via FB and it displays a pop up saying " facebook photos permission is denied. This permission allows your app to read photos of Facebook". Why facebook team denies user photo access ? what else should do to make it work ? My login code implementation is below. I could not find anything on Google regarding this kind of issue. Please help
export const facebookLogin = snackBarBottomMargin => {
return async dispatch => {
try {
const result = await LoginManager.logInWithPermissions([
'public_profile',
'user_photos',
]);
if (!result.isCancelled) {
const data = await AccessToken.getCurrentAccessToken();
if (data && data.accessToken) {
await storage.storeData(
PREFERENCES.FB_ACCESS_TOKEN,
JSON.stringify(data),
);
return data;
} else {
console.log('Facebook result fetch token error cancelled');
return false;
}
} else {
console.log('Login cancelled');
return false;
}
} catch (error) {
dispatch(
showSnackbar(strings.login.facebookLoginError, snackBarBottomMargin),
);
return false;
}
};
};
export function handleFetchFBPhotos(accessToken, after) {
return async dispatch => {
function onSuccess(success) {
dispatch(fetchMediaSuccess(success));
console.log('success', success);
return success;
}
function onError(error) {
dispatch(fetchMediaFailed(error));
console.log('error', error);
return error;
}
try {
dispatch(fetchMediaRequest(true));
const config = {
baseURL: Config.FACEBOOK_BASE_URL,
params: {
type: 'uploaded',
fields: 'images',
after,
},
headers: {Authorization: `Bearer ${accessToken}`},
};
const response = await axios.get(FACEBOOK_PHOTOS, config);
if (response.data && response.data.data) {
console.log('response.data', response.data);
console.log('response.data.data', response.data.data);
console.log('onSuccess(response.data)', onSuccess(response.data));
return onSuccess(response.data);
}
} catch (error) {
const errorObj = getErrorResponse(
error,
Config.FACEBOOK_BASE_URL + FACEBOOK_PHOTOS,
);
console.log('onError(errorObj.message)', onError(errorObj.message));
return onError(errorObj.message);
}
};
}

Google login in Reactnative App with Strapi

I want to implement google login in react native app using strapi. Is there any proper documentation or steps to follow? I didn't understand how to do with strapi. I have found an example with react js.
Here is how to do it:
First of all, install google-signin package and do the necessary setup changes:
#react-native-google-signin/google-signin
Once you are sure that you have finished the configuration, you can perform login like below:
try {
await GoogleSignin.hasPlayServices();
await GoogleSignin.signIn();
const { accessToken } = await GoogleSignin.getTokens();
const resp = await axios.get(`/auth/google/callback?access_token=${accessToken}`);
if (resp.status !== 200) {
//Handle fail case
return;
}
const data = resp.data
// Handle the data and do your stuff like navigate to the home screen.
} catch (error: any) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
// user cancelled the login flow
} else if (error.code === statusCodes.IN_PROGRESS) {
// operation (e.g. sign in) is in progress already
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
// play services not available or outdated
} else {
// some other error happened
}
}

Error: An error occurred while trying to log in to Facebook expo-facebook android issue

I am trying to implement Facebook login in a simple expo app but on the android expo client, it is not working. Following version, I am using.
"expo-facebook": "~12.0.3",
Method code
const handleAuth = async () => {
try {
let options = null;
if (Platform.OS === "android") {
options = {appId: "xxxxxxxxxxxxxx"};
} else {
options = {
appId: "xxxxxxxxxxxxxx",
version: "v9.0",
appName: "xxxxxxxx",
};
}
let res = await Facebook.initializeAsync(options);
console.log("[init res]", res);
const {type, token, expirationDate, permissions, declinedPermissions} =
await Facebook.logInWithReadPermissionsAsync({
permissions: ["public_profile"],
});
console.log("[type]", type);
console.log("[token]", token);
if (type === "success") {
// SENDING THE TOKEN TO FIREBASE TO HANDLE AUTH
const credential = app.auth.FacebookAuthProvider.credential(token);
app
.auth()
.signInWithCredential(credential)
.then((user) => {
// All the details about user are in here returned from firebase
console.log("Logged in successfully", user);
dispatch(saveUser(user));
navigation.replace("App");
})
.catch((error) => {
console.log("Error occurred ", error);
});
} else {
// type === 'cancel'
}
} catch (res) {
console.log("[res]", res);
// alert(`Facebook Login Error: ${res}`);
}
};
Another error i am facing is FacebookAuthProvider is not available in firebase
firebase": "8.10.0"
I have tried the following ways.
app.auth.FacebookAuthProvider
Or
app.auth().FacebookAuthProvider
but both are not working.
Please help if anyone integrated facbook login in. "expo": "~44.0.0"

How to get FB Access Token with Expo

I'm building app where i need to make Facebook Graph API requests in many places. But i dont know how to retrieve access token and then make Graph API request.
I'm using Expo, React Native and Firebase. I would like to do it without installing Xcode and/or Android Studio.
Login is working fine. My code is below:
async loginWithFacebook() {
try {
const {
type,
token,
expires,
permissions,
declinedPermissions,
} = await Expo.Facebook.logInWithReadPermissionsAsync('<APP_ID', {
permissions: ['email', 'public_profile'],
});
if (type === 'success') {
const credential = f.auth.FacebookAuthProvider.credential(token)
f.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => {
console.log(error)
})
var that = this;
const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`);
const userInfo = await response.json();
this.setState({userInfo});
this.setState({
dataSource: userInfo.data,
isLoading: false,
});
} else {
// type === 'cancel'
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
Can someone help me and give me some tips how i can use access token everywhere in my app?
Thank you in advance
Getting the token and saving it into AsyncStorage
Well the code that you have written is basically correct. You have successfully got the access token. It comes back to you when you make the Expo.Facebook.logInWithReadPermissionsAsync request. Once you have it you could then store it in Redux or AsyncStorage to be used at a later date.
logIn = async () => {
let appID = '123456789012345' // <- you'll need to add your own appID here
try {
const {
type,
token, // <- this is your access token
expires,
permissions,
declinedPermissions,
} = await Expo.Facebook.logInWithReadPermissionsAsync(appID, { permissions: ['public_profile', 'email'], });
if (type === 'success') {
// Get the user's name using Facebook's Graph API
const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); //<- use the token you got in your request
const userInfo = await response.json();
alert(userInfo.name);
// you could now save the token in AsyncStorage, Redux or leave it in state
await AsyncStorage.setItem('token', token); // <- save the token in AsyncStorage for later use
} else {
// type === 'cancel'
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
app.json
Also remember to add the following to your app.json, obviously replacing the values with your own. You get these by registering your app with Facebook, you can see more about that here https://docs.expo.io/versions/latest/sdk/facebook/#registering-your-app-with-facebook
{
"expo": {
"facebookScheme": "fb123456789012345",
"facebookAppId": "123456789012345", // <- this is the same appID that you require above when making your initial request.
"facebookDisplayName": "you_re_facebook_app_name",
...
}
}
Getting token from AsyncStorage
Then if you wanted to make another request at a later time you could have a function similar to this where you get the token out of AsyncStorage and then use it to make your request.
makeGraphRequest = async () => {
try {
let token = await AsyncStorage.getItem('token'); // <- get the token from AsyncStorage
const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); // <- use the token for making the graphQL request
const userInfo = await response.json();
alert(userInfo.name)
} catch (err) {
alert(err.message)
}
}
Snack
I would make a snack to show you this working however, snacks do not allow editing of the app.json file (as far as I can tell). So here is something that you could replace your App.js with and then if you added your appIDs etc to the app.json it should work.
import React from 'react';
import { AsyncStorage, Text, View, StyleSheet, SafeAreaView, Button } from 'react-native';
export default class App extends React.Component {
logIn = async () => {
let appID = '123456789012345' // <- you'll need to add your own appID here
try {
const {
type,
token, // <- this is your access token
expires,
permissions,
declinedPermissions,
} = await Expo.Facebook.logInWithReadPermissionsAsync(appID, {
permissions: ['public_profile', 'email'],
});
if (type === 'success') {
// Get the user's name using Facebook's Graph API
const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); //<- use the token you got in your request
const userInfo = await response.json();
console.log(userInfo);
alert(userInfo.name);
// you could now save the token in AsyncStorage, Redux or leave it in state
await AsyncStorage.setItem('token', token); // <- save the token in AsyncStorage for later use
} else {
// type === 'cancel'
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
makeGraphRequest = async () => {
try {
let token = await AsyncStorage.getItem('token');
// Get the user's name using Facebook's Graph API
const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`);
const userInfo = await response.json();
alert(userInfo.name)
} catch (err) {
alert(err.message)
}
}
render() {
return (
<View style={styles.container}>
<Button title={'Sign in to Facebook'} onPress={this.logIn} />
<Button title={'Make GraphQL Request'} onPress={this.makeGraphRequest} />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
}
});