Я разрабатываю независимое приложение WatchOS, целью которого является определение того, когда пользователь покидает определенную область c, и, следовательно, отправляет уведомление. Для этого приложение в значительной степени зависит от фоновых обновлений местоположения.
Пока приложение работает нормально. Он выбирает позицию на основе distanceFilter
свойства CLLocationManager
. Проблема в батарее. Подход, который я придерживался, поддерживает фоновые обновления местоположения в действии, даже если они выбираются только тогда, когда определенное c расстояние «покрыто».
Моя идея заключалась в том, чтобы отключить обновление местоположения, когда область покидает пользователь, а также отключить эту службу в ночные часы. Однако я сталкиваюсь с серьезной проблемой при таком подходе.
Моя главная проблема заключается в том, что отключение обновления местоположения в фоновом режиме не позволяет мне возобновить его. Я пытался сделать это с помощью:
- A Timer.
scheduleBackgroundRefresh(withPreferredDate:userInfo:scheduledCompletion:)
метода, вызывающего startLocationUpdates()
в делегате
Ничего не работает. Мой вопрос:
Есть ли способ возобновить фоновые обновления местоположения, если оно было ранее отключено? Заранее спасибо.
ОБНОВЛЕНИЕ n .2: Я пытался выполнить обновление местоположения с помощью WKApplicationRefreshBackgroundTask
, но он просто игнорирует функцию requestLocation()
(предложено @RomuloBM)
//In extension delegate handle() function
case let backgroundTask as WKApplicationRefreshBackgroundTask:
// Be sure to complete the background ta
LocMng = LocationManager() // I even tried to create a new element!
LocMng.LocMng.requestLocation()// it is just ignored
backgroundTask.setTaskCompletedWithSnapshot(false)
Я вызываю фоновую задачу с помощью этой функции в моем LocationManager:
//In didUpdateLocation
if background {
WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: Date(timeIntervalSinceNow: 30), userInfo: nil){ _ in
print("Done")
self.background = false
self.LocMng.stopUpdatingLocation()
}
}
Для справки, вот мой класс LocationManager:
enum ScanningMode {
case Precise
case Normal
}
class LocationManager : NSObject, CLLocationManagerDelegate, UNUserNotificationCenterDelegate, ObservableObject {
let LocMng = CLLocationManager()
let NotMng = UNUserNotificationCenter.current()
var modeOfScanning: ScanningMode!
var region: CLCircularRegion!
var previousLocation: CLLocation!
// variables for position...
override init() {
super.init()
// stuff for my app...
modeOfScanning = .Precise
setupManager()
setupNotification()
startLocalization()
}
private func startLocalization(){
switch modeOfScanning!{
case ScanningMode.Precise:
LocMng.desiredAccuracy = kCLLocationAccuracyBest
LocMng.distanceFilter = 15
case ScanningMode.Normal:
LocMng.desiredAccuracy = kCLLocationAccuracyHundredMeters
LocMng.distanceFilter = 80
}
LocMng.startUpdatingLocation()
}
private func setupManager(){
LocMng.requestAlwaysAuthorization()
LocMng.delegate = self
LocMng.desiredAccuracy = kCLLocationAccuracyBest
}
private func setupNotification(){
NotMng.delegate = self
NotMng.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("NotificationCenter Authorization Granted!")
}
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedAlways{
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
LocMng.allowsBackgroundLocationUpdates = true
// For the sake of clarity, I will cut out this chunk of code and
// just showing how I execute my action based on the result of location
// This is just an example
actualLocation = locations[length-1]
//find if in a forget
if previousLocation != nil{
if !region.contains(actualLocation!.coordinate) && region.contains(previousLocation!.coordinate){
//Schedule notification
LocMng.stopUpdatingLocation() // <- this does not allow me to resume
}
}
previousLocation = actualLocation
}
}