20260112-01
This commit is contained in:
parent
f553ff9e53
commit
d9292c3fc7
@ -47,11 +47,5 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string>We use your location to provide real-time positioning.</string>
|
<string>We use your location to provide real-time positioning.</string>
|
||||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
||||||
<string>We use your location to provide real-time positioning, even in the background.</string>
|
|
||||||
<key>UIBackgroundModes</key>
|
|
||||||
<array>
|
|
||||||
<string>location</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -161,15 +161,8 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func startBackgroundTracking() {
|
public func startBackgroundTracking() {
|
||||||
backgroundTrackingActive = true
|
// Background tracking disabled on iOS to avoid background location reporting.
|
||||||
if #available(iOS 9.0, *) {
|
backgroundTrackingActive = false
|
||||||
locationManager.allowsBackgroundLocationUpdates = true
|
|
||||||
}
|
|
||||||
if #available(iOS 11.0, *) {
|
|
||||||
locationManager.showsBackgroundLocationIndicator = true
|
|
||||||
}
|
|
||||||
locationManager.pausesLocationUpdatesAutomatically = false
|
|
||||||
locationManager.startUpdatingLocation()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func stopBackgroundTracking() {
|
public func stopBackgroundTracking() {
|
||||||
@ -184,7 +177,12 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func isBackgroundTrackingActive() -> Bool {
|
public func isBackgroundTrackingActive() -> Bool {
|
||||||
return backgroundTrackingActive
|
// iOS only tracks in foreground; expose active tracking state for API parity.
|
||||||
|
return backgroundTrackingActive || foregroundTrackingActive
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isForegroundTrackingActive() -> Bool {
|
||||||
|
return foregroundTrackingActive
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setAuthTokens(accessToken: String, refreshToken: String) {
|
public func setAuthTokens(accessToken: String, refreshToken: String) {
|
||||||
@ -225,10 +223,6 @@ import UIKit
|
|||||||
latestTimestampMs = location.timestamp.timeIntervalSince1970 * 1000.0
|
latestTimestampMs = location.timestamp.timeIntervalSince1970 * 1000.0
|
||||||
backgroundLatestLocation = location
|
backgroundLatestLocation = location
|
||||||
|
|
||||||
if backgroundTrackingActive {
|
|
||||||
postFixIfNeeded(location)
|
|
||||||
}
|
|
||||||
|
|
||||||
emitPositionUpdate(from: location, forceEmit: false)
|
emitPositionUpdate(from: location, forceEmit: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,39 +415,4 @@ import UIKit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func postFixIfNeeded(_ location: CLLocation) {
|
|
||||||
guard let urlString = getBackgroundPostUrl(), let url = URL(string: urlString) else { return }
|
|
||||||
|
|
||||||
let nowMs = Date().timeIntervalSince1970 * 1000.0
|
|
||||||
if nowMs - lastPostAttemptMs < backgroundMinPostIntervalMs {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if location.horizontalAccuracy > backgroundPostMinAccuracyMeters {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let lastPosted = lastPostedLocation {
|
|
||||||
let dist = location.distance(from: lastPosted)
|
|
||||||
if dist < backgroundPostMinDistanceMeters {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPostAttemptMs = nowMs
|
|
||||||
let payload = buildPositionData(from: location)
|
|
||||||
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
||||||
if let token = defaults.string(forKey: accessTokenKey) {
|
|
||||||
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
|
||||||
}
|
|
||||||
|
|
||||||
request.httpBody = try? JSONSerialization.data(withJSONObject: payload, options: [])
|
|
||||||
|
|
||||||
URLSession.shared.dataTask(with: request) { [weak self] _, _, _ in
|
|
||||||
self?.lastPostedLocation = location
|
|
||||||
}.resume()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class DumonGeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
private let implementation = DumonGeolocation()
|
private let implementation = DumonGeolocation()
|
||||||
private var pendingPermissionCall: CAPPluginCall?
|
private var pendingPermissionCall: CAPPluginCall?
|
||||||
private var pendingBackgroundCall: CAPPluginCall?
|
private var pendingBackgroundCall: CAPPluginCall?
|
||||||
|
private var backgroundMappedToForeground = false
|
||||||
|
|
||||||
public override func load() {
|
public override func load() {
|
||||||
implementation.onPositionUpdate = { [weak self] data in
|
implementation.onPositionUpdate = { [weak self] data in
|
||||||
@ -99,21 +100,26 @@ public class DumonGeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func startBackgroundTracking(_ call: CAPPluginCall) {
|
@objc func startBackgroundTracking(_ call: CAPPluginCall) {
|
||||||
if let postUrl = call.getString("postUrl") {
|
// iOS only supports foreground tracking; reuse foreground flow.
|
||||||
implementation.setBackgroundPostUrl(postUrl)
|
|
||||||
}
|
|
||||||
let status = implementation.authorizationStatus()
|
let status = implementation.authorizationStatus()
|
||||||
if status == .authorizedAlways {
|
if !isLocationAuthorized(status) {
|
||||||
implementation.startBackgroundTracking()
|
call.reject("Location permission not granted")
|
||||||
call.resolve()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pendingBackgroundCall = call
|
if !implementation.isForegroundTrackingActive() {
|
||||||
implementation.requestAlwaysPermission()
|
implementation.startPositioning()
|
||||||
|
backgroundMappedToForeground = true
|
||||||
|
} else {
|
||||||
|
backgroundMappedToForeground = false
|
||||||
|
}
|
||||||
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func stopBackgroundTracking(_ call: CAPPluginCall) {
|
@objc func stopBackgroundTracking(_ call: CAPPluginCall) {
|
||||||
implementation.stopBackgroundTracking()
|
if backgroundMappedToForeground && implementation.isForegroundTrackingActive() {
|
||||||
|
implementation.stopPositioning()
|
||||||
|
}
|
||||||
|
backgroundMappedToForeground = false
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dumon-geolocation",
|
"name": "dumon-geolocation",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
||||||
"main": "dist/plugin.cjs.js",
|
"main": "dist/plugin.cjs.js",
|
||||||
"module": "dist/esm/index.js",
|
"module": "dist/esm/index.js",
|
||||||
|
|||||||
@ -110,7 +110,7 @@ export interface DumonGeolocationPlugin {
|
|||||||
setOptions(options: DumonGeoOptions): Promise<void>;
|
setOptions(options: DumonGeoOptions): Promise<void>;
|
||||||
getGnssStatus(): Promise<SatelliteStatus | null>;
|
getGnssStatus(): Promise<SatelliteStatus | null>;
|
||||||
getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;
|
getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;
|
||||||
// Background tracking (Android)
|
// Background tracking (Android; iOS maps to foreground tracking only)
|
||||||
startBackgroundTracking(options?: {
|
startBackgroundTracking(options?: {
|
||||||
title?: string;
|
title?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user