2016-08-05 1 views
2

Je rencontre un problème avec un périphérique Bluetooth fonctionnant avec une application iOS en arrière-plan. J'ai besoin de l'application pour répondre à toutes les notifications bluetooth en temps réel. J'ai suivi Apple's CoreBluetooth background process guide et cela fonctionne environ 10% du temps que mon application est en arrière-plan, mais les autres 90% du temps les événements sont mis en file d'attente et envoyés à mon application par lots toutes les 10 minutes. J'ai juste besoin de lancer une demande de réseau sous-réseau local rapide sur wifi après un événement bluetooth, donc il faut bien sous iOS 10s donne aux applications de travailler en arrière-plan. En ce qui concerne les paramètres CoreBluetooth, j'ai suivi le guide à la lettre, et il fonctionne parfois en arrière-plan. Mais il enregistre également les notifications et relance mon application toutes les dix minutes, ce qui me fait penser qu'il est configuré correctement.Le périphérique Bluetooth connecté à iOS ne fonctionne pas en arrière-plan

Je peux confirmer que l'application n'est pas en cours de suppression. Je peux garder le débogueur attaché et il continue à fonctionner. En fait, le débogueur montre que les notifications sont mises en file d'attente et que l'application entre au premier plan toutes les dix minutes. Cela fonctionne pendant quelques minutes après que j'utilise l'application. Mais il devient inévitablement complètement contextualisé.

Je m'attendrais à ce que l'application soit réveillée dès qu'une notification bluetooth est reçue. La vérification de la liste des appareils connectés sur l'écran iOS Settings> Bluetooth montre un périphérique connecté. Et il est clair que iOS capture les notifications. Mais il réveille rarement l'application pour envoyer les notifications.


Mise à jour le 10 août 2016:

La question est donc pas dans l'appareil lui-même. Il reste connecté et même l'application Paramètres d'iOS indique que l'appareil est toujours connecté. Je me suis rendu compte cependant que j'avais beginBackgroundTaskWithExpirationHandler fonctionnant sur applicationWillResignActive, ce qui me donnait une activité de pseudo-arrière-plan. Quand j'ai commenté cela, l'application ne cesse plus de suspendre la notification bluetooth de mon appareil. Toutes les notifications bluetooth sont mises en file d'attente et se déclenchent immédiatement lorsque l'application est relancée manuellement. Le débogage de l'application ne montre aucune activité lorsque l'application est en arrière-plan. Alors maintenant, il semble que je n'ai pas configuré l'application pour fonctionner correctement avec Bluetooth en arrière-plan.

Donc, mon intuition est que quelque chose est mal configuré en suivant le document de base CoreBluetooth. Mais il n'y a que quelques étapes et j'ai mis en place chacune d'entre elles. Je m'attendrais launchOptions?[UIApplicationLaunchOptionsBluetoothCentralsKey] à être envoyé à application(_:didFinishLaunchingWithOptions:), mais il n'est jamais envoyé. Et centralManager(_:willRestoreState:) n'est jamais appelé.

J'ai activé l'option "Utilise les accessoires Bluetooth LE".

Uses Bluetooth LE accessories

J'utilise CBCentralManagerOptionRestoreIdentifierKey:

manager = CBCentralManager(delegate: self, queue: nil, options: 
          [CBCentralManagerOptionRestoreIdentifierKey: "TTcentralManageRestoreIdentifier", 
          CBConnectPeripheralOptionNotifyOnDisconnectionKey: NSNumber(bool: true), 
          CBConnectPeripheralOptionNotifyOnConnectionKey: NSNumber(bool: true), 
          CBConnectPeripheralOptionNotifyOnNotificationKey: NSNumber(bool: true)]) 

Je vous abonnant à la notification caractéristique:

func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {   
    if service.UUID.isEqual(CBUUID(string: DEVICE_V2_SERVICE_BUTTON_UUID)) { 
     for characteristic: CBCharacteristic in service.characteristics! { 
      if characteristic.UUID.isEqual(CBUUID(string: DEVICE_V2_CHARACTERISTIC_BUTTON_STATUS_UUID)) { 
       peripheral.setNotifyValue(true, forCharacteristic: characteristic) 
       let device = foundDevices.deviceForPeripheral(peripheral) 
       device?.buttonStatusChar = characteristic 
      } else if characteristic.UUID.isEqual(CBUUID(string: DEVICE_V2_CHARACTERISTIC_NICKNAME_UUID)) { 
       peripheral.readValueForCharacteristic(characteristic) 
      } 
     } 
    } 
    ... 
} 

UIApplicationLaunchOptionsBluetoothCentralsKey est jamais appelé.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
    ... 
    let centralManagerIdentifiers = launchOptions?[UIApplicationLaunchOptionsBluetoothCentralsKey] 
    if centralManagerIdentifiers != nil { 
     print(" ---> centralManagerIdentifiers: \(centralManagerIdentifiers)") 
    } 
    ... 
} 

Enfin, centralManager(_:willRestoreState:) est jamais appelé:

func centralManager(central: CBCentralManager, willRestoreState dict: [String : AnyObject]) { 
    manager = central 
    let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as! [CBPeripheral] 
    print(" ---> Restoring state: \(peripherals)") 
    ... 
} 
+0

Bonjour Samuel Clay. première fois que je travaille sur I balise. dans mon cas "didDiscover périphérique" méthode de délégué ne fonctionne pas alors que l'application est en arrière-plan? et j'ai également activé "bluetooth-central" alors pouvez-vous m'expliquer ce que toutes les choses que je veux faire dans le côté mai? Si cela ne vous dérange pas pouvez-vous me donner votre adresse e-mail? –

Répondre

1

A découvert. Jouons repérer le bug ...

class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate { 

   var window: UIWindow? 
   var bluetoothManager = TTBluetoothManager() 

   func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
       ... 
       return true 
   } 
   ...   
} 

Voir cette ligne var bluetoothManager = TTBluetoothManager()? Ce devrait être un var bluetoothManager: TTBluetoothManager! et bluetoothManager = TTBluetoothManager() devrait être dans application(_:didFinishLaunchingWithOptions:)

Cela a fait l'affaire et maintenant mon appareil Bluetooth fonctionne en arrière-plan.

+0

Je ne comprends toujours pas pourquoi, mais cela a résolu mes problèmes de fond sur iOS 10! Chose amusante, le code ci-dessus permet à mon application de fonctionner en arrière-plan sur iOS 11, alors qu'il a été suspendu tout de suite en utilisant iOS 10 – MikeB

0

Il devrait fonctionner. Ça marche pour moi. Avez-vous fait ce qui suit?

  1. Cochez l'option "Utilise les accessoires Bluetooth LE" en arrière-plan.
  2. Ajout de "CBCentralManagerOptionRestoreIdentifierKey" lors de la création du gestionnaire.
  3. Abonnez-vous aux notifications de caractéristiques en utilisant: setNotifyValue: forCharacteristic :.

Sinon, alors quelque chose ne va pas. Essayez peut-être d'initialiser le gestionnaire sur une file d'attente de répartition dédiée juste pour vous assurer que la file d'attente actuelle est bloquée pour une raison quelconque.

Si vous affichez du code, je pourrais peut-être vous aider. Comme je l'ai dit, je sais pertinemment que cela devrait fonctionner.

/A

+0

Ajout d'exemples de code dans une mise à jour de la question d'origine. –