应用程序在后台 ios 中时地理围栏不起作用

Posted

技术标签:

【中文标题】应用程序在后台 ios 中时地理围栏不起作用【英文标题】:Geofence not working while app is in background ios 【发布时间】:2019-06-04 06:18:56 【问题描述】:

我正在尝试为我的应用程序进行地理围栏。当我的应用程序正在运行并且我模拟位置时。它收到了地理围栏,但是当它在后台时它没有收到任何地理围栏。 (我已按照本教程进行地理围栏Geofencing with core location

但我正在使用谷歌地图根据要求显示地图)

有我的AppDelegate的代码

import GoogleMaps
import GooglePlaces
import UserNotifications
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate 

var window: UIWindow?
let locationManager = CLLocationManager()
private let BLE_UUID_NUS_SERVICE = CBUUID(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E")//Nordic UART Service
private let BLE_UUID_NUS_RX_CHARACTERISTIC = CBUUID(string: "6E400002-B5A3-F393-E0A9-E50E24DCCA9E") //write
private let BLE_UUID_NUS_TX_CHARACTERISTIC = CBUUID(string: "6E400003-B5A3-F393-E0A9-E50E24DCCA9E") // notify

var centralManager:CBCentralManager? = nil
var currentLuminKeyIdentifire = ""
var lumnKeyPeripheral:CBPeripheral? = nil
var Rx_Write_Characteristic:CBCharacteristic? = nil
var Tx_Notify_Characteristic:CBCharacteristic? = nil

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

   // location manager delegage
    GMSServices.provideAPIKey(Constant.googleApiKey)
    GMSPlacesClient.provideAPIKey(Constant.googleApiKey)
    locationManager.requestAlwaysAuthorization()
    locationManager.delegate = self
    let options: UNAuthorizationOptions = [.badge, .sound, .alert]
    UNUserNotificationCenter.current()
        .requestAuthorization(options: options)  success, error in
            if let error = error 
                print("Error: \(error)")
            
    

    return true


func applicationWillResignActive(_ application: UIApplication) 
    print("AppDelegate Application applicationWillResignActive")

func applicationDidEnterBackground(_ application: UIApplication) 
    print("AppDelegate Application applicationDidEnterBackground ")


func applicationWillEnterForeground(_ application: UIApplication) 
    print("AppDelegate Application applicationWillEnterForeground ")


func applicationDidBecomeActive(_ application: UIApplication) 

    application.applicationIconBadgeNumber = 0
    UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
    UNUserNotificationCenter.current().removeAllDeliveredNotifications()
    print("AppDelegate Application applicationDidBecomeActive ")
    ReachabilityManager.shared.startMonitoring()



func applicationWillTerminate(_ application: UIApplication) 
    print("AppDelegate Application applicationWillTerminate ")

func handleEvent(for region: CLRegion!) 
    //         currentLuminKeyIdentifire = region.identifier
    //
    //         self.centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey : NSNumber(value: true)])
    //
    //        print("AppDelegate Geofence triggered! and \(currentLuminKeyIdentifire)")


    if UIApplication.shared.applicationState == .active 
        print("Active")
     else 
        // Otherwise present a local notification
        let notificationContent = UNMutableNotificationContent()
        notificationContent.body = "Geo fence Triggred for lumin key"
        notificationContent.sound = UNNotificationSound.default
        notificationContent.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
        let request = UNNotificationRequest(identifier: "location_change_geofence",
                                            content: notificationContent,
                                            trigger: trigger)
        UNUserNotificationCenter.current().add(request)  error in
            if let error = error 
                print("Error: \(error)")
            
        
    

extension AppDelegate: CLLocationManagerDelegate 
func locationManager(_ manager: CLLocationManager, didEnterRegion 
region: CLRegion) 
    if region is CLCircularRegion 
        handleEvent(for: region)
    

extension AppDelegate:CBCentralManagerDelegate 

//start of central Manager Did update
func centralManagerDidUpdateState(_ central: CBCentralManager) 
    switch central.state 
    case .unknown:
        print("AppDelegate central.state is .unknown")

    case .resetting:
        print("AppDelegate central.state is .resetting")
    case .unsupported:
        print("AppDelegate central.state is .unsupported")

    case .unauthorized:
        print("AppDelegate central.state is .unauthorized")

    case .poweredOff:

        //            self.scheduleNotification(title: "Lumin Key Geofence",
        //                                      message: "Bluetooth is off ,Turn on for furthur ")
        print("AppDelegate central.state is .poweredOff")
        // send notification

    case .poweredOn:
        // scanBLEDevices()
        print("AppDelegate central.state is .poweredOn")
        if(!currentLuminKeyIdentifire.isEmpty)
            let  peripheralUUID = UUID(uuidString:currentLuminKeyIdentifire) ?? UUID()
            print("AppDelegate peripheralUUID = \(peripheralUUID)")

            let perif =  central.retrievePeripherals(withIdentifiers:[peripheralUUID])
            if(perif.count > 0)
                for cbPeripheral in perif
                    if(cbPeripheral.identifier.uuidString == currentLuminKeyIdentifire)

                        lumnKeyPeripheral = cbPeripheral
                        lumnKeyPeripheral?.delegate = self

                        //  connect to lumin key
                        centralManager?.connect(self.lumnKeyPeripheral!)
                        break
                    
                

            else
                print("AppDelegate No retrievePeripherals :(")
            


        



    




//End of central Manager Did update

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) 
    //        toast(message: "Found bles didDiscover ")
    //
    //        // show list of peripherals
    //        // get these peripheral
    //        self.lumnKeyPeripheral=peripheral
    //
    //        self.lumnKeyPeripheral?.delegate = self
    //        // stop scanning
    //        centralManager?.stopScan()
    //        // connect to lumin key
    //        centralManager?.connect(self.lumnKeyPeripheral!)

    print(peripheral)


func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) 

    //todo handle this error
    print(error ?? "problem")
    //        if(error != nil)
    //            self.isKeyConnected = false
    //        


func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) 

    //        toast(message: "Connected")
    //        self.isKeyConnected = true

    lumnKeyPeripheral?.discoverServices([BLE_UUID_NUS_SERVICE])

扩展 AppDelegate:CBPeripheralDelegate

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) 
    //        toast(message: "In peripherals")


    guard let services=peripheral.services   else return

    for service in services
        peripheral.discoverCharacteristics([BLE_UUID_NUS_RX_CHARACTERISTIC,
                                            BLE_UUID_NUS_TX_CHARACTERISTIC], for: service)
        //            peripheral.discoverCharacteristics(nil, for: service)
    


func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service:
    CBService, error: Error?) 
    guard let characteristics = service.characteristics else  return 

    for characteristic in characteristics 
        print(characteristic)

        // check if it contains write characteristic
        if characteristic.properties.contains(.read) 
            print("\(characteristic.uuid): properties contains .read")
            // this does not contain any read charateristic
            peripheral.readValue(for: characteristic)

        
        if characteristic.properties.contains(.notify) 
            print("\(characteristic.uuid): properties contains .notify")
            // this also does not notify so this is un used
            // peripheral.setNotifyValue(true, for: characteristic)

        
        if characteristic.properties.contains(.write) 
            Rx_Write_Characteristic = characteristic

            BleCommandUtil.sendColorCommadToKey(color: UIColor.hexStringToUIColor(hex:AppUserDefaults.getselectedColorHex())    ,
                                                lumnKeyPeripheral: lumnKeyPeripheral,
                                                Rx_Write_Characteristic: self.Rx_Write_Characteristic!,
                                                isRandomColor: AppUserDefaults.getRandomColorToggle(),
                                                isPowerSave: AppUserDefaults.getPowerSaveToggle())
        
    


func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) 
    switch characteristic.uuid 
    case BLE_UUID_NUS_TX_CHARACTERISTIC:
        print(characteristic.value ?? "no value")
    default:
        print("AppDelegate Unhandled Characteristic UUID: \(characteristic.uuid)")
    

开始监控功能

func startMonitoring(geotification: Geotification) 
    // 1
    if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) 
        self.toast(message: "Geofencing is not supported on this device!")
        return
    
    // 2
    if CLLocationManager.authorizationStatus() != .authorizedAlways 
        let message = "Your geotification is saved but will only be activated once you grant Geotify permission to access the device location."

        self.toast(message: message)

    
    // 3
    let fenceRegion = region(with: geotification)
    // 4
    loacationManager.startMonitoring(for: fenceRegion)

我无法识别问题。我注意到如果我运行 Geofencing with core location 的 Finished 示例代码并单击 iPhone 上的主页按钮,则 AppDelegate 的 func applicationWillTerminate(_ application: UIApplication) 不会被调用,但是当我运行时我的应用程序调用它。我做错了什么?如何解决这个问题

【问题讨论】:

【参考方案1】:

您是否已在项目设置的“功能”选项卡上启用“后台模式”并选中“位置更新”复选框?如果没有,那么你可以在后台模式下获取更新位置。

【讨论】:

我检查了位置更新,但同样无法正常工作【参考方案2】:

我已经解决了这个问题,问题是 info.list 有 uiapplicationexitsonsuspend = yes 。我删除了它,现在它工作正常

【讨论】:

以上是关于应用程序在后台 ios 中时地理围栏不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在后台服务中创建地理围栏

iOS 5 中来自后台地理围栏的通知?

iOS 7.1 地理围栏和 iBeacons 停止工作

关闭应用程序时的 iOS 7.1 CoreLocation 和地理围栏

应用程序在后台时未触发地理围栏通知

在后台应用程序时不会触发地理围栏通知