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

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.

Related

Multiple contexts , create only if not exists

I have a view controller that is performing an afnetworking request , and upon the response , I am adding that response to my main MOC , and saving it.
My app is a realtime app , and so , performing certain kinds of requests will send messages from server to client via a long lived web socket. What happens is ,when a client sends a single message , he will receive the same message via socket (and I am going to add apns functionality later on, so he will receive the same functionality via apns as well)
I want the web socket to use a background context, so my UI is taxed less.
Right now I am performing a fetch to see if data already exists. If it does not, then I am adding to the context. This check is being done on the socket side as well as the api side.
My concern is , since they are both going to be checked at such close time intervals to each other, is it possible for them to both say that data doesn't exist, and then both will add to the db, causing an unwanted duplicate?
This is my code for clarification:
if ([Chat fetchById:[jsonBody valueForKey:#"id"] withContext:self.managedObjectContext]==nil) {
NSLog(#"GOT NIL FROM SOCKET");
Chat *chat = [Chat initWithContext:self.managedObjectContext];
chat.id = [jsonBody valueForKey:#"id"];
chat.body = [jsonBody valueForKey:#"body"];
chat.user = [User fetchByID:[jsonBody valueForKey:#"user_id"] inContext:self.managedObjectContext];
NSString *date = [jsonBody valueForKey:#"created_at"];
chat.created_at = [TimeFormatter NSDateFromServerString:date];
chat.group = [Group fetchByID:[jsonBody valueForKey:#"grp_id"] inContext:self.managedObjectContext];
[self.managedObjectContext save:nil];
}

Is there anyway to save push notifications?

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".

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 manage Online / Offline / Away status in background PUBNUB + IOS?

We want to implement Online/Offline using Pubnub framework in iOS but app doesn't work in background more than 10 minutes. We have tried to implement this by enable location feature and its working fine. But client does not want to enable location service for this purpose. So how we will manage to make run enable in background infinite ? (QUE 1)
And if we want to put Online/Offline/Away status in our code
Where we should show,
Online: When user open the app
Offline: When user close the app from background OR delete the app
Away: When user tap on home button and app is in background.
How we will implement this (Specially AWAY & Offline state)?(QUE 2)
Is there any other way to manage Online/Offline/Away ? (Without Pubnub ) (QUE 3)
If Yes, please describe the way.
How we will manage Online/Offline/Away using web service? When we call that web services? (QUE 4)
We are using almost 3-4 year old base code. So should we add any other parameter in plist to enable app in background for more time ? (QUE 5)
Please guide us.
With PubNub Presence, you have the best way to provide this feature in your app but due to the way iOS handles app going into background, you may or may not have opportunity to update this status (depends on how app is configured to run).
But very simply, by enabling Presence for your PubNub keys, when a client subscribes to a channel, a join event is sent to all other subscribers that are listening to presence on that channel.
When the app goes into background, if you have opportunity to do so, you can call unsubscribe on all the channels the client is subscribed to and a leave event will be sent to all the subscribers of that/those channels listening to presence events.
And if the app were to get killed or go to background where you do not have a chance to call unsubscribe, when the app is offline/disconnected for longer than the configured heartbeat period, then a timeout (equivalent to a leave event) will be sent to all subscribers listening to presence events.
The heartbeat defaults to 5 minutes but you can configure this to a lower setting like 60 seconds (or shorter for use cases that require this but never lower than 15 seconds).
If you would like your server to listen to Presence events, then you will want to use our Presence Webhooks (docs coming soon). Please see this StackOverflow thread about how to implement PubNub Presence Webhooks and how to get your PubNub keys configured to use them.
There are two scenarios:
User puts App in the background mode
User quits the App.
What you need to do is to get notified when these events occur:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillResignActive)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillTerminate)
name:UIApplicationWillTerminateNotification
object:nil];
Now, in that respective methods, set state using PubNub's API
-(void)appWillResignActive
{
// Sample dictionary
NSDictionary *dicState = #{ #"userName" : senderName, // Optional
#"status" : #"Away", // Or whatever
#"isTyping" : #FALSE // Optional
};
[AppDel.client setState: dicState
forUUID: senderId // current user's UUID
onChannel: KPubNubChannelName // channel name
withCompletion: ^(PNClientStateUpdateStatus *status)
{
NSLog(#"%#", status);
}];
}
Once state is updated on PubNub, all the subscribers of that channel will be notified i.e. follwing method will be called:
- (void)client:(PubNub *)client didReceivePresenceEvent:(PNPresenceEventResult *)event
{
if (![event.data.channel isEqualToString:event.data.subscription])
{
// Presence event has been received on channel group stored in event.data.subscription.
}
else
{
// Presence event has been received on channel stored in event.data.channel.
}
if (![event.data.presenceEvent isEqualToString:#"state-change"]) {
NSLog(#"%# \"%#'ed\"\nat: %# on %# (Occupancy: %#)", event.data.presence.uuid,
event.data.presenceEvent, event.data.presence.timetoken, event.data.channel,
event.data.presence.occupancy);
}
else {
NSLog(#"%# changed state at: %# on %# to: %#", event.data.presence.uuid,
event.data.presence.timetoken, event.data.channel, event.data.presence.state);
}
}
When it gets called, you will have to update your datasource accordingly which will reflect the state update.

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