Is there anyway to save push notifications? - ios

When user a sends a push notification to user b, user b will receive the notification, but once they click on it the payload from that notification is gone. Instead when user b opens the notification, the payload in the notification will get saved to parse, so he can view all the notifications that were sent to him. It's like a notification history. Below is my code to send notifications. I need help on how to save the payload within those notifications, so users can look at notification history.
func pushNotifications(){
let userQuery: PFQuery = PFUser.query()!
userQuery.whereKey("objectId", containedIn: Array(setOfSelectedFriends))
let pushQuery: PFQuery = PFInstallation.query()!
pushQuery.whereKey("user", matchesQuery: userQuery)
let push = PFPush()
push.setQuery(pushQuery)
push.setMessage("\(username!) wants you to meet them at \(location!)")
push.sendPushInBackgroundWithBlock {
success, error in
if success {
print("The push succeeded.")
} else {
print("The push failed.")
}
}
}

You probably should do it the other way around, make a table where you save new "MeetingInvites" and whenever a new entry gets added send a push notification to the corresponding user.
Make the push notification a side effect of the actual new entry. Not make the entry a side effect of the push notification.
That would also save you the trouble of having to deal with notifications that get lost - maybe the receiving user opens the app, then something crashes and your push notification and all the connected data would be lost.
A little bit more detail: Create a column for the location, one column for the "requesting" user and one for the "partner". In your code, set the currentUser as the requesting one, and the partner as the ... well ... partner. Then either on your client device or on the server create a push message. In both cases send the push message to the "partner".

Related

badge should be set before opening the app in IOS

When notification received on IOS device at that time the badge should be changed and Badge should be set before opening the app.
I check this onNotificationOpen() method. But when I tap on notification then it calls.
I use cordova-plugin-firebase.
Here is the link https://github.com/arnesson/cordova-plugin-firebase
But is there a method that calls when the notification received on IOS device?
$ionicPlatform.ready(function() {
if (typeof FirebasePlugin != 'undefined') {
window.FirebasePlugin.subscribe("notficationsubscribe");
// Below method calls when i tap on notifcation and sets the badge number
window.FirebasePlugin.onNotificationOpen(function(data) {
window.FirebasePlugin.setBadgeNumber(4);
}
}
}
Above FirebasePlugin.onNotificationOpen() method calls when I tap on notification and sets the badge number, but I want to set the badge when notification received.
Anyone have ideas? How can I achieve it?
Actually i set a logic for it.
1) I stored a badgeCounter value to database.
2) when i wants to send the notification at that time i retrieve it from database
var badge = badgeCounter // it is an integer value
var notification = {
'title': 'Stock available',
'body': 'Click here to more details...',
'sound': 'default',
'badge': badge
};
3) After tap or click on notification, i cleared the badge using below.
window.FirebasePlugin.setBadgeNumber(0);
4) And also in database i update the value to '0' (zero).
Thus, i solve it and it perfectly works for me.
You don't set this with code, it will set itself based on what your notification contains. You'll have to include "badge":1 (or whatever number) in the notification payload when you send it from your server (Firebase). I'm not sure how it works with firebase, but take a look at the documentation for remote notifications. Notice the "Badge"-key.

CloudKit Not Sending Update Notifications

I am trying to develop a simple messaging app to learn the basics of CloudKit.
I've got it almost figured out, except I am not able to receive notifications for record update events.
To test the app, I am running it simultaneously on the device and on a simulator.
Both instances are logged into the same iCloud account (haven't gotten around to create a dedicated account for testing...); however the app distinguishes the local user from the remote one using UUIds, so that is not a problem.
When one instance of the app wants to send a message, it creates a record and saves it to CloudKit.
I am aware that APNs is not supported on the Simulator, but if I send a message from the Simulator I can get notified on the device.
This works.
Next, I want to mark the messages as "read": That is, flag them when they are first displayed on a device that is not the one that authored them.
I do this by fetching the corresponding record, modifying it, and saving it. So, the message I sent from the device is displayed on the simulator, and flagged there as 'read'. I sync that change with cloudKit and expect the device to receive a notification:
publicDatabase.perform(query, inZoneWith: nil, completionHandler: {(records, error) in
guard let records = records, records.count > 0 else {
return print("Error - Message: \(message.text) by \(message.userName) NOT found on the cloud!")
}
let record = records[0]
// HERE THE RECORD IS MODIFIED LOCALLY:
record["readTimestamp"] = (message.readTimestamp! as NSDate)
// Now, save it:
self.publicDatabase.save(record, completionHandler: {record, error in
guard error == nil else {
return print("Error - Message: \(message.text) by \(message.userName) could NOT be saved as read!")
}
print("Message: \(message.text) by \(message.userName) SAVED as read at \(message.readTimestamp!)")
})
})
However, on the other end, the 'Update' notification is never received.
Is it because both instances are logged into iCloud as the same user? I find this hard to believe, since the "Create" notifications are delivered without problems.
Subscriptions for both notifications ("Message Create" and "Message Update") are registered successfully and appear listed on the CloudKit Dashboard (triggers INSERT and UPDATE).
Update: After a long time thinking what can possibly be different between my "create" subscription and my "update" subscription that could cause only one of them to fire a notification, I realized that only the "create" subscription had a notification body:
let subscription = CKQuerySubscription(recordType: "Message",
predicate: NSPredicate(value: true),
subscriptionID: Bundle.main.bundleIdentifier! + ".subscription.message.create",
options: .firesOnRecordCreation
)
let notificationInfo = CKNotificationInfo()
// THIS LINE MAKES ALL THE DIFFERENCE:
notificationInfo.alertBody = "You've Got Mail!"
subscription.notificationInfo = notificationInfo
publicDatabase.save(subscription, completionHandler: {savedSubscription, error in
...whereas the "update" subscription did not:
let notificationInfo = CKNotificationInfo()
subscription.notificationInfo = notificationInfo
Once I added an alert body, the "update" notifications started arriving.
However, this is just a workaround: I need silent notifications for my read updates. It doesn't make sense to display a banner just to alert the user that his message has been read on the other end.
Also, the CloudKit programming Guide does not mention this limitation.
Is there a way to subscribe with silent (i.e., empty) push notifications?
Update 2: Actually, I found this bit on the API Reference for CKNotificationInfo:
Note
If you don’t set any of the alertBody, soundName, or shouldBadge
properties, the push notification is sent at a lower priority that
doesn’t cause the system to alert the user.
(emphasis mine)
I still fail to see how this "lower priority that doesn’t cause the system to alert the user" is equivalent to "application(:didReceiveRemoteNotification:fetchCompletionHandler:) not being called at all".
The solution appears to be to use an info object with shouldSendContentAvailable = true, like this:
let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
subscription.notificationInfo = info
That has solved it for me. It causes didReceiveRemoteNotification: to fire, without any user visible notification appearing. So it's a silent notification, as desired, and it's actually arriving, as desired.
If I leave subscription.notificationInfo nil the app is never notified of changes. But with an [effectively silent] info object I get the desired results.

How to block specific user push notification in parse iOS app?

I am working on a iOS chatting app by use parse as backend service. If user blocks another user, how to prevent the push notifications? Is that possible to filter this push notification in parse side?
Really appreciate in advance.
There are several different ways to block a push notification from being sent to a user that blocked the sender. It really depends on how you handle the blocking of the user.
You could, for instance, add a blockedUsernames array to each user. If you did this, you could block the push notification from being sent in the first place, by cross checking this blocked users array against the users it is being sent to.
// CHECK FOR BLOCKED USERS
PFUser *currentUser = [PFUser currentUser]; // user sending push
PFUser *sendPushToUser = //user receiving the push
// Get array of blocked users
NSMutableArray *blockedUsersArray = sendPushToUser[#"blockedUsers"];
BOOL blocked = false;
for (NSString *username in blockedUsersArray) {
if ([username isEqualToString:currentUser.username]) {
blocked = true;
}
}
// If the user isn't blocked, send push
if (blocked == false) {
[PFCloud callFunctionInBackground:#"sendPushToUser"
// more cloud code to handle the notification...
You could also block the push notification in the Parse Cloud Code, with some JS.

Parse cloud push notifications are pushing to all users instead of targeted user

I'm having trouble targeting the push notifications to a single user. Right now my test device is receiving a push notification no matter which user is logged into the device. Even when I send a push to _User that is currently logged out and the device is logged in with a completely different _User it receives the push notification.
I have set up cloud code with parse.com to enable push notifications to be sent to users. I have a "user" pointer in the installation class that points to the cooresponding _User that is to receive the push notification.
Example: _User "Sam" is logged in to the mobile device. I send a push from the iOS simulator in Xcode to _User "steve". The mobile device receives the push even though "Sam" is logged in. It receives the push even if NO user is logged in.
When I check the Push control on parse, it seems like the cloud cloud is correctly querying the "user" pointer in the installation that matches the objectId for the _User class, as seen here:
user advanced operator ($inQuery {"className"=>"_User", "objectId"=>"LJQXaJDzkU"})
SENDING TIME
August 5th, 2015 at 3:01 PM
EXPIRATION
None
FULL TARGET
{
"user": {
"$inQuery": {
"className": "_User",
"objectId": "LJQXaJDzkU"
}
}
}
FULL DATA
This is the cloud code that queries the user and sends the push from the parse cloud. The recipientUserId receives a string of the objectId for the _User whom is receiving the push.
Parse.Cloud.define("sendPush", function(request, response) {
var senderUser = request.user
var recipientUserId = request.params.recipientId;
var senderUserId = request.params.senderId;
var message = senderUserId + " sent a message"
var recipientUser = new Parse.User();
recipientUser.id = recipientUserId;
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesQuery('user', recipientUser);
Parse.Push.send ({
where: pushQuery,
data: {
aps: {
alert: message,
badge: "Increment",
sound: "cow-moo1.wav"
}
}
}, {
success: function() {
response.success("Success!");
},
error: function(error) {
response.error(error);
}
});
});
The pushes send no problem, and I can open them on the device but I'm really lost as to why the pushes are being sent to the device even when the queried user isn't even logged in to the device. Any ideas as to whats going on would be greatly appreciated. Thanks!!!
Edit your code so that when you log out, you're removing the user from the installation.
Edit - This was mentioned in the comments below, so I want to make sure it was mentioned here in case it was the solution that worked. OP used matchesQuery, which requires a query to be passed in, but was passing in a Parse.User object instead. I suggested he used equalTo instead of matchesQuery.

How to combine multiple notifications of the same kind

I have an iOS app that shows the user a set of different news feeds in a PageViewController. Everytime the app starts, it requests the news data from the backend for every single feed. In case it worked fine, a notification via for every single news feed is sent via NSNotificationCenter so the data can be displayed.
In case of an error, a notification for every single feed is sent as well, triggering a popup message that tells the user something went wrong. But if this happens, a popup will be shown for every news feed, up to the amount of added news feeds.
My question is, how can I combine all those error case notifications to a single one and therefore avoid having many useless and annyoing popups?
if (self.isShowingErrorDialog) {
return; // Or possibly cache to show after current one is dismissed.
} else {
[[UIAlertView ...] show];
self.showingErrorDialog = YES;
}
When you send a notification using NSNotificationCentre, you can include user info. This is basically an NSDictionary with additional information.
Why not just include the timestamp of the failed request. You can test this with some fuzziness to see if you've already put up an alert for this batch of requests.
- (void) notificationListener: (NSNotification*) notification {
static NSDate* lastAlerted = nil;
NSDate* sentDate = notification.userInfo[#"RequestDate"];
if ( lastAlerted != nil && [lastAlerted timeIntervalSince:sentDate] > FUZZY_INTERVAL) {
// post alert
// And update last Alerted
lastAlerted = sentDate;
}
}
The method you need is postNotificationWithName:Object:UserInfo:.
Gordon
I don't think you can.
Just to confirm, the notifications you're sending are Apple remote notifications and the alerts are the system alerts popped up by the message centre.
The alerts occur before you get control, as the user has to have the opportunity to ignore them, or else people would use this as a cheat to make apps run in the background and kill user's batteries.
All you can do is send a batch token in your request, and check on the back end.
Good luck

Resources