Expo react-native bare workflow using Push notifications - react-native

Firstly i will be really appreciated for your helps.
I'am trying to implement expo push notification using expo-bare workflow. When i run app, it gives me error like this so i could not get token.
error [TypeError: null is not an object (evaluating '_ExponentNotifications.default.getExponentPushTokenAsync')]
Here is my code:
import { Notifications } from "expo";
import * as Permissions from "expo-permissions";
import Constants from "expo-constants";
export const getToken = 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") {
console.log("Failed to get push token for push notification!");
return;
}
token = await Notifications.getExpoPushTokenAsync();
}
else {
console.log("Must use physical device for Push Notifications");
}
return token;
};

You need to install the expo notifications package:
expo install expo-notifications also don't forget to cd into the ios folder and run pod install to properly link the package.
Next, you need to change the way you import and use Notifications like:
import * as Notifications from 'expo-notifications';
Then to get expo token you do something like:
Notifications.getExpoPushTokenAsync({experienceId:'#your_username/your_app_slug'})
which would resolve to a promise containing your expo token in an object format like:
{"data": "ExponentPushToken[ID]", "type": "expo"}
NB: Most method support in the Notifications from expo is different from the one in expo-notifications. You should check here for more details.

To expand on my comment some, I had a similar setup as yours when I was on Expo managed, but I ejected. According to their docs, the bare workflow is a little different, and so mine is set up like this:
// at the top:
import * as Notifications from 'expo-notifications';
// --------
// inside the code:
let settings = false
settings = Notifications.getPermissionsAsync()
if (!settings.granted) {
settings = Notifications.requestPermissionsAsync()
}
if (settings.status === 1 || settings.status === 'granted') {
const experienceId = '#proj/example' // (see docs on using expo credentials:manager)
const token = Notifications.getExpoPushTokenAsync({ experienceId })
const resp = api.sendNotificationToken({ token: token.data })
}

Related

Expo facebook login fails: error : server with the specified hostname could not be found?

UPDATE: it works in the IOS simulator, but only doesnt work in my expo go app.
I have an expo react native managed app. I tried to implement the facebook login but I always get the following error:
my code (there should not be problems with it, its just the sample code from expo)
const AuthScreen = () => {
import * as Facebook from 'expo-facebook';
const loginWithFacebook = async () => {
try {
await Facebook.initializeAsync({
appId: '<MYAPPID>',
});
const {type, token, expirationDate, permissions, declinedPermissions} =
await Facebook.logInWithReadPermissionsAsync({
permissions: ['public_profile'],
});
if (type === 'success') {
const response = await fetch(`https://graph.facebook.com/me?access_token=${token}`);
Alert.alert('Logged in!', `Hi ${(await response.json()).name}!`);
} else {
// type === 'cancel'
}
} catch ({message}) {
alert(`Facebook Login Error: ${message}`);
}
};
return (
<FontAwesome.Button name="facebook" onPress={loginWithFacebook}>Login With Facebook</FontAwesome.Button>
)
};
What I did so when registering my app:
in facebook developers I created my app 'rainy'.
In settings/basic I added IOS and Android.
a. in IOS I only added host.exp.Exponent as the Bundle ID
b. In android I only added the hash key: rRW++LUjmZZ+58EbN5DVhGAnkX4= (I couldnt find that hash on expo docs anymore but found it elsewhere and it should be up to date)
in app.json I added infoPlist with properties to ios as following:
...
"ios": {
"supportsTablet": true,
"infoPlist": {
"facebookScheme": "fb<MYAPPID>",
"facebookAppId": "<MYAPPID>",
"FacebookClientToken": "abcxxxxx", //got it from Settings > Advanced > Client Token
"facebookDisplayName": "rainy",
"facebookAutoLogAppEventsEnabled": false,
"facebookAdvertiserIDCollectionEnabled": false
}
},
...
I wasnt sure but also (after getting the error) tried to add to Valid OAuth Redirect URIs the following: https://auth.expo.io/#/rainy. not sure if even needed but the error is still the same
Also I expo installed expo-facebook.
Did I miss any step or did something wrong? Thank you!!

React Native expo-permission deprecated what to use now?

I am using Permissions from the expo-permission Library to get the location coords of the user:
import * as Location from "expo-location";
import * as Permissions from 'expo-permissions';
const granted = await Permissions.askAsync(Permissions.LOCATION);
The above works but keeps giving the warning that expo-permissions is deprecated.
If I use:
import {Location, Permissions } from 'expo';
it says Cannot read property 'askAsync' of undefined.
Does someone know what i should use? I use sdk42
Thx!
As this blog by Brent Vatne says,
expo-permissions has been deprecated in favor of module-specific permissions methods You should migrate from using
Permissions.askAsync and Permissions.getAsync to the permissions
methods exported by modules that require the permissions.
For example: you should replace calls to
Permissions.askAsync(Permissions.CAMERA) with
Camera.requestPermissionsAsync()
There shouldn’t be two ways to do an identical thing in a single SDK,
and so we picked our preferred approach and are consolidating around
it.
So now, you will have to use Permissions from individual packages
For Location,
Firstly, install expo-location
expo install expo-location
Then you can use it like this
import * as Location from 'expo-location';
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
console.log('Permission to access location was denied');
return;
}
If someone comes here and wants to get permissions for ImagePicker, then according to the docs you should do this:
import * as ImagePicker from "expo-image-picker";
const getPermissionAsync = async () => {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== "granted") {
alert("...");
}
};
Now with expo, each libs have their own permissions requests methods.
Example with Location:
let { status } = await Location.requestForegroundPermissionsAsync();
Documentation
works:
import { Camera } from 'expo-camera';
import * as ImagePicker from "expo-image-picker";
const resultPermision = await Camera.requestCameraPermissionsAsync();
const resultPermisionCamera = resultPermision.status;
if (resultPermisionCamera === "denied") {
toastRef.current.show("Gallery permissions are needed");
} else {
const result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3]
})
........
Now, expo-camera works great, but also I believe something is pending on the side of the app.json.
Do you still need to add these lines?:
"permissions": [
"CAMERA",
"WRITE_EXTERNAL_STORAGE",
"CAMERA_ROLL"
question for everyone here :)
import { Camera } from "expo-camera";
this.state = {
hasCameraPermission: null,
type: Camera.Constants.Type.back,
};
componentDidMount = async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
this.setState({ hasCameraPermission: status === "granted" });
};

stuck at asking for CAMERA_ROLL permission. getting error: undefined is not an object (evaluating '_expo.Permission.askAsync')

getting this warning (Almost an error, because app stuck at this point with showing yellow warning) while asking for the permission in react-native. Below is my code
//MY IMPORTS
import * as ImagePicker from 'expo-image-picker';
import * as Permissions from 'expo-permissions';
//My CODE
onImageUpload = async () => {
const {status, permissions} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
try {
if (status === 'granted') {
console.log("granted!!")
}
} catch (err) {
console.log('onImageUpload error:' + err.message);
}
}
You do not seem to have installed the module correctly. Perform the installation command from the command.
you'll need to run expo install expo-permissions

React-Native: Can't receive expo push notification on stand alone app

This is ss from standalone app, its gettings expo token but for some reason it wont show notifications
I can't receive push notification on my standalone apps and if someone else used the app from expo (not my phone) then he won't receive it either,
For some reason only i receive it ..that too on expo client and if i install the apk on my phone, then i get the error....
In these all situations the error is same,
{
"data": {
"status": "error",
"message": "SNS failed to send the notification (reason: EndpointDisabled, status code: 400).",
"details": {
"error": "DeviceNotRegistered",
"sns": {
"statusCode": 400,
"reason": "EndpointDisabled",
"__message": "Endpoint is disabled"
}
}
}
}
my notification js
import { Permissions, Notifications } from 'expo';
import { AsyncStorage } from 'react-native';
import axios from 'axios';
import {
IUSTCONNECT_URL
} from '../actions/types';
const server = IUSTCONNECT_URL;
export default async function registerForPushNotificationsAsync() {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== 'granted') {
// Android remote notification permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return;
}
// Get the token that uniquely identifies this device
let token = await Notifications.getExpoPushTokenAsync();
console.log(token);
await AsyncStorage.setItem('notificationToken', token);
const adminFlag = await AsyncStorage.getItem('admin');
try {
const { data } = await axios.post(`${server}/admin/app_bridge/user.php`, {
job: 'updateExpoToken',
admin: adminFlag,
token: token
});
if(data.trim() === 'success') {
console.log('expo push notification token sent:');
} else {
console.log('error sending notification token:');
console.log(data);
}
} catch (e) {
console.log(e);
}
}
and i am calling registerForPushNotificationsAsync() on my child tab,
Everything works well for my expo app...rest it doesn't...
Any help?
The issue is with the device. you can see in error DeviceNotRegistered.
see expo docs here.
DeviceNotRegistered: the device cannot receive push notifications
anymore and you should stop sending messages to the given Expo push
token.
The problem is that in docs no information why this error is happening. Try with some other device's.
if you develop with firebase you need update your token, the steps are:
1 in your page of project firebase, select option setting.
2 navigate to option project settings.
3 select option cloud messasging.
4 on credetial of project copy the token.
5. in your terminal in root directory of project type:
expo push:android:upload --api-key <your token>
for more information visit
enter link description here
try send push notification Manually
enter link description here
i'm working with sdk 37.0.0

IOS Expo Push Notifications when app is in foreground

reading from the expo docs:
For iOS, you would be wise to handle push notifications that are
received while the app is foregrounded, because otherwise the user
will never see them. Notifications that arrive while the app are
foregrounded on iOS do not show up in the system notification list. A
common solution is to just show the notification manually. For
example, if you get a message on Messenger for iOS, have the app
foregrounded, but do not have that conversation open, you will see the
notification slide down from the top of the screen with a custom
notification UI.
What I don't understand is what is the best approach for that? is there an Expo API for showing such messages? or should I create an alert component of my own? It is not really clear from the docs.
Thanks.
This answer is outdated as of February 20, 2020. Please see https://stackoverflow.com/a/60344280/2441420 for how to show iOS Notification when your application is in the Foreground
There isn't an Expo API for showing those messages. You can use any 'toast' library of your choosing and display the notification message, but that should be all your code.
For example, this is how we are doing right now:
export default class HomeScreen extends React.Component {
componentDidMount() {
this.notificationSubscription = Notifications.addListener(
(notification) => this.handlePushNotification(notification),
);
}
handlePushNotification(notification) {
const { navigation } = this.props;
PushNotificationsService.handleNotification(notification, navigation);
}
(...)
import Toast from 'react-native-root-toast';
export default class PushNotificationsService {
static handleNotification(notification, navigation) {
if (notification.data.screen && notification.origin === 'selected') {
navigation.navigate(notification.data.screen);
}
Toast.show(notification.data.message);
}
}
Toast libraries include:
react-native-root-toast
react-native-easy-toast
react-native-simple-toast
Now you can just add that in one of your app entry point. The shouldShowAlert is what you want here
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
App.json :
{
"expo": {
"notification": {
"iosDisplayInForeground": true
}
}
DEMO
I'm not sure exactly when this was added to Expo, but as of Expo version 36 is easily doable.
To show Expo Push Notifications on iOS when your app is in the foreground, please do the following:
import { Vibration } from "react-native";
import { Notifications } from "expo";
import * as Permissions from "expo-permissions";
import Constants from "expo-constants";
registerForPushNotificationsAsync = 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;
}
let token = await Notifications.getExpoPushTokenAsync();
console.log("Go to https://expo.io/notifications and copy the token below to easily send yourself a notification.");
console.warn("Notifications on iOS (and I believe Android) ONLY WORK ON A PHYSICAL DEVICE, not a simulator or emulator!!!")
console.log(token);
this.setState({ expoPushToken: token });
} else {
alert("Must use physical device for Push Notifications");
}
};
componentDidMount() {
this.registerForPushNotificationsAsync();
this._notificationSubscription = Notifications.addListener(
this._handleNotification
);
}
_handleNotification = async notification => {
if (notification.remote) {
Vibration.vibrate();
const notificationId = Notifications.presentLocalNotificationAsync({
title: "Follow #technoplato",
body: "To learn yourself goodly (also follow PewDiePie)",
ios: { _displayInForeground: true } // <-- HERE'S WHERE THE MAGIC HAPPENS
});
}
};
Quick and Easy Sanity Check
1) Go here: https://expo.io/notifications
2) Copy the token that is output to the terminal when your application is run.
3) Open your application on iOS.
4) Send a notification to yourself from https://expo.io/notifications and observe that it shows up even when your app is foregrounded.
Notes
Notifications WILL NOT BE RECEIVED ON AN IOS SIMULATOR
Expo makes Notifications ridiculously easy. I honestly can't believe it.
No idea why displayInForeground is false by default and not more prominent in the documentation. I'll submit a PR for it if I can.
Code originally found at this Snack: https://snack.expo.io/#documentation/pushnotifications?platform=ios
LocalNotification.ios._displayInForeground found here: https://docs.expo.io/versions/v36.0.0/sdk/notifications/#localnotification