从 Apple Watch 应用程序到其他设备的本地网络连接在模拟器上有效,但在 Watch 上无效

Local network connection from Apple Watch app to an other device works on simulator but not on the Watch

我正在尝试为我的 Apple Watch 构建一个应用程序来远程控制 Raspberry Pi 上的媒体播放器 (omxplayer)。

我在 Xcode 的模拟器中使用它,但它在实际手表上不起作用。

在 Raspberry Pi 上,我有一个简单的 python 脚本可以启动 TCP 服务器并侦听命令。

在 WatchKit 扩展项目的 InterfaceController.m 文件中,我有以下代码:

- (IBAction)playPauseButtonPressed {    
    [self initNetworkCommunication];
    [self sendNetworkCommand:@"play"];
    [self closeNetworkCommunication];
}

-(void)initNetworkCommunication {
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.10.116", 10010, &readStream, &writeStream);

    if(!CFWriteStreamOpen(writeStream)) {
        NSLog(@"Error, writeStream not open");

        return;
    }

    inputStream = (NSInputStream *)CFBridgingRelease(readStream);
    outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream open];
    [outputStream open];
}

-(void)sendNetworkCommand:(NSString *) command {    
    NSData *data = [[NSData alloc] initWithData:[command dataUsingEncoding:NSASCIIStringEncoding]];
    [outputStream write:[data bytes] maxLength:[data length]];
}

-(void)closeNetworkCommunication {        
    [inputStream close];
    [outputStream close];

    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream setDelegate:nil];
    [outputStream setDelegate:nil];

    inputStream = nil;
    outputStream = nil;
}

当我按下手表应用程序上的按钮时,会调用 "playPauseButtonPressed" 函数。此功能启动到 Raspberry Pi 的网络连接并发送一个字符串。

正如我所说,它可以在 Watch 模拟器上运行,但不能在真实设备上运行。

请注意,相同的代码适用于真实设备上的 iOS 应用程序。

如有任何帮助,我们将不胜感激!

好的,我成功了。与此同时,我升级到了 WatchKit 2.0 SDK。如果有人感兴趣,这是我的代码(仍然需要工作):

手表扩展的

ExtensionDelegate.m:

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

    if ([WCSession isSupported]) {
        WCSession *session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];
    }
}
手表扩展的

InterfaceController.m:

- (IBAction)playPauseButtonPressed
{
    [self sendCommandToPhone:@"pause"];
}

- (IBAction)seekBackwardButtonPressed
{
    [self sendCommandToPhone:@"seek_backward"];
}

- (IBAction)seekForwardButtonPressed
{
    [self sendCommandToPhone:@"seek_forward"];
}

- (IBAction)subtitleButtonPressed
{
    [self sendCommandToPhone:@"subtitle"];
}

- (void)sendCommandToPhone:(NSString *)command
{
    NSLog(@"sendCommandToPhone called");

    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:command, @"command", nil];
    [[WCSession defaultSession] sendMessage:dict
                               replyHandler:^(NSDictionary *replyHandler) {
                               }
                               errorHandler:^(NSError *error) {
                                   NSLog(@"%@", [error localizedDescription]);
                               }
    ];
}
iPhone 应用程序的

ViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Init communication with watch
    if ([WCSession isSupported]) {
        WCSession *session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];

        NSLog(@"WCSession initialized");
    }
}

// Message received from the watch
- (void)session:(WCSession * _Nonnull)session didReceiveMessage:(NSDictionary<NSString *, id> * _Nonnull)message
{
    NSLog(@"didReceiveMessage called");
    [self sendCommandToPlayerAndCloseConnection:message[@"command"]];
}

- (IBAction)connectButtonPressed:(id)sender
{
    [self sendCommandToPlayer:@"list_dir"];
    [self performSegueWithIdentifier:@"toFileTableViewController" sender:self];
}

- (IBAction)seekBackwardButtonPressed:(id)sender
{
    [self sendCommandToPlayerAndCloseConnection:@"seek_backward"];
}

- (IBAction)seekForwardButtonPressed:(id)sender
{
    [self sendCommandToPlayerAndCloseConnection:@"seek_forward"];
}

- (IBAction)stopButtonPressed:(id)sender
{
    [self sendCommandToPlayerAndCloseConnection:@"stop"];
}

- (IBAction)playPauseButtonPressed:(id)sender
{
    [self sendCommandToPlayerAndCloseConnection:@"pause"];
}

- (void)sendCommandToPlayer:(NSString *) command
{
    NSLog(@"%@", [NSString stringWithFormat:@"Sending command to player : %@", command]);

    [self initNetworkCommunication];

    NSData *data = [[NSData alloc] initWithData:[command dataUsingEncoding:NSASCIIStringEncoding]];
    [outputStream write:[data bytes] maxLength:[data length]];
}

- (void)sendCommandToPlayerAndCloseConnection:(NSString *) command
{
    [self sendCommandToPlayer:command];
    [self closeNetworkCommunication];
}

-(void)initNetworkCommunication
{
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.10.116", 10023, &readStream, &writeStream);

    if(!CFWriteStreamOpen(writeStream)) {
        NSLog(@"Error, writeStream not open");

        return;
    }

    inputStream = (__bridge NSInputStream *) readStream;
    outputStream = (__bridge NSOutputStream *) writeStream;

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream open];
    [outputStream open];
}

-(void)closeNetworkCommunication
{    
    [inputStream close];
    [outputStream close];

    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream setDelegate:nil];
    [outputStream setDelegate:nil];

    inputStream = nil;
    outputStream = nil;
}

现在我可以通过我的 phone 和我的手表控制 omxplayer ;)