I am creating an application that receives push notifications, and once recieved a push notification it will process this normally if the application is active, or process it in the background if it is not running.
The most annoying part - The app works fine when I am in Development mode and running through XCode. But when I put an Ad Hoc build up, the app only receives the notifications if the app is running. My Code to handle the notification is below, can someone please shed some light on this:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
MySharedClass *shared = [MySharedClass sharedManager];
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
shared.localNotif = userInfo;
if (shared.localNotif) {
[shared ReceivedPushNotification];
}
} else {
__block UIBackgroundTaskIdentifier background_task;
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
//To make the code block asynchronous
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//### background task starts
NSLog(#"Running in the background\n");
completionHandler(UIBackgroundFetchResultNewData);
shared.localNotif = userInfo;
if (shared.localNotif) {
[shared ReceivedPushNotification];
}
while(TRUE)
{
NSLog(#"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
[NSThread sleepForTimeInterval:1]; //wait for 1 sec
}
//#### background task ends
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
});
}
}
Related
I am using following code to handle push notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if(application.applicationState == UIApplicationStateInactive)
{
//************************************************************
// I only want this called when user click on notification.
//************************************************************
NSLog(#"Inactive");
if ([[userInfo valueForKey:#"noty_type"] isEqualToString:#"web"])
{
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:[userInfo valueForKey:#"url"]]])
{
dispatch_async(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[userInfo valueForKey:#"url"]]];
});
}
}
}
if((application.applicationState == UIApplicationStateActive)
{
// I am useing local notification when app in Forground
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.soundName = #"Default";
localNotification.alertBody = [userInfo valueForKey:#"msg"];
localNotification.userInfo = userInfo;
[[UIApplication sharedApplication] scheduleLocalNotification: localNotification];
}
}
This code open the url in safari browser. this code work fine When my app in background and notification come and I click on notification check the applicationState and open the url with [[UIApplication sharedApplication] openURL.
now the scenario that generate the problem.
I open my app .
and Down the notification UI
now Send the notification from server
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler method get called.
Now I get the ApplicationState == UIApplicationStateInactive .
"It open into the safari browser without any user interaction".
I only want this called when user click on notification.
So, How can I handle this condition ?
Try this.
if (application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground)
{
// do something when app open with notification
}
You have to know why the app is inactive. The two possibilities are that the app was in the background and the user is bringing it to the foreground (by tapping on the notification banner), or something like the notification center was pulled down or the user got a system alert.
To tell the difference, keep track of when the user enters the background. Just set a boolean in the applicationDidEnterBackground: delegate method, and clear it when the app is resigning active.
static BOOL didEnterBackground;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Launching the app is kind of like coming from background.
didEnterEnterBackground = YES;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
didEnterBackground = NO;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
didEnterBackground = YES;
}
Now you can check the variable didEnterBackground to determine how the app got to the inactive state when you're handling a notification.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
if (application.applicationState == UIApplicationStateInactive) {
if (didEnterBackground) {
// The user tapped the notification
}
else {
// The app was inactive, but not in the background.
// Ignore notification, or do whatever the app does
// when receiving a notification while active.
}
}
}
Hope this help you
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
}//iOS below 9
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(nullable NSString *)identifier
forLocalNotification:(nonnull UILocalNotification *)notification
completionHandler:(nonnull void (^)())completionHandler {
// handling local and interactive notifcation
} // iOS 9 and above
Which is used to trigger the notification in background state.
I am trying to execute my code whenever my app enters into background. But my code is not working. Here is my following code:
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask;
NSLog(#"enter in background task");
UIApplication *app = [UIApplication sharedApplication];
NSLog(#"app is %#",app);
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"called function");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}]; }
But my code is not working. As it does not print called function.
Thanks in advance.
I want to update application badge icon when a notification is received. It works fine when app is running (active mode),but having trouble when trying to set it when app is in suspended/background mode. Want to achieve the same without using the 'badge' field in apns dictionary.
Here is what i am doing,
-(void) incrementOneBadge{
NSInteger numberOfBadges = [UIApplication sharedApplication].applicationIconBadgeNumber;
numberOfBadges +=1;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfBadges];
}
-(void) decrementOneBadge{ NSInteger numberOfBadges = [UIApplication sharedApplication].applicationIconBadgeNumber;
numberOfBadges -=1;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfBadges];
}
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
}
else {
// Push Notification received in the background
[self incrementOneBadge];
}
[self handlePushNotificationsForState:application withDictionary:userInfo];
}
I want to fetch service for every 15 mins,so i am using NSTimer.It is working fine.But how to call same service while app is in background state by using nstimer.Nstimer is not working in background state.Please suggest me.
//when the application is about to move from active to inactive state.
- (void)applicationWillResignActive:(UIApplication *)application
{
[self sendBackgroundLocationToServer];
}
- (void) sendBackgroundLocationToServer
{
UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}];
//Start Timer
[self startTimer];
//Close the task
if (bgTask != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}
}
I'm making an iphone app(Live radio app).
My app is supported background mode.
But, if the phone rings when radio app is playing in background mode, my app stop with errors .
MP AVAudioSessionDelegateMediaPlayerOnly end interruption. Interruptor <Phone> category <completed> resumable <0>, _state = 6
MP endInterruptionFromInterruptor :: resuming playback
So, I modified my code, but useless.
I'll add my code. Please tell me my faults. Thanks.
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate, AVAudioSessionDelegate>
#property (assign, nonatomic) UIBackgroundTaskIdentifier bgTask;
... ...
#end
AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// Clean up any unfinished task business by marking where you.
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
}
viewController.m
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
moviePlayer = [[MPMoviePlayerController alloc] init];
[moviePlayer setContentURL:... m3u8];
[moviePlayer play];
you need to add this:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];