it-swarm.com.de

Führen Sie das iPhone als iBeacon im Hintergrund aus

Ist es möglich, ein iOS 7-Gerät als Bluetooth LE-Peripheriegerät (iBeacon) zu betreiben und im Hintergrund werben zu lassen? Ich konnte es mit dem folgenden Code im Vordergrund bewerben und kann es von einem anderen iOS-Gerät aus sehen, aber sobald ich zum Startbildschirm zurückkehre, wird keine Werbung mehr gemacht. Ich habe den Bluetooth-Peripherie-Hintergrundmodus in der plist hinzugefügt, aber das schien nicht zu helfen, obwohl ich die Aufforderung bekomme, die besagt, dass das Gerät Bluetooth im Hintergrund verwenden möchte. Mache ich etwas falsch oder ist das in iOS 7 nicht möglich?

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

Hier ist der Code, der sich am Empfang/Abhören befindet:

- (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;
    }
}
}
67
jpcoder

Standard-CoreBluetooth-Ankündigungen können übertragen werden, während sich die App im Hintergrund befindet, jedoch nicht, wenn sie mit CLBeaconRegion dictionary gestartet wurden. Die Problemumgehung besteht darin, das CoreLocation-Framework vollständig aufzuheben und ein eigenes Proximity-Framework zu erstellen, das nur CoreBlueTooth verwendet.

Sie müssen weiterhin die entsprechenden Hintergrundbezeichner in der Info.plist-Datei verwenden (z. B. bluetooth-peripheral und bluetooth-central).

Der Code sieht ungefähr so ​​aus:

1) Erstellen Sie eine Standard-Werbung für Peripheriegeräte mit CBPeripheralManager.

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

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

2) Verwenden Sie CBCentralManager, um mit der von Ihnen angegebenen UUID nach diesem Dienst zu suchen.

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

[centralManager scanForPeripheralsWithServices:services options:scanOptions];

3) Lesen Sie in der CBCentralManagerDelegate-Methode didDiscoverPeripheral den RSSI-Wert der Ankündigung. 

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

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

4) Übersetzen Sie die RSSI-Werte in eine Entfernung.

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

    return INDetectorRangeUnknown;
}

Ich stellte fest, dass ich die RSSI-Werte "erleichtern" oder "mitteln" musste, um alles brauchbar zu machen. Dies ist nicht anders als bei der Arbeit mit Sensordaten (z. B. Beschleunigungsmesserdaten).

Ich habe dieses Konzept voll in der Hoffnung, es irgendwann irgendwo zu veröffentlichen.

Verwenden Sie auch das docs (Core Bluetooth-Programmierhandbuch), wenn Sie nicht weiterkommen.

Update: A vollständiger Codebeispiel ist auf Github verfügbar . Ich habe daran als Teil eines arbeitsbezogenen Projekts gearbeitet.

Update # 2: _ ​​ Apple veröffentlicht wichtige Verbesserungen des Hintergrundverhaltens von iBeacon für iOS7.1

47
bentford

Das Kannst du das iBeacon riechen? Der Artikel beschreibt sowohl die Verwendung von Estimotes als auch die Werbung von Macs und iOS-Geräten. Sie müssen die Funktion "Dient als Bluetooth LE-Zubehör" im Projektziel aktiviert.

Nein, iOS-Geräte werben für iBeacon nur dann, wenn die app, die die Werbung macht, im Vordergrund läuft. Wenn Sie also zu einer anderen App wechseln oder das Gerät in den Ruhezustand wechselt, wird die Ankündigung gestoppt.

Wenn Sie die Ankündigung wirklich fortsetzen möchten, deaktivieren Sie den Leerlauf-Timer und führen Sie Guided Access aus, damit das iOs-Gerät nicht in den Ruhezustand wechselt und niemand zu einer anderen App wechseln kann.

2
RawMean

Ich hoffe auch, dass ich meine (Test-) App einrichten kann, um einen iBeacon aus dem Hintergrund zu bewerben. Die Dokumente auf dem UIBackgroundModes-Schlüssel info.plist legen nahe, dass der Bluetooth-Peripherie-Schlüssel möglicherweise funktioniert, aber es scheint nicht so zu sein. (Ich habe es vor ein paar Minuten getestet.)

Was ich jetzt mache, ist die Einstellung des Leerlauf-Timers auf deaktiviert, wie von RawMean vorgeschlagen, und dann die Bildschirmhelligkeit auf 0 setzen. Wenn meine Test-App als iBeacon fungiert, füge ich einen Shake-Ereignishandler hinzu, der den Bildschirm beleuchtet 30 Sekunden lang wieder hochfahren. Wenn Sie den Bildschirm so weit dimmen, wie er geht, können Sie den Batterieverbrauch etwas verringern.

1
Duncan C

Das kann gemacht werden. Ich möchte nicht, dass Apple-Ingenieure vor meiner Haustür wütend sind, also werde ich den Algorithmus nicht veröffentlichen.

Zusammenfassend ist der overflow-Bereich , der die Service-UUIDs codiert, nur eine Reihe von Bytes, die über Funk gesendet werden. Sie können es selbst schnüffeln. Es ist insbesondere ein kurzer Hash, der anschließend durch eine One-Hot-Codierung dargestellt wird. Mehrere UUIDs werden kommuniziert, indem mehrere Bits gesetzt werden. Sie werden auf diese Weise Kollisionen haben. Beispielsweise hat die UUID 1001 die gleiche Kodierung wie 3333. Sie können dies selbst überprüfen: Heben Sie eine UUID 1001 für das iPhone im Hintergrund ab und lassen Sie die andere nach 3333 suchen.

0
Anne van Rossum