0

次のコードを使用して、時計アプリから親アプリケーションのアプリケーション状態を「単純に」判断しています。

WatchKit 拡張機能:

[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
    }];

メインアプリ:

- (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];
}

アプリがフォアグラウンドにある場合、これは常に 100% 機能します。アプリが「最小化」または「終了」されている場合、これはおそらく 50% の時間 (おそらくそれ以下) で機能します。機能しない場合、無期限にブロックしているように見えます。たとえば、1 分後に親アプリを起動すると、呼び出し (openParentApplication) はすぐに状態 "UIApplicationStateBackground" (アプリを起動する前の状態) で返されます。立ち上げました)。

ところで:私は実際のハードウェアでテストしています。

私は何を間違っていますか?バックグラウンド タスクを作成しているにもかかわらず、iOS が通話を受信した直後にメイン アプリをスリープ状態にするのはなぜですか? これは完全なショーストッパーです。

どんな考えや提案も大歓迎です!!

4

1 に答える 1

0

いくつかの調査の後、既知の問題のようです。たとえば、次のリンクはこの問題を識別し、解決策を提供します。

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

ただし、この解決策はうまくいきませんでした。その結果、次の解決策を実装しました (少しずさんですが、これは解決策を要約するために意図的なものです)。

//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;
}

簡単に言うと、メイン アプリから応答が返ってくる前にタイマーが起動した場合、基本的にはメイン アプリがスリープ状態になっていると見なします。保留中のすべての呼び出しはいずれかの時点で成功する (たとえば、アプリの状態がアクティブに復元される) ため、(必要に応じて) このシナリオを処理する必要があることに注意してください。

于 2015-07-28T01:15:43.533 に答える