简体   繁体   中英

iOS WatchOS2 WatchConnectivity [WCSession defaultSession] activateSession] failure

I have XCode 7.3, iPhone5 with iOS 9.3, Apple Watch with WatchOS 2.2

I have a company project which wants to support Watch App. Firstly, I built an empty project to make sure the watchkit and watchkit extension is working, and it does work. I can see the session is established and the watch is paired.

But after i put the same code into the company project, it can only work for once:the first time I RUN the app directly from Xcode.When I kill the app from background and open it again, the app shows no paired watch. In this condition , I got the log below: In iOS app

paired == NO ---- watchAppInstalled=== NO---- complicationEnabled==NO  ----<WCSession:0x7ffb9a815ab0,hasDelegate:No,activationState:2>

in watchKit Extension

Error Domain=WCErrorDomain Code=7004 "WatchConnectivity session has not been activated." UserInfo={NSLocalizedRecoverySuggestion=Activate the WatchConnectivity session., NSLocalizedDescription=WatchConnectivity session has not been activated., NSLocalizedFailureReason=Function activateSession has not been called.}

my code about wcsession :

iOS APP

in AppDelegate+GC_WCSession

 - (void)startWCSession{

    [self configSession];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeLoginStatus:) name:GCLoginNotifyKey object:nil];

}
- (void)configSession{
    if (![WCSession isSupported]) {
        return;
    }
    _session = [WCSession defaultSession];
    [_session setDelegate:self];
    [_session activateSession];
}
- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {
    [self.session activateSession];
    if ([applicationContext objectForKey:k_WK_Token]) {
        [self synchronousUserInfo];
    }
}

- (void)changeLoginStatus:(NSNotification *)noti{
    ///
    [self synchronousUserInfo];
}

- (void)synchronousUserInfo{
   ///customCode
    [self.session updateApplicationContext:replayDict error:nil];
}

- (WCSession *)session{
    if (![WCSession isSupported] || ![[WCSession defaultSession] isPaired ]|| ![[WCSession defaultSession]isWatchAppInstalled] ) {
        return nil;
    }
    return  _session;
}

in AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     [self startWCSession]; 
}

watchKit Extension

in ExtensionDelegate

- (void)applicationDidFinishLaunching {
    // Perform any final initialization of your application.
     [self startWCSession];
}
- (void)startWCSession{

    [self configSession];
}
- (void)configSession{
    _session = [WCSession defaultSession];
    [_session setDelegate:self];
    [_session activateSession];
}

- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {
  ///customcode
}
- (WCSession *)session{
    return _session;
}

This is what I've tried up to now:

  • reset content and settings of all simulators

  • deleted watch app from watch &from iPhone

  • via settings in Watch App on Phone: Removed Watch Extension for Phone App and reinstalled it

  • Tried setting up the iPhone WCSession in AppDelegate INIT Method

I don't think the code is wrong, because it's working in an empty project.I wonder if the environment config has problems. I am struggling with this issue for many days now. So every hint is highly appreciated.

As PetahChristian was saying in the comments, in your ExtensionController class change this method:

- (void)applicationDidFinishLaunching {
    // Perform any final initialization of your application.
   [self startWCSession];
}

to be:

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self startWCSession];
    }
    return self;
}

- (void)applicationDidFinishLaunching {
    // Perform any final initialization of your application.
}

You should then be able to receive content via WatchConnectivity even if your extension is running in the background for a complication update.

I Solved this issue. The code is blow.

- (void)configSession{
    dispatch_async(dispatch_get_main_queue(), ^{
    if (![WCSession isSupported]) {
        return;
    }
    _session = [WCSession defaultSession];
    [_session setDelegate:self];
    [_session activateSession];
   });
}

But I don't see any documents that need to call this method in the main thread. Moreover, this method is called before is in the main thread.So I think it might be the runloop problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM