Cordova:在后台模式下扫描iBeacons / BLE(iOS和Android)

时间:2015-09-21 13:57:06

标签: cordova phonegap-plugins bluetooth-lowenergy cordova-plugins ibeacon

我已经实现了一个cordova /离子应用程序(iOS / Android混合应用程序),可以在后台模式下扫描iBeacons,并在找到信标时通知用户。我正在使用以下插件:

  • iBeacon扫描: cordova-plugin-ibeacon by petermetz
  • 背景模式: katzer
  • cordova-plugin-background-mode
  • 通知:katzer cordova-plugin-local-notifications

到目前为止(在iOS和Android上都有效)。这里的问题是,Apple会拒绝我的App表单发布到App Store(参见https://github.com/katzer/cordova-plugin-background-mode/issues/77)。 另一个问题是,背景信标扫描似乎消耗了非常多的电池容量。使用此背景插件,完整的应用程序在后台运行,而不仅仅是特定的功能/服务。

你是否有人知道是否有一个插件可以在后台运行任务(或者更具体一点:在后台扫描iBeacons),它可以在iOS和Android上运行,并且会被App Store接受吗?我还没找到。如果没有这样的插件,您认为通常可以开发这样的插件吗?据我所知,后台服务适用于Android和iOS(本机)。

谢谢!

3 个答案:

答案 0 :(得分:1)

说到iOS,这不是特定于Cordova的问题。 Apple不允许在后台对信标进行测距(扫描)超过几分钟,而无需特殊权限,需要额外的障碍才能在AppStore中获得批准。为了在AppStore中获得批准,并对信标进行持续的后台扫描,您必须说服Apple,您的应用程序是导航应用程序。 Read more here.

至于电池使用情况,是的,信标的恒定范围会显着耗尽电池电量。这就是为什么Apple通常不允许应用程序在后台执行此操作。另一种方法是使用信标监控API而不是信标测距API。当信标出现或消失时,监控API会向您发出警报,并使用硬件辅助或仅定期蓝牙扫描来节省电量。

在后台处理方面存在特定的Cordova复杂性(主要是由于需要WebView处理活动来处理回调),但如果您计划部署到AppStore,则必须首先解决更基本的问题上方。

答案 1 :(得分:1)

我也面临同样的问题。我不是本机应用程序开发人员,但我知道将所有这三个插件组合在一起就可以得到理想的结果。

我的概念是在信标从应用程序后台模式中的区域移动时通知移动设备。

-Naitik

答案 2 :(得分:0)

对于延迟回复表示歉意。几个月前我遇到了同样的问题但没有找到答案:(我只是愿意分享我的发现

你可以使用你的cordova插件只担心Android设备。对于iOS,您可以使用beacon monitoring api。

您只需要在xCode上导入cordoba项目

您将在项目内找到一个名为AppDelegate.swift的文件 在类初始化之前把这个

import CoreLocation

在类初始化之后,你需要输入像这样的变量

class AppDelegate: UIResponder, UIApplicationDelegate {
    var beaconManager:CLLocationManager!
    var region:CLBeaconRegion!

现在按下命令+ N或转到文件>新>档案

创建一个新的swift文件,单击下一步并给出我的名字

使用此

更改文件内容
import Foundation
import CoreLocation
import UserNotifications

extension AppDelegate:CLLocationManagerDelegate{
//here we will initialize our beacon monitoring manager, 
//we will call this function later on the AppDelegate Main class
func initBeaconManager(){
    //remember whe have defined our locationManager and region variable on AppDelegate Main Class
    locationManager: CLLocationManager = CLLocationManager()
    locationManager.delegate = self

    //you will need to change these variables according to your becon configuration
    let uuid = UUID(uuidString: "CHANGE ME YOUR BEACON UUID IF YOU DONT CHANGE IT IT WILL CRASH")!
    let major = 123 //beacon major
    let minor = 012 // beacon minor
    let identifier = "some indentifier of your region that you like"

    //you can define your region with just the uuid that way if you have more that one beacon it will work with just one region
    //uncomment below if that´s the case
    //let region = CLBeaconRegion(proximityUUID: uuid, identifier: identifier)

    //in this case we will be ussing all variables major minor and uuid
    region = CLBeaconRegion(proximityUUID: uuid, major: CLBeaconMajorValue(major), minor: CLBeaconMinorValue(minor), identifier: identifier)

    //great now that we have defined our region we will start monitoring on that region
    //first of all we make sure we have the correct permissions
    let authorization = CLLocationManager.authorizationStatus()
    switch authorization {
    case .notDetermined:
        //in case it is not authorized yet we will ask here for authorization
        //the key is to request always authorization that way the enter and exit region callbacks will be called even if the app is killed or the phone restarted
        locationManager.requestAlwaysAuthorization()
        //after requesting for ahtorization we will get the authorization changed callback, there will be starting monitoring our region
    case .denied, .restricted ,.authorizedWhenInUse:
        //the user has denied the authorization we can make the user go to settings and enable it again 
        //but you can do that also ussing cordoba so... I just put in this case switch to commit that :D
        break
    case .authorizedAlways:
        //we are goot to go now we can start monitoring
        locationManager.startMonitoring(for: region)
    }


    if let uuid = UUID(uuidString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D") {
        let beaconRegion = CLBeaconRegion(
            proximityUUID: uuid,
            major: 100,
            minor: 50,
            identifier: "iBeacon")
        locationManager.startMonitoring(for: beaconRegion)
    }
}


//LOCATOIN MANAGER EXIT AND ENTER REGION
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
    //notification when enter
    let notificationTitle = "CHANGE ME"
    let notificationBody = "CHANGE ME ENTER REGION"
    sendNotification(title: notificationTitle, body: notificationBody)
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
    //notification when leave 
    let notificationTitle = "CHANGE ME"
    let notificationBody = "CHANGE ME EXIT REGION"
    sendNotification(title: notificationTitle, body: notificationBody)
}



//Simple notification with only a custom title and body
func sendNotification(title:String,body:String){
    if #available(iOS 10.0, *) {
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = body
        content.sound = UNNotificationSound.default()
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
        let request = UNNotificationRequest(identifier: "enterNotification", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
            // Handle error
        })
    } else {
        let notification = UILocalNotification()
        if #available(iOS 8.2, *) {
            notification.alertTitle = title
        }
        notification.alertBody = body
        notification.soundName = UILocalNotificationDefaultSoundName
        UIApplication.shared.presentLocalNotificationNow(notification)
    }

}
}

在文件评论中,您可以找到需要更改的地方

现在返回AppDelegate文件并将其放在函数

func application(_ application: UIApplication, didFinishLaunchingWithOptions ....

这将初始化您在扩展程序上的所有功能

self.initBeaconManager()