So I am trying to use react-native-fbsdk FBAppInviteDialog to show invitation dialog but I always get this error
I was trying to use this code from Sending App Invites in a React Native app
here is my code
constructor (props) {
super(props)
this.state = {
appInviteContent: {
applinkUrl: 'https://facebook.com'
}
}
}
_onPress = () => {
var tmp = this
AppInviteDialog.canShow(this.state.appInviteContent).then(
function (canShow) {
if (canShow) {
return AppInviteDialog.show(tmp.state.appInviteContent)
}
}
).then(
function (result) {
if (result.isCancelled) {
Alert.alert('Share cancelled')
} else {
Alert.alert('Share success with postId: ' + result.postId)
}
},
function (error) {
Alert.alert('Share fail with error: ' + error)
}
)
}
If you want that the showDialog works you must first as the example show something like this:
appInviteContent= {
contentType: 'link',
contentUrl: Platform.select({ ios: 'https://iossomething.com',
android: 'https://androidsomething.com'}),
contentDescription: 'Check the website!',
};
Also as I see there in the code you are using the flow language.
Check that.
Related
🐛 Bug Report
AppLink.fetchDeferredAppLink() always returns null in android and undefined in iOS.
To Reproduce
I use https://developers.facebook.com/tools/app-ads-helper to test the deep-link. Here i enter the uri-scheme of the app and checked both Send Notification & Send Deferred.
It shows two popup,
If i click on the notification which i received on the developer facebook account, it is opening the installed app, but the method AppLink.fetchDeferredAppLink() always returns null/undefined.
I tried uninstaling the app, then clicked on the deferred link, then installed and opened the app, still same.
Code Example
const fbsdkInit = (bool) => {
if (bool) {
Settings.setAdvertiserTrackingEnabled(bool).then(() => {
Settings.initializeSDK();
AppLink.fetchDeferredAppLink().then((link) =>
console.log("Link 1", link)
);
});
} else {
Settings.initializeSDK();
AppLink.fetchDeferredAppLink().then((link) => console.log("Link 2", link));
}
};
async function getATTPermissionForFbAppEvents() {
const ATT_CHECK = await check(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
if (ATT_CHECK === RESULTS.DENIED) {
try {
const ATT = await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
if (ATT === RESULTS.DENIED) {
getATTPermissionForFbAppEvents();
} else {
if (ATT === RESULTS.GRANTED) {
fbsdkInit(true);
} else {
fbsdkInit(false);
}
}
} catch (error) {
fbsdkInit(false);
}
} else if (ATT_CHECK === RESULTS.GRANTED) {
fbsdkInit(true);
} else {
fbsdkInit(false);
}
}
componentDidMount() {
if (Platform.OS === "ios" && Number(Platform.Version) > 14.4) {
getATTPermissionForFbAppEvents();
} else {
fbsdkInit(true);
}
}
I am currently using the following Libraries:
react-native-version-check
react-native-navigation (By Wix)
I would like to ask, what is the best practice on what event should I use in "react-native-navigation" to do a "react-native-version-check"? I created multiple pages using hooks, and ideally would not like to use the "UseEffect" in order to check the app version if it's the latest.
I have attached my code below, this is during registering all the app screen:
Navigation.events().registerCommandCompletedListener(async (event) => {
try {
console.log('Version Check Attempting');
let current = await VersionCheck.getCurrentVersion();
let latest = await VersionCheck.getLatestVersion();
let response = await VersionCheck.needUpdate({
currentVersion: current,
latestVersion: latest,
});
if (isChecked) { return }
if (response.isNeeded) {
Navigation.showOverlay({
component: {
name: "UpdateRequired",
options: {
layout: {
componentBackgroundColor: 'transparent'
},
},
},
});
isAllModalDismissed = false
isChecked = true
} else {
if(isChecked === false && isAllModalDismissed === true) {
isAllModalDismissed = true;
await Navigation.dismissAllOverlays();
}
}
} catch(error) {
console.log(error)
} finally {
console.log('Version Check Finished');
}
})
From the code below, I'm sending email using EmailJs library and the alert method get's executed after submitting but the change method doesn't. What I'm I missing?
Error message on the console is
Uncaught (in promise) TypeError: Cannot read property 'change' of undefined
at app.js:2755
My Script
<script>
import emailjs from "emailjs-com";
export default {
data() {
return {
flash: false,
};
},
methods: {
sendEmail: (e) => {
emailjs
.sendForm(
"service_k9mhh",
"template_epghgfh",
e.target,
"user_w9U76tg77yhcggh"
)
.then(
(result) => {
console.log("SUCCESS!", result.status, result.text);
alert("Message Sent Successfully")
this.change();
},
(error) => {
console.log("FAILED...", error);
}
);
// Reset form field
},
change(){
this.flash = true;
}
},
};
</script>
Without arrow functions as shown below, It still throws the same error.
methods: {
sendEmail: function (e) {
emailjs
.sendForm(
"service_",
"template_",
e.target,
"user_"
)
.then(
function (result) {
console.log("SUCCESS!", result.status, result.text);
this.change();
},
function (error) {
console.log("FAILED...", error);
}
);
},
change: function () {
this.flash = true;
}
The problem is that in arrow functions this does not refer to the Vue instance so this.change is not defined there.
Read this:
https://v2.vuejs.org/v2/guide/instance.html#Data-and-Methods
Okay so you and eldo were both half right. You need to use a regular function syntax when declaring a method, and an arrow function in any nested .then's.
Using an arrow function in your then and catch handler's ensures that 'this' remains a reference to the Vue instance.
Your method wants to look like this:
sendEmail(e) {
emailjs
.sendForm("service_", "template_", e.target, "user_")
.then((result) => {
console.log("SUCCESS!", result.status, result.text);
this.change();
})
.catch((error) => {
console.log("FAILED...", error);
});
},
I am Trying to implement signing up with Facebook feature for my react-native app and i am stuck at this stage that Data is successfully retrieved from the profile and I have check it on the alert screen. Here is my Code in which I call the Function of another component (FBLogin).First of all there is a Touchable Opacity(Custom UI for facebook login Button)
<TouchableOpacity // This is in the Main Screen
onPress={() => {
this.goFacbookLogin()
}}
</TouchableOpacity>
Here is My Function which is being called on the onPress Event.
async goFacbookLogin(){ // This is also a function on the Main Screen
await FBLogin.facebookLogin().then((data) =>{
alert("Data: " + JSON.stringify(data));
});
}
Now The FBLogin is basically a service for login as facebook. and it has a function facbookLogin()
import React, { Component } from 'react';
import { View, Button, Dimensions } from 'react-native';
import {LoginManager, LoginButton,
AccessToken,GraphRequest,GraphRequestManager } from 'react-native-fbsdk';
class FBLoginButton extends Component{// This is Implemented in another File
constructor(props)
{
super(props);
this.state =
{
//screenWidth: Dimensions.get("window").width,
//screenHeight: Dimensions.get("window").height,
UserProfileInformation:
{
UserAge: null,
Gender: null,
UserLocation: null,
ImageUrl: null,
}
}
}
async facebookLogin()
{
let _result;
try
{
LoginManager.setLoginBehavior('NATIVE_ONLY');
_result = await LoginManager.logInWithReadPermissions(['public_profile',
"email","user_birthday", "user_gender","user_hometown"]);
console.warn("Done");
}
catch (nativeError)
{
try
{
LoginManager.setLoginBehavior('WEB_ONLY');
_result = await LoginManager.logInWithReadPermissions(['public_profile',
"email", "user_birthday", "user_gender", "user_hometown"]);
}
catch (webError)
{
alert("Function Called Web Error");
}
}
if (_result.isCancelled)
{
alert('Login Cancel')
}
else
{
global.res1 = "None";
const data = await AccessToken.getCurrentAccessToken();
const infoRequest = new GraphRequest
(
'/me',
{
accessToken: data.accessToken,
parameters:
{
fields:
{
string: 'first_name, name, gender, birthday, email, hometown'
}
}
},
(error, result) => {
if (error)
{
alert("error: " + JSON.stringify(error));
}
else
{
let UserProfileInformation = this.state.UserProfileInformation;
UserProfileInformation['Gender'] = result.gender;
UserProfileInformation['UserLocation'] = result.hometown.name;
this.setState({ UserProfileInformation: UserProfileInformation}, ()
=> console.warn("DDDDD: " + this.state.UserProfileInformation));
res1 = result;
}
}
);
new GraphRequestManager().addRequest(infoRequest).start()
return(this.state.UserProfileInformation);
}
//return "Done";
}
}
export default FBLogin = new FBLoginButton();
Now the Problem Here is that when Graph Request Starts the InfoRequest it Fetches the Data successfully in the callback function but i have no idea how to return it to the main function call in which i have implemented then statement after the function call. Currently The data gets stored in a state but as state takes time to change the return statement executed early and i got null but when i press the opacity button second time, the data is correct as it's previous state was changed.
i have tried global and let variables but they got destroyed after the callback function ends.
In Short All I want is to return this result to the facebookLogin in the Main Screen.
i am New in React Native so If any one can help it would really be appreciated.
I am using react-native-firebase with messaging to deliver notifications to my app with cloud functions, with admin.messaging().send(message), very similar to here: https://medium.com/the-modern-development-stack/react-native-push-notifications-with-firebase-cloud-functions-74b832d45386 .
I receive notifications when the app is in the background. Right now I am sending a text in the body of the notification, like 'a new location has been added to the map'. I want to be able to add some sort of deep link, so that when I swipe View on the notification (on iOS for example), it will take me to a specific screen inside the app. How do I pass data from the notification to the app?
I am using react-native-navigation in the app. I can only find code about deep links from inside the app (https://wix.github.io/react-native-navigation/#/deep-links?id=deep-links).
My solution was to use add what information I need in the data object of the notification message object:
in functions/index.js:
let message = {
notification: {
body: `new notification `
},
token: pushToken,
data: {
type: 'NEW_TRAINING',
title: locationTitle
}
};
and process as follows in the app for navigation:
this.notificationOpenedListener =
firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
if (notification.data.type === 'NEW_TRAINING') {
this.props.navigator.push({
screen: 'newtrainingscreen',
title: notification.data.title,
animated: true
});
}
I think you are fine with the "how firebase notification work"... cause of this, here is only an description of the Logic how you can Deeplinking into your App.
If you send a notification, add a data-field. Let's say your app has a Tab-Navigator and the sections "News","Service" and "Review".
In your Push-Notification - Datafield (let's name it "jumpToScreen" you define your value:
jumpToScreen = Service
I assume you still have the Handling to recieve Notifications from Firebase implemented.
So create an /lib/MessageHandler.js Class and put your business-logic inside.
import firebase from 'react-native-firebase';
/*
* Get a string from Firebase-Messages and return the Screen to jump to
*/
const getJumpPoint = (pointer) => {
switch (pointer) {
case 'News':
return 'NAV_NewsList'; // <= this are the names of your Screens
case 'Service':
return 'NAV_ServiceList';
case 'Review':
return 'NAV_ReviewDetail';
default: return false;
}
};
const MessageHandler = {
/**
* initPushNotification initialize Firebase Messaging
* #return fcmToken String
*/
initPushNotification: async () => {
try {
const notificationPermission = await firebase.messaging().hasPermission();
MessageHandler.setNotificationChannels();
if (notificationPermission) {
try {
return await MessageHandler.getNotificationToken();
} catch (error) {
console.log(`Error: failed to get Notification-Token \n ${error}`);
}
}
} catch (error) {
console.log(`Error while checking Notification-Permission\n ${error}`);
}
return false;
},
clearBadges: () => {
firebase.notifications().setBadge(0);
},
getNotificationToken: () => firebase.messaging().getToken(),
setNotificationChannels() {
try {
/* Notification-Channels is a must-have for Android >= 8 */
const channel = new firebase.notifications.Android.Channel(
'app-infos',
'App Infos',
firebase.notifications.Android.Importance.Max,
).setDescription('General Information');
firebase.notifications().android.createChannel(channel);
} catch (error) {
console.log('Error while creating Push_Notification-Channel');
}
},
requestPermission: () => {
try {
firebase.messaging().requestPermission();
firebase.analytics().logEvent('pushNotification_permission', { decision: 'denied' });
} catch (error) {
// User has rejected permissions
firebase.analytics().logEvent('pushNotification_permission', { decision: 'allowed' });
}
},
foregroundNotificationListener: (navigation) => {
// In-App Messages if App in Foreground
firebase.notifications().onNotification((notification) => {
MessageHandler.setNotificationChannels();
navigation.navigate(getJumpPoint(notification.data.screen));
});
},
backgroundNotificationListener: (navigation) => {
// In-App Messages if App in Background
firebase.notifications().onNotificationOpened((notificationOpen) => {
const { notification } = notificationOpen;
notification.android.setChannelId('app-infos');
if (notification.data.screen !== undefined) {
navigation.navigate(getJumpPoint(notification.data.screen));
}
});
},
appInitNotificationListener: () => {
// In-App Messages if App in Background
firebase.notifications().onNotificationOpend((notification) => {
notification.android.setChannelId('app-infos');
console.log('App-Init: Da kommt ne Message rein', notification);
firebase.notifications().displayNotification(notification);
});
},
};
export default MessageHandler;
In your index.js you can connect it like this:
import MessageHandler from './lib/MessageHandler';
export default class App extends Component {
state = {
loading: null,
connection: null,
settings: null,
};
async componentDidMount() {
const { navigation } = this.props;
await MessageHandler.initPushNotification();
this.notificationForegroundListener = MessageHandler.foregroundNotificationListener(navigation);
this.notificationBackgroundListener = MessageHandler.backgroundNotificationListener(navigation);
this.setState({ loading: false, data });
}
componentWillUnmount() {
this.notificationForegroundListener();
this.notificationBackgroundListener();
}
async componentDidMount() {
MessageHandler.requestPermission();
AppState.addEventListener('change', this.handleAppStateChange);
MessageHandler.clearBadges();
}
componentWillUnmount() {
AppState.removeEventListener('change', this.handleAppStateChange);
}
handleAppStateChange = (nextAppState) => {
if (nextAppState.match(/inactive|background/)) {
MessageHandler.clearBadges();
}
....
I hope this give you an Idea how to implement it for your needs.
I think you don't need to use deep links nor dynamic links but just use Firebase/Notifications properly. If I were you I would add the following logic in the componentDidMount method of your parent container:
async componentDidMount() {
// 1. Check notification permission
const notificationsEnabled = await firebase.messaging().hasPermission();
if (!notificationsEnabled) {
try {
await firebase.messaging().requestPermission(); // Request notification permission
// At this point the user has authorized the notifications
} catch (error) {
// The user has NOT authorized the notifications
}
}
// 2. Get the registration token for firebase notifications
const fcmToken = await firebase.messaging().getToken();
// Save the token
// 3. Listen for notifications. To do that, react-native-firebase offer you some methods:
firebase.messaging().onMessage(message => { /* */ })
firebase.notifications().onNotificationDisplayed(notification => { /* */ })
firebase.messaging().onNotification(notification => { /* */ })
firebase.messaging().onNotificationOpened(notification => {
/* For instance, you could use it and do the NAVIGATION at this point
this.props.navigation.navigate('SomeScreen');
// Note that you can send whatever you want in the *notification* object, so you can add to the notification the route name of the screen you want to navigate to.
*/
})
}
You can find the documentation here: https://rnfirebase.io/docs/v4.3.x/notifications/receiving-notifications