簡體   English   中英

iOS / Objective-C:外圍模式下的BLE不起作用

[英]iOS/Objective-C: BLE in Peripheral mode doesn't work

我正試圖在中央外圍模式下啟動BLE。 現在為了簡單起見,使用硬編碼變量。
我想我已根據文檔實現了所有內容。

我可以使用Android智能手機檢查外設模式是否正常工作(api-19,不支持外設模式)。 例如,當我使用MyBeacon應用程序時,iPhone會正確顯示。

但是,當我在我的應用程序中運行此代碼時,它不會顯示:

這是.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");

我有這個建議:

在相關主題上,確保無論代碼創建和執行什么代碼都允許對象生存足夠長的時間以執行藍牙操作。 如果它超出范圍或被垃圾收集,你將遇到同樣的問題。

我不知道如何檢查這是否屬實。

此外, 本教程使用此方法:

- (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];
    }
}

...但是文檔中沒有任何與此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.stateperipheral.state返回4 ,而CB...ManagerStatePoweredOn等於5 我如何使它等於5 應用程序請求訪問bt,但iphone沒有啟用它。 當手動啟用時,一切似乎都運行良好。

您可能過早地將服務transferService添加到外圍設備管理器,您也可能過早地開始播放廣告。

您必須等到 peripheralManagerDidUpdateState報告您的外圍設備管理器的狀態已達到CBPeripheralManagerStatePoweredOn

RCT_EXPORT_METHOD(start:(NSDictionary *)options) ,您可以將代碼從RCT_EXPORT_METHOD(start:(NSDictionary *)options)到空的peripheralManagerDidUpdateState實現中。

或者,如果你只想服務添加到您的peripheralManager ,然后開始投放廣告,當有人呼吁您start方法(看起來像你創建一個陣營的天然結合?),確保self.peripheralManager.stateCBPeripheralManagerStatePoweredOn你內start方法。 但是這需要start (你的React Native JS代碼)的調用者不要過早地調用這個方法。

RCT_EXPORT_METHOD(start:(NSDictionary *)options)
{
  NSLog(@"Start?");
  if (self.peripheralManager.state != CBPeripheralManagerStatePoweredOn) {
      NSLog(@"Peripheral is not powered on");
      return;
  }
  if (self.centralManager.state != CBCentralManagerStatePoweredOn) {
      NSLog(@"Central is not powered on");
      return;
  }
  NSLog(@"OK, peripheral and central are both powered on");
  [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");
}

同樣,只有在具有“開機”狀態的情況下,才能使用centralManager開始掃描外圍設備。

顯然,沒有辦法以編程方式在iOS上打開藍牙,以及現在無法以編程方式進行配對。

但是,我們可以通過RCT_EXPORT_METHOD(start:(NSDictionary *)選項)方法中的警報來啟用用戶打開藍牙。

if(peripheralManager.state < CBPeripheralManagerStatePoweredOn){
{
     //Show alert to user to turn on the Bluetooth and it will go to 
       peripheralManagerDidUpdateState when user turn it on.
}
else
{
     //You can continue setting up the data.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM