I'm playing with Sinch and have some problems with Push notifications.
Firstly I can use Sinch to send and receive messages (two devices
with two different Sinch IDs). So that means the Sinch Client is
correctly configured.
Secondly I can confirm the push notification are correctly set on
both of the devices, because I can send push notifications to them on
Parse.com. They all have valid push notification tokens.
Then in my app, I found that the Sinch delegate method: shouldSendPushNotification is not called when the receiver side is not "online".
I did a search on SO and found there's a similar question (Sinch, message shouldSendPushNotification not being called) which suggested to check the messageSent call back.
Therefore I tried the following in the receiver side:
put the app into background by pressing home
force quit the app (double click home, remove the app from background)
enable flight mode
After that when a message sent, I can see:
- (void)messageSent:(id<SINMessage>)message recipientId:(NSString *)recipientId
is being invoked in the sender's side and the recipientId is the same as the destination device's. But the shouldSendPushNotification method is never being called as stated in Sinch's documentation.
Since this shouldSendPushNotification method is not invoked, there will not be any push notifications being sent out to the destination device.
I've been working on this problem for several days, and very keen to know the solution, any help is appreciated.
Test environment
two devices in iOS 8 beta 4 and one in iOS 7.1.2
build using XCode 6 beta 4
Code:
Setting up the Sinch messaging service in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
// setup Parse
[Parse setApplicationId:#"xxxxx"
clientKey:#"xxxxx"];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
// use registerUserNotificationSettings
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert) categories: UIUserNotificationActionContextDefault]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
// use registerForRemoteNotifications
// Let the device know we want to receive push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
#else
// use registerForRemoteNotifications
// Let the device know we want to receive push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
#endif
// app response from the notifications while in background
NSDictionary* remotePush = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remotePush) {
// Extract the Sinch-specific payload from the Apple Remote Push Notification
NSString* payload = [remotePush objectForKey:#"SIN"];
// Get previously initiated Sinch client
id<SINNotificationResult> result = [_client relayRemotePushNotificationPayload:payload];
if (result.isMessage) {
// Present alert notifying
NSString *messageId = [[result messageResult] messageId];
NSLog(#"Received messageid: %#", messageId);
} else if (!result.isValid) {
// Handle error
}
NSLog(#"Received Payload: %#", payload);
}
return YES;
}
- (void)initSinchClientWithUserId:(NSString *)userId {
if (!_client) {
_client = [Sinch clientWithApplicationKey:#"xxxx"
applicationSecret:#"xxxx"
environmentHost:#"sandbox.sinch.com"
userId:userId];
_client.delegate = self;
[_client setSupportMessaging:YES];
[_client setSupportPushNotifications:YES];
[_client setSupportActiveConnectionInBackground:NO];
[_client start];
[_client startListeningOnActiveConnection];
}
}
And this line is called as expected when the app starts
- (void)clientDidStart:(id<SINClient>)client {
NSLog(#"Sinch client started successfully (version: %#)", [Sinch version]);
}
Inside the app's MessageSendingViewController
- (id<SINClient>)client {
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] client];
}
-(void)viewDidLoad {
...
[self.client messageClient].delegate = self;
...
}
Are you registering "push data" (e.g. your APN token) via the method -[SINClient registerPushNotificationData:]?
Try something like:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[_client registerPushNotificationData:deviceToken];
}
(There is also more details here on http://www.sinch.com/docs/ios/user-guide/#pushnotifications)
Problem solved with some help from the Sinch.
First make sure that client is not nil (0x0) when the delegate method registerPushNotificationData:deviceToken is being called.
In my case, I need to manually register notification settings again after starting the Sinch client.
Once the client is started and notification settings are registered, the shouldSendPushNotification method should be called without any problems.
Related
Currently one of my php developer provided me push notification API for iOS devices
The problem is : If i run that api with respective parameter in any Browser(Chrome/Safari/Firefox and etc..) i am getting notification on foreground of iOS device. But not in iOS app(Xcode) itself
In my app i used code like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for Push Notitications, if running on iOS 8
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}
#pragma mark
#pragma mark -- Push Notification Delegate Methods
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings: (UIUserNotificationSettings *)notificationSettings{
//register to receive notifications
[application registerForRemoteNotifications];
}
-(void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
// Prepare the Device Token for Registration (remove spaces and < >)
devToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"My token is: %#", devToken);
// My token is: cd2887c4093569b3eed142320f21a81e521e486cf5c40467390901d3a191398b
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:deviceToken forKey:#"deviceToken"];
}
-(void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{
NSLog(#"Failed to get token, error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(#"%s..userInfo=%#",__FUNCTION__,userInfo);
}
I am getting response:(in didReceiveRemoteNotification)
{
aps = {
alert = "You're login successfully";
sound = default;
};
}
This message is not showing on Status bar(top of the screen). Is there any issue in iOS side (or) PHP side
If the issue is in iOS side--> How can i do this
Here is my Testing Push notification API:
https://shopgt.com/mobile1/iphone/register.php?device_type=2&email=sukhpal#anaad.net®Id=4d1d9067cc1382ecb8b0532831cce7fc8eb6fc388a6139060cd84712407a0ae5
Can you please help me out regarding this issue
You need to customize the view for showing Banner of Push Notification while the app in Foreground. You can use JCNotificationBannerPresenter. Follow the sample code using below link.
https://github.com/jcoleman/JCNotificationBannerPresenter
#import "JCNotificationCenter.h"
#import "JCNotificationBannerPresenterSmokeStyle.h"
- (void) application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)notification {
NSString* title = #"Push Notification";
NSDictionary* aps = [notification objectForKey:#"aps"];
NSString* alert = [aps objectForKey:#"alert"];
[JCNotificationCenter
enqueueNotificationWithTitle:title
message:alert
tapHandler:^{
NSLog(#"Received tap on notification banner!");
}];
}
Hope it Helps you..!
There is no issue, this is default behaviour.
The banner that appears at the top of the screen when you are on the Home screen does not appear when you are inside the app.
You need to get the app to do something with the notification yourself, inside didReceiveRemoteNotification. This could be showing an alert, adding a badge to the tab bar, etc. but banners only show when you are outside of the app.
We have integrated Urban SDK using these guidelines.
We have tried to check the push notification using ad hoc profile where we have set below values in AirshipConfig.plist
inProduction=YES
productionAppKey=OUR PRODUCTION KEY
productionAppSecret= OUR PRODUCTION SECRET
Please check the below code which we have implemented in the AppDelegate file of project.
-(void) applicationDidFinishLaunching: (UIApplication *)application
{
.
.
.
.
UAConfig *config = [UAConfig defaultConfig];
config.automaticSetupEnabled=NO;
[UAirship takeOff:config];
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
NSLog(#"------------REGISTER DEVICE------------: >= 8");
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
}
else
{
NSLog(#"------------REGISTER DEVICE------------: <8 ");
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
.
.
.
.
}
#pragma mark Remote Notification methods
-(void) application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken // Device Registration
{
[[UAirship push] appRegisteredForRemoteNotificationsWithDeviceToken:devToken];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[[UAirship push] appRegisteredUserNotificationSettings];
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(#"%#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"NOTIFICATION------------ didReceiveRemoteNotification ------------ %#", userInfo);
[[UAirship push] appReceivedRemoteNotification:userInfo applicationState:application.applicationState];
}
When we are trying to send the notification to the registered device token, the server shows that device token as INACTIVE Device token.
Please show me what should I do for this.
So, first it looks like you are missing a few app delegate methods.
Urban Airship handles APNS registration. Remove your manual registration calls as UA will just override them, and instead, enable notifications with [UAirship push].userPushNotificationsEnabled = YES;. It should prompt the user to accept notifications, and then the Urban Airship channel should be opted in.
I have seen too many questions about the silent push notification does not work if the device is not connected to xcode, but I could not find the real answer.
I'm using Silent APN to start a process in background and then fire a local Push notification
Server sends this info:
"_metadata" = {
bagde = 1;
pushText = "semeone has sent you a message!!";
sender = "semeone";
};
aps = {
"content-available" = 1;
};
And _metadata is customized info to fire the local notification, I did not included badge, pushText.. in aps because I it is a silent push notification.
Client should get the info in didReceiveRemoteNotification,
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if(application.applicationState != UIApplicationStateActive ){
if([userInfo[#"aps"][#"content-available"] intValue]== 1) //it's the silent notification
{
//start a background task
UIBackgroundTaskIdentifier preLoadPNTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background task to start a process ");
}];
//end completionHandler regarding to fetchCompletionHandler
completionHandler(UIBackgroundFetchResultNewData);
// doing my process...... and fire a local notification
if(preLoadPNTask){
NSLog(#"End Background task ");
[[UIApplication sharedApplication] endBackgroundTask:preLoadPNTask];
preLoadPNTask = 0;
}
return;
}
else
{
NSLog(#"didReceiveRemoteNotification it's NOT the silent notification ");
completionHandler(UIBackgroundFetchResultNoData);
return;
}
}
else {
if(preLoadPNTask){
NSLog(#"End Background task ");
[[UIApplication sharedApplication] endBackgroundTask:preLoadPNTask];
preLoadPNTask = 0;
}
completionHandler(UIBackgroundFetchResultNewData);
}
}
It works perfectly fine when the device is connecting to xcode, but when it doesn't, the didReceiveRemoteNotification doesn't start :(
Any ideas?
Thank you in advance!!
What I end up is a cable USB was cause me some issues apparently every time that I plugged in the iphone device said that "this accessory may not be supported" but it continue working normally , so I replace for a new one, but that not solve my issue, however can be part of this. so I looked in the code, and I did some changes, after receive 2 o more silent push notification preLoadPNTask (UIBackgroundTaskIdentifier) was creating many times so I added a validation before it start,
if(!preLoadPNTask){
//start a background task
UIBackgroundTaskIdentifier preLoadPNTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background task to start a process ");
}];
}
I hope this help you
Regards
In ios 8, You need to the following steps to fire didReceiveRemoteNotification: method
Select project target goto Capabilities tab
Select 'Background modes' turn on.
It'll add a key (Required background modes)in your project info.plist
After these modifications, when you get a apple push notification and if the app is in background already then didReceiveRemoteNotification will be fired.
Probably because under iOS 8 you have to ask for push notifications in a different way. Try this:
-(void) registerForPushNotifications {
UIApplication* application=[UIApplication sharedApplication] ;
// Register for Push Notitications, if running iOS 8
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
} else {
// Register for Push Notifications before iOS 8
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
}
I was going to new remote notifications API of iOS 8, when I found this in the docs:
"It is recommended that you call this method before you schedule any
local notifications or register with the push notification service"
I could not understand why is it said so. I have the impression that the two method calls:
registerUserNotificationSettings
and
registerForRemoteNotifications
are now independent and one does not effect other. Then why it is recommended to call one before another?
You can find this in Apple documentation:
If you want your app’s remote notifications to display alerts, play sounds, or perform other user-facing actions, you must call the registerUserNotificationSettings: method to request the types of notifications you want to use. If you do not call that method, the system delivers all remote notifications to your app silently.
IOS 8 , for fetch device token and register remote notification we need to apply a different process.
if (IS_OS_8_OR_LATER) {
//Right, that is the point
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound
|UIRemoteNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}else{
// Register for push notifications
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound];
}
///////////Again we need to define
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
//handle the actions
if ([identifier isEqualToString:#"declineAction"]){
}
else if ([identifier isEqualToString:#"answerAction"]){
}
}
Then we can get the device token in ios 8
I have tried to set up Urban Airship to deliver push notifications to my iOS application with no luck.
Here are the things I have:
Developer Provisioning profile with push notifications enabled
Push Notification Certificate on device and uploaded to Urban Airship
No errors anywhere - UA's error console is empty and I checked that my Device token is active
Here is some snippets from my AppDelegate.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
//Init Airship launch options
NSMutableDictionary *takeOffOptions = [[NSMutableDictionary alloc] init];
[takeOffOptions setValue:launchOptions forKey:UAirshipTakeOffOptionsLaunchOptionsKey];
// Create Airship singleton that's used to talk to Urban Airship servers.
// Please populate AirshipConfig.plist with your info from http://go.urbanairship.com
[UAirship takeOff:takeOffOptions];
// Register for notifications
[[UAPush shared] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)];
[UAirship setLogging:YES];
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
// Updates the device token and registers the token with UA
NSLog(#"APN device token: %#", devToken);
[[UAPush shared] registerDeviceToken:devToken];
}
None of the following methods are ever called when I send a notification through UA's "Test Push Notification" tab, or send a CURL command through terminal
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"Error in registration. Error: %#", err.description);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received push notification with userInfo:%#", userInfo);
}
- (void)handleNotification:(NSDictionary *)notification applicationState:(UIApplicationState)state
{
NSLog(#"Received push notification with notification:%#", notification);
}
I have tried sending test push notifications with the app closed and iOS does not do anything either. I checked in Settings on the iphone and went to my app and it shows push is enabled for badges and banners. I'm running iOS 6.1 on an iPhone 5.
I figured it out - I must have missed this line from the documentation:
[[UAPush shared] handleNotification:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]
applicationState:application.applicationState];