how to advertise in the background as a beacon when entering a beacon region

随声附和 提交于 2019-12-11 06:26:13

问题


I'm currently working on developing an app that is heavily dependent on iBceaons.

I managed to create a beacon region which wakes up the app process in the background for 10 seconds when entering the region.

The next step is making phone it self advertise when it enters the region while in background

Currently while the app is open it keeps ranging and transmits as a beacon while its in a region
where as when the app is in the background , it ranges for 10 seconds but doesn't transmit as a beacon when it enters a region

so is there a way to allow the phone to transmit as a beacon when its in the background when it enters a region ?

I already had a look into Apple's background Bluetooth which mentioned that the advertising packet is differs when transmitting in the background. I have also looked at This Solution but this solution doesn't use core location so it can't wake the app when entering a region

import UIKit
import CoreLocation
import CoreBluetooth
class ViewController: 
UIViewController,CLLocationManagerDelegate,CBPeripheralManagerDelegate {

var locationManager: CLLocationManager!
var localBeacon: CLBeaconRegion!
var beaconPeripheralData: NSDictionary!
var peripheralManager: CBPeripheralManager!

let myCustomServiceUUID = CBUUID(string:"5A4BCFCE-174E-4BAC-A814-092E77F6B7E5")

override func viewDidLoad() {
    super.viewDidLoad()
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()

    }


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == .authorizedAlways {
        if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
            if CLLocationManager.isRangingAvailable() {
                startScanning()
            }
        }
    }
}

func startScanning() {
    let uuid = UUID(uuidString: "48de4980-968d-11e4-b4a9-0800200c9a66")!
    let beaconRegion = CLBeaconRegion(proximityUUID: uuid, major: 1, minor: 1, identifier: "region1")
       beaconRegion.notifyEntryStateOnDisplay=true;
    locationManager.startMonitoring(for: beaconRegion)
    locationManager.startRangingBeacons(in: beaconRegion)
}

func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {

    if(beacons.count > 0) {
        let nearestBeacon:CLBeacon = beacons[0] as CLBeacon

    NSLog("RSSI value is %ld", nearestBeacon.rssi);
        initLocalBeacon() // Here I'm transmitting as a beacon along with ranging when entering or within a region  which works fine the app is open but not transmitting while in background 



    }
}

func locationManager(_ manager: CLLocationManager,didDetermineState state: CLRegionState,for region: CLRegion)    {

    switch state {
    case .inside:
        NSLog("locationManager didDetermineState INSIDE  %@", region.identifier);


    case .outside:
        NSLog("locationManager didDetermineState OUTSIDE  %@", region.identifier);

    case .unknown:
        NSLog("locationManager didDetermineState OTHER  %@", region.identifier);

    }
}

func initLocalBeacon() {
    if localBeacon != nil {
        stopLocalBeacon()
    }

    let localBeaconUUID = "5A4BCFCE-174E-4BAC-A814-092E77F6B7E5"
    let localBeaconMajor: CLBeaconMajorValue = 2
    let localBeaconMinor: CLBeaconMinorValue = 1

    let uuid = UUID(uuidString: localBeaconUUID)!
    localBeacon = CLBeaconRegion(proximityUUID: uuid, major: localBeaconMajor, minor: localBeaconMinor, identifier: "identifer here")

    beaconPeripheralData = localBeacon.peripheralData(withMeasuredPower: -59)
    peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}

func stopLocalBeacon() {
    peripheralManager.stopAdvertising()
    peripheralManager = nil
    beaconPeripheralData = nil
    localBeacon = nil
}

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
    if peripheral.state == .poweredOn {
        peripheralManager.startAdvertising(beaconPeripheralData as! [String: AnyObject]!)
    } else if peripheral.state == .poweredOff {
        //peripheralManager.stopAdvertising()
    }
}
}

I have the act as a BLE Accessory selected in the background modes in capabilities and the Privacy - Bluetooth Peripheral Usage Description added in the playlist


回答1:


Sorry, iOS will not let your app advertise a BLE packet matching the iBeacon spec when it is in the background. As you have mentioned in your question, Apple alters the way background advertisements emitted in the background look, and as a result, they will not trigger CoreLocation enter events to wake up receiving apps in the background.

There are a few imperfect alternatives:

  1. You can use other beacon advertisements in the background and wake up your app. This won't be as quick as iBeacon, but it will wake up your app within a few minutes. Here is a setup that does that: https://github.com/Decemberlabs/AltBeacon

  2. You can advertise iBeacon whenever the app is in the foreground, and try to get the user to bring the app to the foreground through a local notification.

  3. If there are other foreground copies of your app in the vicinity (based on background beacon detection), you can use a web service to notify them of your presence during the 10 seconds your app runs in the background. This notification can tell them to start advertising on your behalf.



来源:https://stackoverflow.com/questions/45840606/how-to-advertise-in-the-background-as-a-beacon-when-entering-a-beacon-region

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!