问题
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:
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
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.
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