We are using communication notification to update notification icon, but for us it's not working for xamarin project.
var intent = new INSendMessageIntent(null,INOutgoingMessageType.Text,
"Message content",
null,
"unique-conversation-id-1",
null,
sender,null);
// Use the intent to initialize the interaction.
var interaction = new INInteraction(intent: intent, response: null);
interaction.Direction = INInteractionDirection.Incoming;
interaction.DonateInteraction((error) =>
{
// ...
});
NSError error1 = null;
var content = request.Content;
var updatedContent = content.Update(intent, out error1);
contentHandler(updatedContent);
Related
When I explored different options for my lockdown-development project, I considered using App Store Server Notifications to inform my Firebase data base about subscriptions purchased in the App. Cloud Functions were supposed to receive the notification JSONs from Apple, interpret them, update the data base, and to respond to Apple. Apple and Google provide a lot of information about App Store Server Notifications and Cloud Functions, but linking them together can still be time consuming. Both companies describe well how to set their services up, and you will find an example of my code below. I ended up not using it, and Google migrated Cloud Functions to Node.js 10 in the meantime, but my code might still be useful to somebody:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
// The Express Functions to create an Express application.
const express = require('express');
const app = express();
// Add a generic JSON and URL-encoded parser as top-level middleware.
const bodyParser = require('body-parser');
// Parse application/x-www-form-urlencoded.
app.use(bodyParser.urlencoded({ extended: false }));
// Parse application/json.
app.use(bodyParser.json());
// Empty function for Timeout
function wait(ms) {
var d = new Date();
var d2 = null;
do { d2 = new Date(); }
while(d2-d < ms);
}
// Parse JSON and return relevant notification data.
function parseJSON(request) {
// returnValue[0] = environment
// returnValue[1] = notification_type
// returnValue[2] = original_transaction_id
// returnValue[3] = transaction_id
// returnValue[4] = latest_expired_receipt
// returnValue[5] = purchase_date_ms
// returnValue[6] = cancellation_date_ms
// returnValue[7] = expires_date
// returnValue[8] = grace_period_expires_date_ms
// returnValue[9] = product_id
// Carefully unwrap JSON
if(request) {
try {
// Declare local variables
const obj = JSON.parse(request.rawBody);
var original_transaction_id = 'Empty';
var transaction_id = 'Empty';
var purchase_date_ms = 'Empty';
var expires_date = 'Empty';
var grace_period_expires_date_ms = 'Empty';
var product_id = 'Empty';
// Unwrap variables in responseBody
var environment = (obj.environment) ? obj.environment : 'Empty';
var notification_type = (obj.notification_type) ? obj.notification_type : 'Empty';
var latest_expired_receipt = (obj.latest_expired_receipt) ? obj.latest_expired_receipt : 'Empty';
var cancellation_date_ms = (obj.cancellation_date_ms) ? obj.cancellation_date_ms : 'Empty';
// Make sure latest_receipt_info is there before unwrapping
if (obj.latest_receipt_info) {
original_transaction_id = (obj.latest_receipt_info.original_transaction_id) ? obj.latest_receipt_info.original_transaction_id : 'Empty';
transaction_id = (obj.latest_receipt_info.transaction_id) ? obj.latest_receipt_info.transaction_id : 'Empty';
purchase_date_ms = (obj.latest_receipt_info.purchase_date_ms) ? obj.latest_receipt_info.purchase_date_ms : 'Empty';
expires_date = (obj.latest_receipt_info.expires_date) ? obj.latest_receipt_info.expires_date : 'Empty';
product_id = (obj.latest_receipt_info.product_id) ? obj.latest_receipt_info.product_id : 'Empty';
}
// Make sure pending_renewal_info is there before unwrapping
if (obj.pending_renewal_info) {
grace = (obj.pending_renewal_info.grace_period_expires_date_ms) ? obj.pending_renewal_info.grace_period_expires_date_ms : 'Empty';
}
return returnValue = [environment, notification_type, original_transaction_id, transaction_id, latest_expired_receipt, purchase_date_ms, cancellation_date_ms, expires_date, grace_period_expires_date_ms, product_id];
} catch (error) {
throw (error);
}
}
return returnValue = ['Empty', 'Empty', 'Empty', 'Empty', 'Empty', 'Empty', 'Empty', 'Empty', 'Empty', 'Empty'];
}
// Function passes request to app
exports.iapStatusUpdate = functions.https.onRequest(async (request, response) => {
// Constants
const userID = [];
const currentDate = admin.firestore.FieldValue.serverTimestamp();
const collectionUsers = 'myData';
const collectionNotifications = 'myNotifications';
// Parse JSON and get relevant notification data.
try {
var parsedJSON = parseJSON(request);
} catch (error) {
// The server cannot or will not process the request due to an apparent client error.
response.status(400).send(error);
}
// Save relevant notification data.
try {
const writeResult = await admin.firestore().collection(collectionNotifications).add( {"environment": parsedJSON[0],
"notification_type": parsedJSON[1],
"original_transaction_id": parsedJSON[2],
"transaction_id": parsedJSON[3],
"latest_expired_receipt": parsedJSON[4],
"purchase_date_ms": parsedJSON[5],
"cancellation_date_ms": parsedJSON[6],
"expires_date": parsedJSON[7],
"grace_period_expires_date_ms": parsedJSON[8],
"product_id": parsedJSON[9],
"date": currentDate});
} catch (error) {
// A generic error message (Write failed)
response.status(500).send(error);
}
// Query document from database
try {
// In the case of an initial buy, pause execution for 3 seconds to allow Firebase to update record first
if (parsedJSON[1].includes("INITIAL_BUY")) {
wait(3000);
}
// Query document from database and write document id in userID array
const snapshot = await admin.firestore().collection(collectionUsers).where("original_transaction_id", '==', parsedJSON[2]).get();
snapshot.docs.map(doc => userID.push(doc.id));
} catch (error) {
// This failure does not necessarily mean that a real error occurred
// INITIAL_BUY: The App Store notification could have arrived before Firebase saved the original_transaction_id
// In all other cases: The original_transaction_id should be known and a user with this id should exist
if (parsedJSON[1].includes("INITIAL_BUY")) {
response.status(200).send('OK');
} else {
response.status(404).send(error);
}
}
// Update database
try {
// If the notification type is cancel, downgrade user from premium to free
if (parsedJSON[1].includes("CANCEL")) {
const writeEvent = await admin.firestore().collection(collectionUsers).doc(userID[0]).set( {"canceled": true,
"cancellation_date_ms": parsedJSON[6],
"premium": false}, { merge: true });
} else if (parsedJSON[1].includes("INITIAL_BUY")) {
const writeEvent = await admin.firestore().collection(collectionUsers).doc(userID[0]).set( {"confirmedPurchase": true,
"confirmedPurchaseOn": parsedJSON[5],
"purchase_date_ms": parsedJSON[5],
"expires_date": parsedJSON[7],
"premium": true}, { merge: true });
} else if (parsedJSON[1].includes("INTERACTIVE_RENEWAL") || parsedJSON[1].includes("DID_RECOVER") ) {
const writeEvent = await admin.firestore().collection(collectionUsers).doc(userID[0]).set( {"renewedPurchaseOn": parsedJSON[5],
"billingRetryPeriod": true,
"expires_date": parsedJSON[7],
"premium": true}, { merge: true });
} else if (parsedJSON[1].includes("DID_FAIL_TO_RENEW")) {
const writeEvent = await admin.firestore().collection(collectionUsers).doc(userID[0]).set( {"billingRetryPeriod": true,
"grace_period_expires_date_ms": returnValue[8],
"premium": true}, { merge: true });
}
} catch (error) {
// A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
response.status(500).send(error);
}
// Send final response
response.status(200).send('OK');
});
Improvements and suggestions are most welcome.
I cannot get a new record entry into my firestore document db to generate an alert to users.
IOS app fetches and updates firestore data with no issues
If I manually send a message from firebase my app gets the message no issues
I can deploy my cloud function to firebase with no errors
What am I doing wrong? Thanks for any help.
let functions = require('firebase-functions')
let admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
let db = admin.firestore()
exports.announceAlert = functions.database
.ref('/alerts/{documentId}')
.onCreate((snapshot, context) => {
let alert = snapshot.val()
sendNotification(alert)
})
function sendNotification(alert) {
let title = alert.Incident_Number
let summary = alert.Flash_Summary
let status = alert.Incident_Status
let payload = {
notification: {
title: 'Critical Incident: ' + title,
body: 'Summary: ' + summary,
sound: 'default'
}
}
console.log(payload)
let topic = "Alerts"
admin.messaging().sendToTopic(topic, payload)
}
This is what I did and it worked. Please keep in mind that the user of your iOS app has to subscribe to the topic and you do that through the app. The code below is just a function telling firebase to send a notification to subscribed users when a new document is created in a certain repository.
let functions = require('firebase-functions')
let admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
let db = admin.firestore()
exports.announceMessage = functions.firestore
.document('/myData/{documentId}')
.onCreate((snapshot, context) => {
let message = snapshot.data()
sendNotification(message)
})
function sendNotification(message) {
let title = message.column1
let notification = message.column2
let payload = {
notification: {
title: 'Some title: ' + title,
body: 'Some header: ' + notification
},
}
console.log(payload)
let topic = "yourTopic"
return admin.messaging().sendToTopic(topic, payload)
}
I have an app with a like functionality. Each time user A likes content X of user B:
It creates a notification request in my Firebase Database
Firebase functions observes the path on write & creates a push notification for user B
But when user A likes -> unlikes -> likes content X, user B gets another push notification.
How is it possible to decline further notification requests by user A for content X?
This is the Firebase Functions code:
exports.sendLikeNotification = likeRef.onWrite(event => {
if (event.data.previous.exists()) {
return;
}
var notificationId = event.params.likeNotificationId;
var notificationRequest = event.data.val();
var receiverId = notificationRequest.receiverId;
var message = notificationRequest.message
var data = notificationRequest.data
var topic = '/topics/user_' + receiverId;
var payload = {
notification: {
body: message,
sound: 'default'
},
data: { data }
};
var options = {
priority: "high",
contentAvailable: true
};
// Send a message to devices subscribed to the provided topic.
admin.messaging().sendToTopic(topic, payload, options)
.then(function(response) {
console.log("Successfully sent message:", response);
return event.data.adminRef.remove();
})
.catch(function(error) {
console.log("Error sending message:", error);
});
});
Thank you!
I know this question have been ask a lot of time in android but not ios. So I already test out push notification with FCM it work fine. Mine problem is wether it's a way to create custom notification rather than letting the system to handle the notification with the notification payload?
-Users can send data messages with FCM.What you have to send is,
Sample PostMan Json data:
{ "data": {
"any key": "any value",
"any key 2": "any value 2"
},
"to" : "token received to mobile from FCM"
}
Payload inside "data" can change according to the requirement.
Mobile end:
application(_:didReceiveRemoteNotification:) override method will get fire.So it is unto developer to extract data from the userInfo property in iOS and use it.
For ios using c# working code:-
public bool NotificationToiosDevice()
{
bool str;
try
{
//Create the web request with fire base API
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
//serverKey - Key from Firebase cloud messaging server
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AAAALNl-P7o:APA91bE38khU73UTdIj7L6LvVS3uI6f47REmxl.................................."));
//Sender Id - From firebase project setting
tRequest.Headers.Add(string.Format("Sender: id={0}", "12345"));
tRequest.ContentType = "application/json";
var payload = new
{
to = "dDDbFltwE5o:APA91bFmZZ-c1pNp................",
priority = "high",
content_available = true,
notification = new
{
title = "Title Of Notification",
},
data = new
{
body = new { Parameter1 = "FirstParameterValue", Parameter2 = "SecondParameterValue" },
},
};
string jsonNotificationFormat = Newtonsoft.Json.JsonConvert.SerializeObject(payload);
Byte[] byteArray = Encoding.UTF8.GetBytes(jsonNotificationFormat);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
// str = sResponseFromServer;
}
}
}
}
str = true;
}
catch (Exception ex)
{
str = false;
}
return str;
}
I tried to use PutExtra & GetIntExtra, But the notification id is always overwritten by the last notification, All the notification value is the same. Please tell me how to solve it,
Thanks in advance!
Intent actionIntent = new Intent(this, typeof(ConfirmActivity));
actionIntent.PutExtra("NOTIFY_ID", 1);
PendingIntent actionPendingIntent = PendingIntent.GetActivity(this, 0, actionIntent, PendingIntentFlags.UpdateCurrent);
NotificationCompat.Action action = new NotificationCompat.Action.Builder(Resource.Drawable.ic_done_white_64dp_1x,
this.Resources.GetString(Resource.String.confirm), actionPendingIntent)
.Build();
var notification = new NotificationCompat.Builder(this)
.SetContentTitle("1111")
.SetContentText("1111111111111111111111")
.SetSmallIcon(Resource.Drawable.Icon).Extend(new NotificationCompat.WearableExtender().AddAction(action)).Build();
var manager = NotificationManagerCompat.From(this);
manager.Notify(1, notification);
Intent actionIntent2 = new Intent(this, typeof(ConfirmActivity));
actionIntent2.PutExtra("NOTIFY_ID", 2);
PendingIntent actionPendingIntent2 = PendingIntent.GetActivity(this, 0, actionIntent2, PendingIntentFlags.UpdateCurrent);
NotificationCompat.Action action2 = new NotificationCompat.Action.Builder(Resource.Drawable.ic_done_white_64dp_1x,
this.Resources.GetString(Resource.String.confirm), actionPendingIntent2)
.Build();
var notification2 = new NotificationCompat.Builder(this)
.SetContentTitle("2222")
.SetContentText("22222222222222222222")
.SetSmallIcon(Resource.Drawable.Icon).Extend(new NotificationCompat.WearableExtender().AddAction(action2)).Build();
manager.Notify(2, notification2);
=================================
[Activity(Label = "ConfirmActivity")]
public class ConfirmActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Confirm);
Intent intent = this.Intent;
int NOTIFY_ID = intent.GetIntExtra("NOTIFY_ID", 0); //always 2
}
}
You may want to check on this thread. It suggested to pass a Bundle along with PendingIntent to the next Activity.
Bundle bundle = new Bundle();
bundle.putString("Any String");
NotificationManager notifManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE);
int uniqueInteger = //create a unique Integer
int icon = R.drawable.ic_launcher;
NotificationCompat2.Builder mNotification = new NotificationCompat2.Builder(this).setSmallIcon(icon)
.setContentTitle(contentTitle).setContentIntent(getPendingIntent(bundle, uniqueInteger));
mNotification.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
mNotification.setAutoCancel(true);
notifManager.notify(uniqueInteger, mNotification.build());
Here are some related SO posts which might help:
How to check which notification id is clicked?
Getting data from clicked notification in android
Get the PendingIntent event when notification is clicked