I'm doing my final year project about flood push notification. Previously, a user will retrieve notifications whenever the value in database changes from 0 to 1. But right now,in my app, the user can choose which places he parks his car and he can retrieved status and notification based on the park's place whether it's zero or one. As for example, User A set his spinner value in Mid Valley and User B set his spinner value in KPS. User A will get notification when FLOOD_STATUS_MID_VALLEY is 1, while User B didn't receive any notifications because FLOOD_STATUS_KPS is still 0. Anyone can help me on how to send notification based on the spinner value in the app?
Screenshot of my app
Screenshot
below is the python code that running on server to send notification based on a value called "FLOOD_STATUS" in firebase database
from pusher_push_notifications import PushNotifications
config = {
'apiKey': "APIKEY",
'authDomain': "car-app-push-notification.firebaseapp.com",
'databaseURL': "https://car-app-push-notification.firebaseio.com",
'projectId': "car-app-push-notification",
'storageBucket': "car-app-push-notification.appspot.com",
'messagingSenderId': "596729642105",
'appId': "APPID",
'measurementId': "G-9LMJGS1BDW"
}
firebase = pyrebase.initialize_app(config)
db = firebase.database()
beams_client = PushNotifications(
instance_id='49f62b05-bd81-4040-ab57-80afa56a8680',
secret_key='SECRET KEY',
)
def stream_handler(message):
print(message)
if(message['data'] is 1):
response = beams_client.publish_to_interests(
interests=['hello'],
publish_body={
'apns': {
'aps': {
'alert': 'Hello!',
},
},
'fcm': {
'notification': {
'title': 'Alert!',
'body': 'It is starting to flood, please remove your car immediately!',
},
},
},
)
print(response['publishId'])
my_stream = db.child("FLOOD_STATUS").stream(stream_handler,None)
As this is your FYP, I won't provide any code for this.
When a user changes where they parked, you will want to change their device interest to match the relevant location.
When the FLOOD_STATUS is updated to 1 for a given location, you send the notification to the matching interest.
I suggest that, when the user A select the MID_VALLEY in the Spinner you send the selected value to the server. I recommend you to have a look on this tutorial to see how to get the selected value from Spinner
At server side, when the FLOOD_STATUS_MID_VALLEY is 1 you only send the notification to the user A(because you knew the FCM token of the user A).
If you want to custom the item of Spinner you can watch this tutorial.
Related
Is it possible to cancel a pushed notification before displaying it on the users phone ?
I have some custom logic which decides whether a notification needs to be displayed/appear . Is it possible for me to control this behaviour from the client side ios/android code ?
Once a message is sent to Firebase Cloud Message, there is no way to cancel its delivery.
If your message contains only a data element and no notification, displaying the message is handled by your application code - so in that case you may be able to suppress its display there.
Although the best way is to handle this is to cancel it on backend side, you still can add UNNotificationServiceExtension and override the didReceive method:
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
self.receivedRequest = request;
self.contentHandler = contentHandler
self.content = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let content = self.content {
// I had to check something inside the push itself
if let infoDictionary = content.userInfo {
// Check something inside the push notification
contentHandler(content)
return
}
}
// Otherwise, send an empty notification to the system and it will show nothing
contentHandler(UNNotificationContent())
}
I'm totally new to Cloud Functions of Firebase and I need a little support.
I would to trigger two cloud functions, one that run once a day and the other one that sends a push notification to my Android client app.
Just let me write a little representation of my Cloud Firestore (not Realtime Database), IDs are auto generated by Firebase:
/users
/uId1
/myitems
/adId1
/myinterestedusers
/uId2
/adId2
...
/uId2
...
/itemsonsale
/uId1_adId1
/uId1_adId2
/uId2_adId1
I perform all the operations to populate and update the db correctly in the client side Android app written in koltin but I need these more things.
The function I would trigger once a day has to update a field if a string in a adIdXX document, representing the date, is expired and then it should be change another field in the same documentReference with string "EXPIRED". All this operation must be done for each docRef that have a adIdXX in all the db, so for each /myitems/{id} of each /users/{id} and for each /itemsonsale/{id}.
The other one, that must be send a push notification to my client, has to listen for the same status as above but when it will be "SOLD" it must notify the interested users, so for example I thought that it's enough to watch the /itemsonsale collection and for each {id} document check this field and then following this path to send notification to that user in /users:
/itemsonsale/{id} checks fields "status"=="SOLD"
take ownerID
go to /users/ownerIdXX/myitems/adIdXX/myinterestedusers/{id}
and send a push notification for each of those {id} documents in that collection
NOTE: uIdXX_adIdXX stands for ownerId_adId
Hope I explained my idea and wait for support cause I have no idea of where to start...
EDITED: after a few hours I'm stuck on this code below...anyone can tell me how can I continue?
exports.checkItemsSold =
functions.firestore.document('/itemsonsale/{id}')
.onUpdate((change, context) => {
const after = change.after.data()
const before = change.before.data()
const oldStatus = before.itemStatus
const newStatus = after.itemStatus
console.log(`Item's owner replaced ${oldStatus} with ${newStatus}\n`)
if(newStatus === "SOLD")
{
//here I have to send push to interested users
}
})
exports.checkItemsExpirationDate =
functions.firestore.document('/users/{uid}/myitems/{iid}') //but really all the db so also /itemsonsale/{id}
.onUpdate((change, context) => {
const after = change.after.data()
const before = change.before.data()
//I'm not sure if onUpdate() is the right way for this task
//but this function has to perform the check of date expiration
//from 'expiryDate' field and in case of it's expired must set
//"EXPIRED" to 'itemStatus' field. All for each item in the db, once a day
console.log('Updated info from data: ', after)
});
After checking your code I can say that at least this section is ok:
exports.checkItemsSold =
functions.firestore.document('/itemsonsale/{id}')
.onUpdate((change, context) => {
const after = change.after.data()
const before = change.before.data()
const oldStatus = before.itemStatus
const newStatus = after.itemStatus
console.log(`Item's owner replaced ${oldStatus} with ${newStatus}\n`)
if(newStatus === "SOLD")
{
//here I have to send push to interested users
}
})
The main issue with the second one is that the triggers only happens when there is an update, write, delete or create event. As you're not waiting for an update or any of the other events but checking the status of some fields on your DB I would say that you can create an scheduled function. Here you will find an example code which is something like this for your case:
//Let's supose that you want to check the expiration date every day in the first minute of the day
const admin = require('firebase-admin');
admin.initializeApp();
let db = admin.firestore();
exports.scheduledFunctionCrontab = functions.pubsub.schedule('1 0 * * *')
.timeZone('America/New_York') // Users can choose timezone - default is America/Los_Angeles
.onRun((context) => {
//Here goes your code to change the status of the field needed in your DB to Expired.
return null;
});
Sorry if there is a mistake with the code but I'm not good with NodeJS. Good luck!
UPDATE:
Ok so from all the comments I got convinced that using Firebase is the best solution for a number of reasons but how would I check for that change (canceled == yes) in my json file from firebase and automatically send the notification if the course is canceled.
Sample JSON response:
{
"class" : "Class",
"time" : "00:00",
"trainer" : "T",
"canceled" : ""
},
{
"class" : "Class",
"time" : "00:00",
"trainer" : "T",
"canceled" : ""
}
INITIAL QUESTION
I am parsing a json api and one of the fields is called canceled.
I would like my app to set a notification whenever that canceled key has a value of yes and so far it's easy, just create a simple notification like in the android developer topic and if canceled == yes update the Builder and then notify();.
The issue here is how can I keep checking for changes in the json after the app has been closed and set the notification ?
I have access to the server and make changes to the api if required.
Can I do this without the help of any third party services?
As #Sujal mentioned With Android O you have restriction on running background service for a long time. So It's better move this thing to server side. Whenever there is a change in the status i.e. Whenever key canceled becomes yes send a notification to android device which would show the Notification.
Ref : https://firebase.google.com/docs/cloud-messaging/
Ref : https://www.codementor.io/flame3/send-push-notifications-to-android-with-firebase-du10860kb
I´m creating this chat app using Firebase. I wanted to create a system
where every device having the chat app installed is responsible for delivering chat messages.
Even if the device did not send the message it plays a part in the pool of workers, that deliver chat messages.
Now for a normal chat app the device that creates the chat message can easily send the message using E.g. OneSignal.
In my case user can chat with abstract things and there can be many people listening for new chat messages. One is sending and 1000+ is listening.
Here is where the problem comes. If one device is responsible for notifying 1000+ other it can get really heavy on the load. I was thinking all other devices can help out with the delivery,
so I´m trying this Firebase database notification entry:
{
"NOTIFICATIONS" : {
"-Kg4_cnR9T8Efx77rL2n" : {
"targetId" : "-KfpVVenyQccKqAxxrvE",
"text1" : "There´s a message for you",
"text2" : "Pluto",
"text3" : "",
"time" : 1490447404504,
"type" : "chatMessage"
},
"-Kg4_eWQFZndhztPqSTp" : {
"targetId" : "-KfpWz7ZWBAa_8pLM7tI",
"text1" : "There´s a message for you",
"text2" : "Saturnus",
"text3" : "",
"time" : 1490447411536,
"type" : "chatMessage"
}
}
}
and when one device is creating a message it post this new NOTIFICATIONS that will be picked up by all devices that are listening.
Now since all devices is listening on the NOTIFICATIONS and will grab one NOTIFICATIONS and send the chat message heads up, to all other devices that are registered on the targetId the problem obviously arise.
Here are the TARGET_VISITORS. This are the users that are registers for new chat messages.
{
"TARGET_VISITORS" : {
"-KfpVVenyQccKqAxxrvE" : {
"HnhLyXRxUINmlltK3jdsfxx2QBYiQ53" : {
"notify" : true,
"time" : 1490300590623,
"userFirebaseId" : "HnhLyXRxUINmlltK3jdsfxx2QBYiQ53"
}
},
"-KfpWz7ZWBAa_8pLM7tI" : {
"HnhLrryXUINmlltK3jdsfxx2QBYi3455" : {
"notify" : true,
"time" : 1490300581677,
"userFirebaseId" : "HnhLrryXUINmlltK3jdsfxx2QBYi3455"
}
}
Can I use the Firebase Transaction for this?
Like one device pick up a NOTIFICATIONS and then gets maybe 10 TARGET_VISITORS (there can be 1000+), and in a Firebase transaction locking down TARGET_VISITORS to perform the chat message heads up delivery on his userFirebaseId or OneSignal PlayerId.?
After that the TARGET_VISITORS can save the NOTIFICATIONS id and by doing that prevent getting duplicate messages.
Maybe creating a visitor lock rule like:
"TARGET_VISITORS_LOCK": {
".read": "auth != null",
"$FirebaseId": {
// This need to be a final entity.
// we can write as long as old data or new data does not exist.
// In other words, we can write if we're deleting or creating data, but not updating data.
".write": "!data.exists() || !newData.exists() && auth != null"
}
},
And then run an Data Fan Out updateChildren on the TARGET_VISITORS_LOCK, if it fails it means some other device is running the updateChildren before me and sending the notification to the single device. What will happen her if device having an offline period?
Many devices in the pool of workers can have the same NOTIFICATIONS to try to send and they will fight over TARGET_VISITORS, so to speak
Then comes the problem to know when to remove a NOTIFICATIONS entry, remove it when all TARGET_VISITORS have been notified :) Yea this is quite fun :)
It´s all theoretical at this point and i´m reading a loot so hoping for some input about this?
I'm using Pushwoosh to send notification both under Android and iOS.
Now it's possible to send Custom data under the Additional data tab of the Send push web page.
So I put some like this
{"event" : "1234"}
on the Custom data field but I can't get this kind of data on the app.
This is what I get under Android
{
"title":"test 4",
"collapse_key":"do_not_collapse",
"from":"320152062216",
"onStart":true,
"foreground":false,
"p":"f"
}
This is what I get under iOS
{
aps = {
alert = "test 4";
sound = default;
};
p = f;
}
Is there anyone who has managed to make it work?
Thanks.
I think Stack might be not the best place for this, but custom data is available only on Premium accounts.