0

I'm using the following code to "simply" determine the application state of the parent application from my watch app:

WatchKit Extension:

[WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error)
    {
        UIApplicationState appState =  UIApplicationStateBackground;
        if(nil != replyInfo)
            appState = (UIApplicationState)[((NSNumber*)[replyInfo objectForKey:kAppStateKey]) integerValue];

        //handle app state
    }];

Main App:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply
{
    __block UIBackgroundTaskIdentifier realBackgroundTask;

    realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

        reply([NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:[[UIApplication sharedApplication] applicationState]], kAppStateKey, nil]);
        [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
    }];

    reply([NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:[[UIApplication sharedApplication] applicationState]], kAppStateKey, nil]);

    [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}

When the app is in the foreground this works 100% of the time. When the app is "minimized" or "terminated" this maybe works 50% of the time (maybe less). When it doesn't work it appears to be blocking indefinitely. If after 1 minute, for example, I launch the parent app, the call (openParentApplication) immediately returns with the state "UIApplicationStateBackground" (the state it was before I launched the app as clearly the app isn't in the background state if I launched it).

BTW: I'm testing with real hardware.

What am I doing wrong? Why is iOS putting my main app to sleep immediately after receiving the call even though I create a background task? This is a complete show-stopper.

Any thoughts or suggestions would be greatly appreciated!!

user3335999
  • 392
  • 1
  • 2
  • 17

1 Answers1

0

After some research it looks to be a known issue. For example, the following link identifies this issue and provides a solution:

http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply

However, this solution did not work for me. As a result I implemented the following solution (its a little sloppy, but this is intentional to help condense the solution):

//start the timeout timer
timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeOutTime target:self selector:@selector(onTimeout) userInfo:nil repeats:NO];

//make the call
messageSent = [WKInterfaceController openParentApplication:[NSDictionary dictionary] reply:^(NSDictionary *replyInfo, NSError *error)
{
  if(nil != _stateDelegate)
  {     
    UIApplicationState appState =  UIApplicationStateBackground;
    if(nil != replyInfo)
      appState = (UIApplicationState)[((NSNumber*)[replyInfo objectForKey:kAppStateKey]) integerValue];

    [_stateDelegate onOperationComplete:self timeout:false applicationState:appState];
    _stateDelegate = nil;
   }
}];

//if the message wasn't sent, then this ends now
if(!messageSent)
{
   if(nil != _stateDelegate)
   {
      //just report that the main application is inactive
      [_stateDelegate onOperationComplete:self timeout:false applicationState:UIApplicationStateInactive];
   }
   _stateDelegate = nil;
}


-(void)onTimeout
{
    timeoutTimer = nil;
    if(nil != _stateDelegate)
    {
        [_stateDelegate onOperationComplete:self timeout:true applicationState:UIApplicationStateInactive];
    }
    _stateDelegate = nil;
}

In a nutshell, if the timer fires before I hear back from the main app I will basically assume that the main app has been put to sleep. Keep in mind that all pending calls will succeed at some point (e.g. app state is restored to active) and, thus, you will need to handle this scenario (if necessary).

user3335999
  • 392
  • 1
  • 2
  • 17