If user says no to push notification permission in the initial launch of application, will the APN device token be received by the application ?
There is a very important exception you should be aware of. If you enable the Background Mode "Remote Notifications", you will get a token from iOS regardless of the user's response to the permission question. You will be able to send silent push notifications to your app using this token (a push with the content-available key set to 1 in the 'aps' section of the json
silent notification means if your app is in the foreground you will get a hit in didReceiveRemoteNotification and if your app is in the background it will also get a call (in the background) to the same delegate function.
BUT - this will not be visible to the user. so it still gives you a way to communicate with your app, albeit a limited one.
No, you need to have the user permission to get the token
IMPORTANT EDIT: This answer is incorrect. Please look at the answer below. I cannot delete that as it is an accepted answer.
User must give permission for you to get the device token.
If user gives permission, - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken method is executed in AppDelegate and you'll get the device token.
If user refuses to give permission, - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error method is executed and you'll only get corresponding NSError object.
Related
I've had various struggles with push notifications over the course of my app that seem to be fixed by uninstalling. I believe I've narrowed it down to expired deviceTokens.
Reading Apple's Push notification documentation, I found this:
Registration Succeeded But No Notifications Received
. . .
Your app may have sent an incorrect device token to your provider.
Your app should always ask for the device token by registering with
the push service each time it is launched. Don't store a device token
from your app and try to reuse it, because the token can change. Your
provider should then pass that same token on to the push service.
They suggest registering each time the app is launched. They also suggest best practice for push notifications is not to do that, since users don't like getting bombarded with access requests before even getting to see your app. So, just throwing the registration call into the app delegate isn't the best option. However, I am not seeing any more info on when a deviceToken expires or how to see if it has expired.
The closest thing I can find is this documentation on UIApplication's instance method isRegisteredForRemoteNotifications:
Return Value YES if the app is registered for remote notifications and
received its device token or NO if registration has not occurred, has
failed, or has been denied by the user.
My understanding is that this is the method to call to check if a user has enabled push notification services. I understand that permissions for specific notification types could all be turned off and this could still be true if the user allows push notifications. But the wording looks like it requires the app to be registered with the current deviceToken. Does this mean that I could call
[[UIApplication currentApplication] isRegisteredForRemoteNotifications]
inside the appDelegate, and if it's true, register remote notifications to update my deviceToken on my server and make sure my push notifications don't expire? Or, is this function going to run into the same thing that I currently am, where eventually the deviceToken is going to expire and this method will begin to return false instead of true, even though the user had allowed push notification?
tl;dr - Apple says deviceTokens eventually expire for push notifications. They suggest registering every time the app launches. I don't want to bombard new users with that alert. How do I ensure only users who have already accepted push notifications get re-registered?
The alert will only be shown once.
If the user previously Allowed notifications, your code will get the new token without needing any interaction from (or UI notice to) the user.
OK, the best practice for this are as follows, which we follow without failure
Always register for the Push on app launch, or in suitable AppDelegate lifecycle methods, using the following code
[[UIApplication sharedApplication] registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
The delegate for Push if it is successfully registered will get called with deviceToken
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
The delegate above will get called if there is change in deviceToken always. So whenever you get a deviceToken update it in the server.
In the server make sure you hit correct mode if you are running in Sandbox, or Production mode, discard values from Simulators they normally fails and block the service for sometime.
You can always check with your pem file and device token that Push is working or not with this online service.
Hope it helps.
Cheers.
I am using Sinch with ManagedPush to receive notifications for VoIP via PushKit. In my app I have three possible states:
Online
Offline
"Not available for incoming calls, but I can make calls"
The user can change this state at any time during the App session.
Following documentation:
https://www.sinch.com/docs/voice/ios/#unregisterapushdevicetoken
I am using unregisterPushNotificationDeviceToken as well as stopListeningOnActiveConnection
This seems to work to get the person not to receive incoming calls and still having the client active to make calls. Where I am having issues is on setting the user back online. The active connection works, but I can't seem to be able to register again for the notifications, to receive the call when the app is in background.
Questions like Sinch SDK - How to logout user? don't solve how to put the user back online.
I have considered using the SinchService component https://github.com/sinch/SinchService-iOS but I can see from the code that the logout functionality terminates the client. And I am interested in not terminating the client, but stop receiving notifications and then receving them again on the same session.
What I have tried:
Not available for incomming calls button does:
[_client stopListeningOnActiveConnection];
[_client unregisterPushNotificationDeviceToken];
Online button does:
[_client startListeningOnActiveConnection];
[[UIApplication sharedApplication] registerForRemoteNotifications];
The reason I am calling registerForRemoteNotifications is to force the didRegisterForRemoteNotificationsWithDeviceToken delegate method to be called so I can call the Managed Push to register again for notifications. I thought that might do the trick but it didn't.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[self.push application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
Most likely this doesn't work because this goes through PushKit and the way to register is different.
As workaround that works for me is recreating the client when the user switches to online status back:
[_client terminateGracefully];
_client = nil;
[self initSinchClientWithUserId:[BCDataProvider loggedInUser].callerId];
Is there any way I can get back on being registered for VoIP notifications, after a unregisterPushNotificationDeviceToken without having to recreate the client?
Thanks!!
If I am not wrong, basically you need to achieve VOIP, by online / offline etc you need to manage user to allow for call or not.
You can use socket architecture, which keeps broandcast user is online / offline, so on that basis you can manage to allow for call or not.
If you are working with VOIP, then below method has to be in use.
-(void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
{
///tell the Sinch SDK about the push token so we can
///give that to users that want to call this user.
[_client registerPushNotificationData:credentials.token];
}
Below mentioned method will not be in use.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
}
Using push notification, will always provide you new unique device token, so once you unregistered for offline, then again for online you would not be able to register with same device token.
Using push kit( Silent push notification ) you will always get same device token registering after unregistered.
I am working in XMPP Application.
When I terminate and kill My Application than,
1)User is Not Connected In XMPP Server. User is Offline. But I want User is Connected and Online. Like Whats App(Appliction).
2)I can't get Any Messages From XMPP Server Side at that time,
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
This method is not call. So, How Can I get Messages ?
And i also implement Pushnotification but in this way same issue Like,When app is Kill and Terminate than,This method is not call,
- (void)application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
So, Please Guide me In Proper Way and Suggest me How to work as like same Whats App(Application).
Also, We can't set VOIP Flag In .plist file Because this way is not Proper and reject by the apple.
My Goal is Only Notification Work As like Whats App.
1)User is Not Connected In XMPP Server. User is Offline. But I want
User is Connected and Online. Like Whats App(Appliction).
Once you closed or minimized WhatsApp the user gets offline (tested on iPhone4s), and messages received in this state are as push notifications.
2)I can't get Any Messages From XMPP Server Side at that time,
(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
This method get called only when application is active. So you can not get messages here after you killed your application.
- (void)application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
This method will get called in following scenarios
If your app is active and you got any new push notification.
If your app is in background or killed or not started then system will show only notification on the top bar, once user tapped on notification it will open your application and then the method will get called.
And of course you can not use VOIP.
WhatsApp shows custom notification when user is active in WhatsApp.
You need to send push notification for every message of your conversation. In this case
If user is active then show your custom notification in app.
If user is inactive (i.e. killed or minimized app) then system will show Notification in notification center.
When user taps on notification, system will launch application, and you have to check for app launching conditions (from which source app launched) and according to conditions join server/chat (or groups if you are using group chat).
Once you joined server with your name/nickname, you will get recent chats. You can also get history, you need to specify while joining chat server / group.
Make sure you are disconnecting from server and also from group when your app is getting minimized or killed. Use following methods to disconnect and/or related changes
1. - (void)applicationDidEnterBackground:(UIApplication *)application
2. - (void)applicationWillTerminate:(UIApplication *)application
Hope this will help you, I have implemented same to achieve expected results as WhatsApp.
When your app kill, that time XMPP Deactivate all service.So, you can send webservice to server which can tell - you are offline.
Then after sever can send you Push notification all chat content.
First of all, If your application is terminated then you will receive Push Notification data in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
in launchOptions dictionary with key
if (launchOptions)
{
if ([launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey])
{
// Your code
}
}
Second, you can use background fetch for retrieving user's message, While background fetch you can connect your stream and fetch messages from XMPP server.
NOTE: WhatsApp's (iOS) version, fetches the message as soon as you open the app, it is connecting to the stream and then fetches the messages.
However you can implement your own logic to customize your functionality.
Read the following document it will help you.
http://xmpp.org/extensions/xep-0168.html
We ned to add priority when the presence of user is set as below:
-(void)GoOnline{
XMPPPresence *goOnline = [XMPPPresence presence];
NSXMLElement *priority = [NSXMLElement elementWithName:#"priority" stringValue:#"-1"];
[goOnline addChild:priority];
[xmppStream sendElement:goOnline];
}
Now to know more about priority, it's role and how it works, read the document from above link.
Hope it may help you :)
Check this link and read the Remote Notifications (iOS 7 and Greater) section which is combining the Background Modes and Remote notifications to download content before launching the app.
You will get the idea and you can implement in your preferred language obj-c or swift.
I have a live app. in apple store that implements a push notification procedure. As known I communicate with my server to send and save device tokens.
My server is receiving device tokens correctly for some devices(Requests) and also receives null values for some other devices.
How is that could be possible in any case?!
Then you have a bug in your code, the device never generates a null token, or you have failed to implement the following delegate:
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
If this delegate gets called then you could/should implement a retry algorithm that retries to re-register for the APN token a few times.
I have finished this tutorial here
http://mobiforge.com/developing/story/programming-apple-push-notification-services
and now i can send a push notification to my device using my application.
However i cannot figure out how to send push notifications not just to my specific device token but to all devices with my application.
You have to send the message to each device individually, i.e.: in a loop
Apples Push Notification servers only know to direct messages to specific devices.
It is the developer's responsibility to pass the tokens you receive from the
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
method to your server ( through an HTTP post for instance ) and keep track of all the existing tokens.
If/when you want to send a message to all the devices - you simply need to iterate all the existing device tokens.