69 votes

Faire fonctionner l'iPhone comme une iBeacon en arrière-plan

Est-il possible de faire fonctionner un appareil iOS 7 comme un périphérique Bluetooth LE (iBeacon) et de le faire annoncer en arrière-plan ? J'ai réussi à l'annoncer au premier plan avec le code ci-dessous et je peux le voir à partir d'un autre appareil iOS, mais dès que je retourne à l'écran d'accueil, il cesse d'annoncer. J'ai ajouté le mode d'arrière-plan bluetooth-peripheral dans le plist mais cela ne semble pas aider bien que je reçoive l'invite disant que le dispositif veut utiliser le bluetooth en arrière-plan. Est-ce que je fais quelque chose de mal ou est-ce que ce n'est tout simplement pas possible dans iOS 7 ?

peripManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
  if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
      return;
  }

  NSString *identifier = @"MyBeacon";
  //Construct the region
  CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:identifier];

  //Passing nil will use the device default power
  NSDictionary *payload = [beaconRegion peripheralDataWithMeasuredPower:nil];

  //Start advertising
  [peripManager startAdvertising:payload];
}

Voici le code qui se trouve du côté de la réception/écoute :

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons
           inRegion:(CLBeaconRegion *)region
{
//Check if we have moved closer or farther away from the iBeacon…
if (beacons.count > 0) {
    CLBeacon *beacon = [beacons objectAtIndex:0];

    switch (beacon.proximity) {
        case CLProximityImmediate:
            [self log:[NSString stringWithFormat:@"You're Sitting on it! %li", (long)beacon.rssi]];
            break;
        case CLProximityNear:
            [self log:[NSString stringWithFormat:@"Getting Warmer! %li", (long)beacon.rssi]];
            break;
        default:
            [self log:[NSString stringWithFormat:@"It's around here somewhere! %li", (long)beacon.rssi]];
            break;
    }
}
}

49voto

bentford Points 9981

Les annonces standard de CoreBluetooth peuvent être diffusées lorsque l'application est en arrière-plan, mais pas si elles ont été lancées avec l'option CLBeaconRegion dictionnaire. La solution consiste à abandonner complètement le framework CoreLocation et à créer votre propre "framework" de proximité en utilisant uniquement CoreBlueTooth.

Vous devez toujours utiliser les spécificateurs d'arrière-plan appropriés dans le fichier Info.plist (par ex. bluetooth-peripheral y bluetooth-central ).

Le code ressemble à quelque chose comme ceci :

1) créer une annonce périphérique standard en utilisant CBPeripheralManager

NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey:@"my-peripheral",
                                  CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:identifier]]};

// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];

2) utiliser utiliser CBCentralManager pour rechercher ce service en utilisant l'UUID que vous avez spécifié.

NSDictionary *scanOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
NSArray *services = @[[CBUUID UUIDWithString:identifier]];

[centralManager scanForPeripheralsWithServices:services options:scanOptions];

3) dans la CBCentralManagerDelegate méthode didDiscoverPeripheral lire le RSSI la valeur de l'annonce.

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{

    NSLog(@"RSSI: %d", [RSSI intValue]);
}

4) Traduire les valeurs RSSI en distance.

- (INDetectorRange)convertRSSItoINProximity:(NSInteger)proximity
{
    if (proximity < -70)
        return INDetectorRangeFar;
    if (proximity < -55)
        return INDetectorRangeNear;
    if (proximity < 0)
        return INDetectorRangeImmediate;

    return INDetectorRangeUnknown;
}

J'ai découvert que je devais "assouplir" ou "moyenner" les valeurs RSSI pour obtenir quelque chose d'utilisable. C'est la même chose que lorsque vous travaillez avec des données de capteurs (par exemple, des données d'accéléromètre).

J'ai ce concept entièrement travaillé et j'espère le publier quelque part à un moment donné.

Utilisez également le docs (Guide de programmation du Core Bluetooth) si vous êtes bloqué.

Mise à jour : A L'échantillon de code complet est disponible sur Github . J'ai travaillé sur ce sujet dans le cadre d'un projet lié au travail .

Mise à jour n°2 : Apple publie des améliorations majeures du comportement de l'arrière-plan iBeacon pour iOS7.1

4voto

El Vous sentez l'iBeacon ? L'article traite à la fois de l'utilisation d'Estimotes et de la publicité à partir de Macs et d'appareils iOS. Vous devez cocher la capacité "Agit comme un accessoire Bluetooth LE" dans la cible du projet.

2voto

RawMean Points 1761

Non, les appareils iOS ne font de la publicité iBeacon que lorsque l'application qui en est à l'origine fonctionne au premier plan. Ainsi, si vous passez à une autre application ou si l'appareil se met en veille, la publicité s'arrête.

Bien sûr, si vous voulez vraiment que la publicité continue, désactivez le minuteur de veille et faites l'accès guidé pour que l'appareil iOs ne se mette pas en veille et que personne ne puisse passer à une autre application.

1voto

Duncan C Points 18661

J'espère également pouvoir configurer mon application (de test) pour annoncer un iBeacon en arrière-plan. Les documents sur la clé UIBackgroundModes info.plist suggèrent que la clé bluetooth-peripheral pourrait fonctionner, mais il semble que non. (Je viens de le tester il y a quelques minutes).

Ce que je fais pour l'instant, c'est de désactiver la minuterie d'inactivité, comme le suggère RawMean, puis de régler la luminosité de l'écran sur 0. Enfin, lorsque mon application de test agit comme une balise iBeacon, j'ajoute un gestionnaire d'événement de secousse qui rallume l'écran pendant 30 secondes. Le fait de réduire la luminosité de l'écran au maximum permet de réduire quelque peu la consommation de la batterie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X