使用Swift中的CoreLocation通过WKWebView发送位置

时间:2018-10-26 09:52:13

标签: javascript ios swift core-location wkwebview

我正在开发本机Webbrowser,以使Web应用程序与Swift中的核心功能(蓝牙,位置,微型..)交互。本机应用程序托管一个WKWebview来显示Web应用程序的内容,JS通过window.webkit.messageHandlers与WKWebview进行通信。

有一个功能,当位置发生变化时,即使在后台,Web应用程序也会要求本机应用程序检索用户位置。为简单起见,我使用CoreLocation获取位置并将位置发送回WKWebview。 Web应用程序通过窗口侦听器侦听这些事件,然后调用服务器以保存位置。

这在模拟器中运行良好,但是由于某些我不知道的原因,这在真实的iPhone上不起作用。

问题:

  1. 它可以与WKWebview生命周期相关吗?
  2. 位置管理器的配置是否正确,以便不被处于后台状态的操作系统杀死/挂起?
  3. 其他应用程序能否优先获取位置信息并停止我的应用程序获取信息?

任何建议都赞赏

网络应用服务:

this.eventManager.addEventListener(window, 'sendLocalisation', (params : CustomEvent) => {

 let data = params.detail.data;
 let datas = { 'annotations' : data }
  this.sendLocalisation(datas).subscribe( (ans : any ) => {
     ...
  }); 

window.webkit.messageHandlers.JSLocalisation.postMessage("start");

本地快速代码:

// Variables
private var localisationManager : LocalisationManager!

extension JSEventManager : WKScriptMessageHandler {

open func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

    if message.name == "JSLocalisation" {
       self.handleLocalisationEvents(message: message.body as! String) 
    }

 }

func handleLocalisationEvents(message : String) {

    if message == "start" {
        localisationManager.startLocalisation()
    }
}

class LocalisationManager : NSObject {

// Delegation
weak var delegate : LocalisationManagerDelegate?

// Variables
private var locationManager : CLLocationManager!
private var positions : [[String: Any]] = []

override init() {
    super.init()
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.activityType = .other
    locationManager.pausesLocationUpdatesAutomatically = false
}

func startLocalisation() {
    delegate?.didStartLocalisation()
    locationManager.requestAlwaysAuthorization()
}


}

extension LocalisationManager : CLLocationManagerDelegate {

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

    if CLLocationManager.authorizationStatus() == .authorizedAlways {
        startReceivingLocationChanges()
    }

}

func startReceivingLocationChanges() {

    let authorizationStatus = CLLocationManager.authorizationStatus()
    if authorizationStatus != .authorizedWhenInUse && authorizationStatus != .authorizedAlways {
        // User has not authorized access to location information.
        return
    }
    // Do not start services that aren't available.
    if !CLLocationManager.locationServicesEnabled() {
        // Location services is not available.
        return
    }
    // If the user confirms always authorization
    if authorizationStatus == .authorizedAlways {
        locationManager.allowsBackgroundLocationUpdates = true
    }

    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters 
    locationManager.distanceFilter = 40.0  // In meters.
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
}


func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let location = locations[0]

    let timestamp = String(format:"%f", location.timestamp.timeIntervalSince1970*1000)
    let longitude = "\(location.coordinate.longitude)"
    let latitude = "\(location.coordinate.latitude)"

    let position : [String: Any] = ["timestamp" : timestamp, "lon" : longitude, "lat" : latitude,  "timezone" : 0 ]

    self.positions.append(position)

    if self.positions.count == 3 {
        sendCoordinates()
    }
}


func sendCoordinates(){
    let locationsToSend = self.positions
    self.positions = []

    if let stringToSend = json(from:locationsToSend as Any) {
        self.delegate?.shouldSendCoordinates(coordinates: stringToSend)
    }

}

func json(from object:Any) -> String? {
    guard let data = try? JSONSerialization.data(withJSONObject: object, options: []) else {
        return nil
    }
    return String(data: data, encoding: String.Encoding.utf8)
}

}


// shouldSendCoordinates call this function, shortcut not to display all the delegates trough the app 
func sendLocalisation(localisation: String) {
    let str = "window.iOSLocalisationAPI.sendPositions('\(localisation)')"
    self.evaluateJavaScript(str) { (result, error) in
        guard error == nil else {
            print(error)
            return
        }
    }
}

在webwiew中注入了脚本:

(function () {
"use strict";

let geonative = {

    sendPositions : function(positions) {

         var evt = new CustomEvent('sendLocalisation', { detail: { data : positions } });
         window.dispatchEvent(evt);

    }

}

window.iOSLocalisationAPI = geonative;

}());

0 个答案:

没有答案