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
Related
i have succesfully integrating react-native-fcm and
i am getting notification when i am sending from firebase console (in foreground,background,and killed state of app)
but when i am sending it from our server with custom data i cannot recieved when app is in (killed,background) state
i have also tried content-availble:true in data object
below is the notification data which i am sending
{
aps = {
"content-available" = 1;
};
body = "Get a free T-Shirt #WROGN on every purchase via Shopholix. T&C apply.";
"gcm.message_id" = "0:1475746605785619%9a4a567a9a4a567a";
"gcm.notification.data" = "{\"image\":\"http:\\/\\/res.cloudinary.com\\/saurabh\\/image\\/upload\\/v1469791885\\/media\\/yljgxgmfg1qbulxzwakm.png\",\"user_type\":\"all\",\"screen\":\"store\",\"id\":\"56d7e33ce69f7c8f06550002\",\"title\":\"Shopholix\",\"message\":\"Get a free T-Shirt #WROGN on every purchase via Shopholix. T&C apply.\",\"body\":\"Get a free T-Shirt #WROGN on every purchase via Shopholix. T&C apply.\"}";
"gcm.notification.priority" = high;
id = 56d7e33ce69f7c8f06550002;
image = "http://res.cloudinary.com/saurabh/image/upload/v1469791885/media/yljgxgmfg1qbulxzwakm.png";
message = "Get a free T-Shirt #WROGN on every purchase via Shopholix. T&C apply.";
screen = store;
title = Shopholix;
"user_type" = all;
}
Any help would be appreciated
Thanks,
Your content_available is set to 1. I'm pretty sure when using FCM, you should use true or false. Correct me if I'm reading your payload structure in a wrong way, but are you specifying the content_available separate from the GCM payload?
Also, the priority parameter should be outside the notification payload parameter.
See here for more details.
Were you able to resolve your issue?
Looking at the JSON, if it is exactly how you're sending it, then it is not well formed. All of the keys need to be strings surrounded by quotes. And each key-value pair needs to be comma-separated, not semi-colon.
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".
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.
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.
I'm having some trouble with Quickblox chat. Whenever two users are both logged in and both joined in the same chat room, messages that are sent between the two users are not marked as read. When I back out of the room to the dialogs list and the dialogs are refreshed, it says that there are unread messages even though I was in the room and I was receiving the messages live.
Is there a certain call that I must make to let it be known that the received messages should be marked as read? I am developing in iOS.
Thanks.
User has to read message to mark it as read
NSString *dialogID = #"53d10eede4b02f496c21549f";
NSArray *mesagesIDs = #[#"53aabe15e4b077ddd43e7fd3", #"53aabe15e4b077ddd43e7fd7"];
[QBChat markMessagesAsRead:mesagesIDs dialogID:dialogID delegate:self];
In iOS you can use:
QBRequest.markMessagesAsRead(Set<String>?, dialogID: String, successBlock:
{
(QBResponse) in code
})
{
(QBResponse) in code
}