Отправить местоположение через WKWebView, используя CoreLocation в Swift - PullRequest
0 голосов
/ 26 октября 2018

Я разрабатываю собственный веб-браузер, чтобы веб-приложение взаимодействовало с основными функциями (bluetooth, location, micro ...) в Swift.Нативное приложение содержит WKWebview для отображения содержимого веб-приложения, JS связывается через window.webkit.messageHandlers с WKWebview.

Существует функция, при которой веб-приложение запрашивает собственное приложение для получения местоположения пользователя при изменении положения, даже в фоновом режиме.Чтобы упростить процесс, я использую CoreLocation, чтобы получить местоположение и отправить его обратно в WKWebview.Веб-приложение прослушивает эти события через оконные прослушиватели и вызывает сервер, чтобы сохранить местоположение.

Это хорошо работает в симуляторе, но по некоторым причинам, о которых я не знаю, это не работает на реальном 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;

}());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...