1

我正在开发一个与蓝牙 2.1 通信的 iOS 应用程序。应用程序在激活时连接到 BT。如果应用程序进入后台并再次激活,它工作正常。

但我刚刚注意到一个问题:

如果我关闭 BT 模块电源,应用程序会收到通知,我执行以下操作:

  - (void)accessoryDidDisconnect:(EAAccessory *)accessory
    {
        NSLog(@"EAController::accessoryDidDisconnect:");
        _selectedAccessory = nil;
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"Lost connection. " delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setBool:YES forKey:@"Lost Communication"];
        [self closeSession];
    }

然后我重新打开模块电源,进入设置 -> 蓝牙,将 BT 模块连接到 iPhone,活动应用程序(从后台返回),无法启动 EASession:

if (_session == nil)
    {
        NSLog(@"EAController::openSession");
        [_selectedAccessory setDelegate:self];
        _session = [[EASession alloc] initWithAccessory:[self selectedAccessory] forProtocol:_protocolString];

        if (_session)
        {
                    // Set up delegate........
        }
        else
        {
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setBool:NO forKey:Unit_Has_Connection_UserDefault_Key];
            NSLog(@"creating session failed");
        }
    }

启动 _accessoryList 和 _selectedAccessory:

_accessoryList = [[NSMutableArray alloc] initWithArray:[[EAAccessoryManager sharedAccessoryManager] connectedAccessories]];
_selectedAccessory = [_accessoryList objectAtIndex:0];

我发现 _accessoryList 有我正在使用的附件,但它的“协议”是空的。

$12 = 0x1dd58050 <__NSArrayI 0x1dd58050>(
<EAAccessory: 0x1dd1dce0> {
  connected:YES
  connectionID:XXX
  name: XXX
  manufacturer: XXX
  modelNumber: XXX
  serialNumber: 
  firmwareRevision: XXX
  hardwareRevision: XXX
  macAddress: XXX
  protocols: (
)
  delegate: (null)
}
)

如果我杀死应用程序并重新启动,它工作正常。

有谁知道如何解决这个问题?

这个问题与这个问题类似但发生在不同的情况下,并且该问题的答案似乎无法解决我的问题。

4

4 回答 4

1

经过几天寻找解决方案,我终于解决了这个问题(或者我希望我解决了。)。我在这里发布我的答案,所以如果有人有同样的问题可以有一个想法。

你永远不能相信 EAAccessoryManager,它可能有幽灵附件。因此,使用以下命令启动 _accessoryList 并不总是有效。

_accessoryList = [[NSMutableArray alloc] initWithArray:[[EAAccessoryManager sharedAccessoryManager] connectedAccessories]];

如果您使用幽灵附件启动附件列表,则肯定无法成功启动 EASession。

正确的方法是使用 EAAccessory Notification,这在这个答案中有描述,但它没有详细说明如何做。

首先,您需要创建两个通知:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(accessoryConnected:) name:EAAccessoryDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(accessoryDisconnected:) name:EAAccessoryDidConnectNotification object:nil];

[[EAAccessoryManager sharedAccessoryManager]registerForLocalNotifications];

然后在accessoryConnected和accessoryDisconnected中,可以进行如下操作。

- (void)accessoryConnected:(NSNotification *)notification
{
    NSLog(@"EAController::accessoryConnected");

    EAAccessory *connectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];
    [[self accessoryList] addObject:connectedAccessory];
    if ([_accessoryList count])
    {
        _selectedAccessory = [_accessoryList objectAtIndex:0];
        NSArray *protocolStrings = [_selectedAccessory protocolStrings];
        if ([protocolStrings count]) {
            self.protocolString = [protocolStrings objectAtIndex:0];
            [self openSession];
        }
    }
}


- (void)accessoryDisconnected:(NSNotification *)notification
{
    EAAccessory *disconnectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];

    int disconnectedAccessoryIndex = 0;
    for(EAAccessory *accessory in [self accessoryList]) {
        if ([disconnectedAccessory connectionID] == [accessory connectionID]) {
            break;
        }
        disconnectedAccessoryIndex++;
    }

    if (disconnectedAccessoryIndex < [[self accessoryList] count]) {
        [[self accessoryList ] removeObjectAtIndex:disconnectedAccessoryIndex];
    } else {
        NSLog(@"could not find disconnected accessory in accessory list");
    }
    NSLog(@"_accessory did disconnect: %@",_accessoryList);

}
于 2013-08-19T20:12:56.533 回答
1

从后台返回时,我在重新连接到我的配件时也遇到了问题,尤其是在假设 8h+ 空闲之后。详细说明仅依赖 EAAccessoryDidConnectNotification/Disconnect(而不是可以提供幽灵设备的 EAAccessoryManager)看起来大部分时间都可以正常工作

但是,如果两个应用程序正在使用我们的配件,则一旦唤醒手机/平板电脑,它可能会出现故障。第一个进入前台的应用程序最终会收到连接通知。但是在第二个应用程序中交换时 - 它只会收到断开连接通知,而不是连接。在这里,我很难确定我们是否有连接的附件,因为我不能信任 EAAccessoryManager。

于 2014-10-13T07:36:03.477 回答
1

我发现当 EAAccessory 重新连接时,您会看到配件对象的两次刷新。第一个没有协议字符串,而几秒钟后,相同的附件(具有相同的连接 ID)以协议字符串重新出现。结构化我的代码 st 它会根据 Apple 推荐的技术忽略任何没有协议字符串的附件。

于 2016-04-12T21:14:11.510 回答
-1

我相信您的配件必须具有与 MFI(Made for iPhone、ipAd 和 iPod touch)芯片一起定义的协议,以支持 iDevice 和配件之间的通信。您需要检查您的固件团队以及苹果 MFI 程序。该协议需要在应用程序plist文件的“支持的外部附件协议”字段中添加。

于 2014-07-18T13:20:02.047 回答