Я пытаюсь запустить BLE в Central и Peripheral. С жестко закодированными переменными на данный момент для простоты.
Я думаю, что я реализовал все в соответствии с документами.
Я могу проверить, работает ли периферийный режим с помощью Android-смартфона (api-19, не поддерживайте периферийный режим). iPhone отображается правильно, когда я использую приложение MyBeacon, например.
Однако он не появляется, когда я запускаю этот код в своем приложении:
Вот .h
:
#import <RCTBridgeModule.h>
#import <RCTEventEmitter.h>
@import CoreBluetooth;
@import QuartzCore;
@interface BTManager : RCTEventEmitter <RCTBridgeModule, CBCentralManagerDelegate, CBPeripheralManagerDelegate, CBPeripheralDelegate>
@property (nonatomic, strong) CBCentralManager *centralManager;
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;
@property (nonatomic, strong) CBMutableCharacteristic *transferCharacteristic;
@end
И .m
:
#import "BTManager.h"
@implementation BTManager
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"BTManagerDeviceFound", @"BTManagerStatus"];
}
- (void)viewDidLoad
{
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
self.centralManager = centralManager;
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
self.peripheralManager = peripheralManager;
}
RCT_EXPORT_METHOD(start:(NSDictionary *)options)
{
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable];
CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] primary:YES];
transferService.characteristics = @[self.transferCharacteristic];
[self.peripheralManager addService:transferService];
[self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:@"FB694B90-F49E-4597-8306-171BBA78F846"]] }];
NSLog(@"Started");
}
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
// log peripheralManager state
NSLog(@"peripheralManagerDidUpdateState peripheral %@", peripheral);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error
{
// log centralManager state
NSLog(@"peripheralManager didAddService peripheral %@", peripheral);
NSLog(@"peripheralManager didAddService service %@", service);
NSLog(@"peripheralManager didAddService error %@", error);
}
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error
{
NSLog(@"peripheralManagerDidStartAdvertising peripheral %@", peripheral);
NSLog(@"peripheralManagerDidStartAdvertising error %@", error);
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
[self sendEventWithName:@"BTManagerDeviceFound" body:advertisementData];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSLog(@"centralManagerDidUpdateState central %@", central);
}
RCT_EXPORT_METHOD(stop:(NSDictionary *)options)
{
// remove all related processes, send event to js
[self sendEventWithName:@"BTManagerStatus" body:@"details here"];
// [self.myCentralManager stopScan];
}
@end
Никто из прослушивателей событий не стреляет, кроме NSLog(@"Started");
У меня есть это предложение:
В отношении связанного объекта убедитесь, что любой код, созданный и выполняющий ваш BTManager, позволяет объекту жить достаточно долго для выполнения действий Bluetooth. Если он выходит из сферы действия или собирает мусор, у вас будет такая же проблема.
Я не знаю, как проверить, верно это или нет.
Кроме того, этот учебник использует этот метод:
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
return;
}
if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES];
transferService.characteristics = @[_transferCharacteristic];
[_peripheralManager addService:transferService];
}
}
... но docs не содержит ничего, что связано с этим CBPeripheralManagerStatePoweredOn
. Статья составляет 4 года, поэтому она может быть даже не актуальна сейчас.
О, да, а также я едва знаком с objective-c, поэтому ошибка там может быть очень простой.
Спасибо, что прочитали здесь:)
Обновление 1
По-видимому, viewDidLoad
никогда не запускается. Поэтому я переместил код из него в метод start
и код из start
в ...DidUpdateState
, как предложил @LarsBlumberg.
#import "BTManager.h"
#import <React/RCTLog.h>
@implementation BTManager
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"BTManagerDeviceFound", @"BTManagerStatus"];
}
RCT_EXPORT_METHOD(start:(NSDictionary *)options)
{
RCTLogInfo(@"Start?");
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey: @(YES)}];
self.centralManager = centralManager;
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
self.peripheralManager = peripheralManager;
RCTLogInfo(@"Started");
}
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
// log peripheralManager state
RCTLogInfo(@"peripheralManagerDidUpdateState peripheral %ld", (long)peripheral.state);
if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
RCTLogInfo(@"Peripheral is not powered on");
return;
}
self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable];
CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] primary:YES];
transferService.characteristics = @[self.transferCharacteristic];
[peripheral addService:transferService];
NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey : @"yphone", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:@"EBA38950-0D9B-4DBA-B0DF-BC7196DD44FC"]]};
[peripheral startAdvertising:advertisingData];
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error
{
// log centralManager state
RCTLogInfo(@"peripheralManager didAddService peripheral %@", peripheral);
RCTLogInfo(@"peripheralManager didAddService service %@", service);
RCTLogInfo(@"peripheralManager didAddService error %@", error);
}
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error
{
RCTLogInfo(@"peripheralManagerDidStartAdvertising peripheral %@", peripheral);
RCTLogInfo(@"peripheralManagerDidStartAdvertising error %@", error);
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
[self sendEventWithName:@"BTManagerDeviceFound" body:advertisementData];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
RCTLogInfo(@"centralManagerDidUpdateState central %ld", (long)central.state);
// if (central.state == CBCentralManagerStatePoweredOff) {
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Error" message: @"Please turn on Bluetooth in Settings" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
// [alert show];
// }
if (central.state != CBCentralManagerStatePoweredOn) {
RCTLogInfo(@"Central is not powered on");
return;
}
[central scanForPeripheralsWithServices:nil options:nil];
}
RCT_EXPORT_METHOD(stop:(NSDictionary *)options)
{
// remove all related processes, send event to js
[self sendEventWithName:@"BTManagerStatus" body:@"details here"];
// [self.myCentralManager stopScan];
}
@end
Теперь все идет нормально до состояния обновлений. Оба central.state
и peripheral.state
возвращают 4
, а CB...ManagerStatePoweredOn
равно 5
. Как сделать его равным 5
? Приложение запрашивает доступ к bt, но iphone не разрешает его. Когда он включается вручную, все работает хорошо.