【问题标题】:Local network connection from Apple Watch app to an other device works on simulator but not on the Watch从 Apple Watch 应用程序到其他设备的本地网络连接在模拟器上有效,但在 Watch 上无效
【发布时间】:2015-07-25 20:27:27
【问题描述】:

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

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

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

在 WatchKit Extension projet 的 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”函数。该函数启动到树莓派的网络连接并发送一个字符串。

正如我所说,它适用于 Watch 模拟器,但不适用于真实设备。

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

任何帮助将不胜感激!

【问题讨论】:

  • TCP 连接的东西在 Watch 上不起作用吗?我有同样的问题,都可以在模拟器上运行,但不能在真实手表上运行。
  • 我不知道,正如我在回答中所写的那样,我现在使用 WCSession 与手机应用程序进行通信,所有的网络逻辑都是从应用程序完成的

标签: ios objective-c apple-watch


【解决方案1】:

好的,我得到了它的工作。与此同时,我升级到了 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;
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多