Permissions in Firebase notifications - firebase

I have created this function in Google Cloud Platform associated with Firebase Realtime Database. The function sends a notification to mobile applications when something appears in the database.
As you can see below I set the priorities so that the notification will be noticed by the user
var message = {
token: tokenSnapshot,
notification: {
title: "Title",
body: "Body",
},
android: {
priority: 'high',
notification: {
sound: 'default',
priority: 'high',
visibility: 'public'
}
},
};
Unfortunately, it doesn't do anything. The notification comes but the user sees when he checks manually if something has come
I use a standard approach in the application
messaging().enable.setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', JSON.stringify(remoteMessage));
})
Is there any way for notifications to be with sound, vibration and to appear on the lock screen?
I haven't used the react-native-push-notification library yet. Can this library help in this?

If you are using firebase-cloud messaging i suggest using firebase in your app.
https://rnfirebase.io/messaging/usage
Make sure you follow the initial set up first.
Please read more about this here. https://rnfirebase.io/

Related

Convert PushNotification.localNotification to firebase push notification

I am working on a school thesis with the concept of Geofence. For my project, i have made notifications to arrive based on the boundary events. The project works with local notifications coming based on events:
Boundary.on(Events.ENTER, id => {
console.log('Background Enter');
PushNotification.localNotification({
channelId: 'boundary-demo',
title: 'ENTER SIGNAL',
message: `You've entered region: ${id} in background`,
importance: 'max',
priority: 'max',
ignoreInForeground: false,
allowWhileIdle: true,
});
});
Boundary.on(Events.EXIT, id => {
console.log('Background Exit');
PushNotification.localNotification({
channelId: 'boundary-demo',
title: 'EXIT SIGNAL',
message: `You've left region: ${id} in background`,
importance: 'max',
priority: 'max',
ignoreInForeground: false,
allowWhileIdle: true,
});
});
I am making a single app, which 2 users can login and use (Parent and child)
Right now, because it is using localnotification, One device can recieve the notification. But i need the same notifications to come at both devices.
So how do I convert PushNotification.localNotification to Firebase Push Notification.
NOTE: Both users have been linked together with firebase realtime database.
Please help, thank you so much

Redirect to a specific screen from React Native Firebase Push Notifications based on a Deeplink

I got a problem,
1 ) I'm using Firebase to send remote Push Notifications, i test by sending from FCM tester.
2 ) I've activated Deep-Linking in my project and started to use it.
3 ) In FCM tester i pass this key value into "notifications.data" :
{ "link" : "MY_LINK" }
Now i want my app to be able to recognize there is a deepLink in it & read it.
Which i achieved to do somehow but not the way i was looking for.
What i did :
NotificationContextProvider.ts
useEffect(() => {
const unsubscribeClosedApp = messaging().onNotificationOpenedApp(
remoteMessage => {
addNotification(remoteMessage);
console.log(
'Notification caused app to open from background state:',
remoteMessage.notification,
);
redirectFromKey(remoteMessage.data?.redirection);
console.log(remoteMessage.data, 'remote message data');
console.log(remoteMessage, 'remote message full');
console.log(remoteMessage.notification?.body, 'remote message body');
console.log(remoteMessage.notification?.title, 'remote message title');
if (remoteMessage.data?.link === 'https://[MY-LINK]/TnRV') {
console.log(remoteMessage.data?.link, 'Deeplink detected & opened');
navigation.navigate({
name: 'Logged',
params: {
screen: 'Onboarded',
params: {
screen: 'LastAnalyse',
},
},
});
}
},
);
And it's working fine but it's not based on reading a link, but by comparing a value and it's not what i'm trying to achieve.
Firebase Doc' give us a way to do this : https://rnfirebase.io/dynamic-links/usage#listening-for-dynamic-links
This is what Firebase suggests :
import dynamicLinks from '#react-native-firebase/dynamic-links';
function App() {
const handleDynamicLink = link => {
// Handle dynamic link inside your own application
if (link.url === 'https://invertase.io/offer') {
// ...navigate to your offers screen
}
};
useEffect(() => {
const unsubscribe = dynamicLinks().onLink(handleDynamicLink);
// When the component is unmounted, remove the listener
return () => unsubscribe();
}, []);
return null;
}
And i have no clue how to make it works.
I got to mention that deep-links are correctly setup in my project and working fine, my code is in Typescript.
Basicaly you can find on this web page what i'm trying to achieve but i want to use Firebase/messaging + Dynamic links. My project don't use local notifications and will never do : https://medium.com/tribalscale/working-with-react-navigation-v5-firebase-cloud-messaging-and-firebase-dynamic-links-7d5c817d50aa
Any idea ?
I looked into this earlier, it seems that...
You can't send a deep link in an FCM message using the firebase Compose Notification UI.
You probably can send a deep link in an FCM message using the FCM REST API. More in this stackoverflow post.
The REST API looks so cumbersome to implement you're probably better off the way you're doing it: Using the firebase message composer with a little data payload, and your app parses the message data with Invertase messaging methods firebase.messaging().getInitialNotification() and firebase.messaging().onNotificationOpenedApp().
As for deep linking, which your users might create in-app when trying to share something, or you might create in the firebase Dynamic Links UI: For your app to notice actual deep links being tapped on the device, you can use Invertase dynamic links methods firebase.dynamicLinks().getInitialLink() and firebase.dynamicLinks().onLink().

Remove notification after a certain time in React Native (#react-native-firebase/messaging)

I have push notifications working in React Native using #react-native-firebase/messaging. I am using FCM on the backend, and it is currently showing the OS lock screen notifications on iOS and Android.
I want to clear a given notification after a certain time, or after an amount of time has passed. Is there a way to do this? Right now when I send a notification it will stick around for days if I don't click on it. I would like to take a notification down after say an hour, or at 4pm, or whatever. Front-end and/or back-end solutions welcome.
I had assumed that the "ttl" (time to live) parameter did this, but this is not the case.
you could use a background handler like react-native-background-fetch
In your onMessage or backgroundMessage schedule a backgroundTask for your desired time with scheduleTask().
You could use react-native-push-notification to display the notification, which has an method cancelLocalNotifications() to cancel notifications
In the task you could clear the notification depending on the id
PushNotification.configure({
onNotification: (notification) => {
var {id} = remoteMessage.data
BackgroundFetch.configure({
minimumFetchInterval: 15
}, async (taskId) => {
PushNotification().cancelLocalNotifications(id)
BackgroundFetch.finish(taskId);
})
BackgroundFetch.scheduleTask({
taskId: id,
forceAlarmManager: true,
delay: 5000
});
}
})
TTL parameter only specifies the delivery of the notification to the user device. E.g. Still deliver the message after the phone was offline for 2 hours or not.
I'm not sure if there is a way with the default firebase package, but the more advanced version of it seems to be able to handle that use case:
https://notifee.app/react-native/reference/canceldisplayednotification
I think you should be able to call that method in a background task (e.g. after receiving another (silent) notification).
Unfortunately I couldn’t test it myself yet.
On iOS you you can use the badge setting. If you set it to 0, it will remove all notifications. For your case you could schedule a "cleanup" task that triggers the below request after a certain amount of time.
{
message: {
notification: {
body: "" // has to be empty
},
android: {
notification: {
channel_id: 'some_channel'
}
},
apns: {
payload: {
aps: {
category: 'some_category',
badge: 0
}
}
},
token: device_token
}
}
Unfortunately, I have not found a similar solution for android yet.

How to use Sign-In User ID to send push notifications

I have some users signed into my actions-on-google app via Google Sign-In ( https://developers.google.com/actions/identity/google-sign-in )
I want to sent push notifications to one of those users.
For getting push notifications work with actions in the first place, I tried this sample: https://github.com/actions-on-google/dialogflow-updates-nodejs/blob/master/functions/index.js but I only can get this to work without this commit: https://github.com/actions-on-google/dialogflow-updates-nodejs/commit/c655062047b49e372da37af32376bd06d837fc7f#diff-1e53ef2f51bd446c876676ba83d7c888
It works fine, but I think const userID = conv.user.id; returns the deprecated Anonymous User ID. The commit suggests to use const userID = conv.arguments.get('UPDATES_USER_ID'); which returns undefined.
I use this nodejs code to send the push notifications.
const request = require('request');
const {JWT} = require('google-auth-library');
const serviceAccount = require('./service-account.json');
let jwtClient = new JWT(
serviceAccount.client_email, null, serviceAccount.private_key,
['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
null
);
jwtClient.authorize((authErr, tokens) => {
let notification = {
userNotification: {
title: process.argv[2],
},
target: {
userId: USERID,
intent: 'tell_latest_status',
// Expects a IETF BCP-47 language code (i.e. en-US)
locale: 'en-US'
},
};
request.post('https://actions.googleapis.com/v2/conversations:send', {
'auth': {
'bearer': tokens.access_token,
},
'json': true,
'body': {
'customPushMessage': notification, 'isInSandbox': true
},
}, (reqErr, httpResponse, body) => {
console.log(httpResponse.statusCode + ': ' + httpResponse.statusMessage);
});
});
I simply can't get this to work with the const userID = conv.arguments.get('UPDATES_USER_ID'); version, because as I said
When I use conv.user.profile.payload.sub as suggested here: https://developers.google.com/actions/identity/user-info the AoG API returns "SendToConversation response: Invalid user id for target."
Is there any way to make this work with Google Sign-In?
Has anyone made this work? I mean with the UPDATES_USER_ID field?
I already created an issue on the samples repo: https://github.com/actions-on-google/dialogflow-updates-nodejs/issues/15 but I was sent here.
Thanks!
While researching why I sometimes got undefined I found an answer on this question that solved my issue.
I've found solution for this problem. While getting UPDATES_USER_ID
conv.arguments.get() only works for first attempt. So, while building
your action you must save it. If you didn't store or save, you can
reset your profile and try again, you will be able to get.
You can reset your user profile for the action here.

Error trying to test tokenized payments

CONTEXT
I'm writing a custom checkout process using tokenized payments inside a WebView since I need to use payments outside US.
I'm using this code, based on this facebook guide, to ask for the user's credit card info.
const saveThis = this
MessengerExtensions.requestPaymentCredentials(
function success(name, email, cardType, cardLastFourDigits, shippingAddress) {
console.log('success getting user payment info', cardLastFourDigits)
saveThis.printAsyncData(cardType)
},
function error(err, errorMessage) {
console.log('error trying to get user payment info', errorMessage)
saveThis.printAsyncData(errorMessage)
},
['CONTACT_NAME', 'CONTACT_EMAIL', 'CONTACT_PHONE', 'SHIPPING_ADDRESS']
);
CONSIDERATIONS
saveThis.printAsyncData() function is a workaround to log the
output in mobile devices so I can debug the code, since payments
don't work using the Messenger web client.
I'm testing this chatbot with my facebook account which is the one having the chatbot's Administrator role.
Administrator user returns the profile property is_payment_enabled: true
OUTPUT
I'm getting the following error: "An unexpected error has occured.24002". In the facebook's error reference, 24002 means "Payment request cannot be processed due to missing privacy url".
QUESTION
Does that mean that I have to provide a privacy policy URL to test payments even when I'm using the Administrator's chatbot account in a testing environment??
UPDATE
As suggested, I implemented the updated WebView payment code as follows:
const methodData = [{
supportedMethods: ['fb'], //only 'fb' is supported
data: {
merchantTitle: 'Merchant name', // optional, defaults to the Facebook Page name
merchantImageUrl: 'imageURL', //optional, defaults to the app icon
confirmationText: 'Thank you!', // optional, defaults to "Thank you for your payment"
merchantFBPageId: '28636603843****', // page id with onboarded payment method. Need to be the same with the page id in thread or messenger extension
termsUrl: 'https://www.facebook.com/' // Merchant payment privacy terms and conditions.
}
}]
const paymentDetails = {
displayItems: [ //array of items being charged for
{
label: 'T-shirt',
amount: {
currency: 'USD',
value : '15.00'
}
}
],
total: {
label: 'Total', // defaults to "Total"
amount: {
currency: 'USD',
value : '16.23'
}
},
shippingOptions: [ // Optional. Array of options for user to select
{
id: 'free-shipping', // custom ID
label: 'Free shipping in US', //human-readable name
amount: {currency: 'USD', value: '0.00'},
selected: true
}
]
}
const additionalOptions = {
requestShipping: false, // If shipping is required. If true, handle shippingoptionchange and shippingaddresschange events.
requestPayerName: true, // Name of the payer sent with the final response
requestPayerEmail: true, // Email address, same as above
requestPayerPhone: false // Phone number, same as above
}
let request = new this.messengerExtensions.PaymentRequest(
methodData, // array of payment methods and their setup
paymentDetails, // array of items, total, shipping options
additionalOptions, // request shipping information, payee email address, etc
);
request.canMakePayment()
.then(response => {
this.printAsyncData(response + ' from canMakePayment')
if (response === true) {
// proceed
} else {
// something went wrong, e.g. invalid `displayItems` configuration
// or the device does not run a
// recent enough version of the Facebook app
}
})
.catch(error => {
this.printAsyncData(error+' error from canMakePayment')
// an error such as `InvalidStateError`
// if a payment is already in process
});
This suggested implementation returns the variable response as false. Each configuration variable is copied from this link. I changed the MerchantPageID with the PageID I found on my Chatbot's fb page > Information, so I don't think this could be the problem. I checked the Messenger's version of my Android device and is the latest, being the 147.0.0.25.86 one.
I even tried to implement the payment dialog as follows just to see how it behaves.
request.show().then(response => {
// Process the payment if using tokenized payments.
// Process the confirmation if using Stripe/PayPal
this.printAsyncData(response)
// paymentResponse.complete('success').then(() => {
// // cleanup UI, log, etc
// });
}).catch(error => this.printAsyncData(error+'from show()'));
Payment dialog pops over nicely. It shows user's name and email but under the METHOD PAYMENT header it shows a loading spinner indefinitely. Moreover, .show() never triggers the callback thus not allowing to print its response on the line before paymentResponse.complete('success').
UPDATE 2
I've got the supported features with the following code to try to get some clue of what I'm missing
const saveThis = this
MessengerExtensions.getSupportedFeatures(function success(result) {
var features = result.supported_features;
saveThis.printAsyncData(features)
}, function error(err, errorMessage) {
saveThis.printAsyncData(errorMessage)
});
This is the output on my android messenger client:
["sharing_broadcast","sharing_direct", "sharing_open_graph", "permissions", "thread_context", "context", "sharing_media_template"]
There is no "payments" as it should be, based on this reference
Yes, but since you are just testing it can be any URL. Once you submit your bot for approval it will need to point to a real privacy policy.
You are also using the deprecated version of payments. For webview payments you should use PaymentRequest which is explained here:
https://developers.facebook.com/docs/messenger-platform/payments/webview-payments

Resources