@tokamakdev/plugin-location 0.1.0-beta.127 → 0.1.0-beta.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -8
- package/android/LocationPlugin.kt +26 -5
- package/android/LocationPositions.kt +52 -0
- package/apple/LocationEvents.swift +9 -0
- package/apple/LocationPlugin.swift +22 -12
- package/apple/LocationPositions.swift +49 -0
- package/package.json +3 -5
- package/src/errors.ts +0 -17
- package/src/index.ts +10 -23
- package/tokamak-plugin.json +3 -20
- package/android/Bindings.kt +0 -997
- package/android/bindings.ts +0 -4150
- package/apple/Bindings.swift +0 -1059
- package/apple/bindings.ts +0 -1314
- package/src/android.ts +0 -150
- package/src/apple.ts +0 -117
package/README.md
CHANGED
|
@@ -254,14 +254,6 @@ The web uses `navigator.geolocation`. `permission()` reports `inUse` from the
|
|
|
254
254
|
Permissions API, and the other additions reject with `NotSupportedError`,
|
|
255
255
|
including the event-stream methods. Native support is provided on Apple and Android.
|
|
256
256
|
|
|
257
|
-
## Platform bindings
|
|
258
|
-
|
|
259
|
-
`@tokamakdev/plugin-location/apple` is Core Location, and
|
|
260
|
-
`@tokamakdev/plugin-location/android` is `android.location` with the
|
|
261
|
-
`Context`, `CancellationSignal`, `SystemClock`, `Executor` and `Consumer`
|
|
262
|
-
types it uses, for Worker code that needs what this API does not offer.
|
|
263
|
-
`getCurrentPosition` and `watchPosition` are built on them.
|
|
264
|
-
|
|
265
257
|
## Errors
|
|
266
258
|
|
|
267
259
|
Rejections and `onLocationError` events are `DOMException` names:
|
|
@@ -45,6 +45,7 @@ class TokamakLocationPlugin(
|
|
|
45
45
|
private val significantChanges = LocationUpdates(context, LocationUpdates.SIGNIFICANT_CHANGES)
|
|
46
46
|
private val regions = LocationRegions(context)
|
|
47
47
|
private val events = LocationEvents(host)
|
|
48
|
+
private val positions = LocationPositions(context, manager)
|
|
48
49
|
|
|
49
50
|
/** Whether the provider was on when last reported, as each request reports its changes. */
|
|
50
51
|
private var providerEnabled = true
|
|
@@ -67,6 +68,8 @@ class TokamakLocationPlugin(
|
|
|
67
68
|
override fun call(method: String, arguments: Any?, reply: TokamakPluginReply): (() -> Unit)? {
|
|
68
69
|
when (method) {
|
|
69
70
|
"setup" -> setup(requireObject(arguments), reply)
|
|
71
|
+
"recentPosition" -> reply(Result.success(recentPosition(requireObject(arguments))))
|
|
72
|
+
"currentPosition" -> return currentPosition(reply)
|
|
70
73
|
"permission" -> reply(Result.success(permission()))
|
|
71
74
|
"requestPermission" -> requestPermission(requireObject(arguments), reply)
|
|
72
75
|
"servicesEnabled" -> reply(Result.success(manager.isLocationEnabled))
|
|
@@ -92,12 +95,30 @@ class TokamakLocationPlugin(
|
|
|
92
95
|
method: String,
|
|
93
96
|
arguments: Any?,
|
|
94
97
|
reply: TokamakPluginReply,
|
|
95
|
-
): () -> Unit =
|
|
98
|
+
): () -> Unit =
|
|
99
|
+
when (method) {
|
|
100
|
+
"watchPosition" -> watchPosition(reply)
|
|
101
|
+
else -> events.listen(method, reply) ?: super.subscribe(method, arguments, reply)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The provider's last known position when it is no older than the options' `maximumAge`, or null. */
|
|
105
|
+
private fun recentPosition(options: JSONObject): JSONObject? =
|
|
106
|
+
runCatching { positions.recent(options.optDouble("maximumAge", 0.0))?.let(::position) }
|
|
107
|
+
.getOrElse { throw locationError(it) }
|
|
108
|
+
|
|
109
|
+
/** Replies with a new fix, or null when Android finds none, unless the returned cancellation runs first. */
|
|
110
|
+
private fun currentPosition(reply: TokamakPluginReply): () -> Unit =
|
|
111
|
+
runCatching { positions.current { reply(Result.success(it?.let(::position))) } }
|
|
112
|
+
.getOrElse { throw locationError(it) }
|
|
113
|
+
|
|
114
|
+
/** Replies with each position as the device moves, until the provider turns off or the returned release runs. */
|
|
115
|
+
private fun watchPosition(reply: TokamakPluginReply): () -> Unit =
|
|
116
|
+
runCatching {
|
|
117
|
+
positions.watch({ reply(Result.success(position(it))) }) {
|
|
118
|
+
reply(Result.failure(TokamakPluginError("NotReadableError", "Location provider is unavailable")))
|
|
119
|
+
}
|
|
120
|
+
}.getOrElse { throw locationError(it) }
|
|
96
121
|
|
|
97
|
-
/**
|
|
98
|
-
* Passes [action] whether the app may read fine or coarse location, asking when it may not.
|
|
99
|
-
* Throws `NeedsUIError` when asking would show UI while the app is in the background.
|
|
100
|
-
*/
|
|
101
122
|
/**
|
|
102
123
|
* Asks for the foreground [permissions], then passes [action] whether the app has one, first
|
|
103
124
|
* starting what waited for permission.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
package com.tokamak.plugins.location
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.location.Location
|
|
5
|
+
import android.location.LocationListener
|
|
6
|
+
import android.location.LocationManager
|
|
7
|
+
import android.location.LocationRequest
|
|
8
|
+
import android.os.CancellationSignal
|
|
9
|
+
import android.os.SystemClock
|
|
10
|
+
import com.tokamak.runtime.TokamakPluginError
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Positions for `getCurrentPosition` and `watchPosition`, at the provider's highest accuracy, from
|
|
14
|
+
* the first enabled of the fused provider, which combines GPS with Wi-Fi and cell signals, GPS and
|
|
15
|
+
* the network, or any other enabled provider. Each throws `SecurityException` without permission.
|
|
16
|
+
*/
|
|
17
|
+
internal class LocationPositions(private val context: Context, private val manager: LocationManager) {
|
|
18
|
+
/** The provider's last known position when it is no older than [maximumAge] milliseconds. */
|
|
19
|
+
fun recent(maximumAge: Double): Location? = manager.getLastKnownLocation(provider())?.takeIf { age(it) <= maximumAge }
|
|
20
|
+
|
|
21
|
+
/** Passes [found] a new fix, or null when Android finds none, and returns the cancellation. */
|
|
22
|
+
fun current(found: (Location?) -> Unit): () -> Unit {
|
|
23
|
+
val signal = CancellationSignal()
|
|
24
|
+
manager.getCurrentLocation(provider(), highAccuracy(0), signal, context.mainExecutor) { found(it) }
|
|
25
|
+
return signal::cancel
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Passes [next] each position, and [disabled] the provider turning off, until the returned release runs. */
|
|
29
|
+
fun watch(next: (Location) -> Unit, disabled: () -> Unit): () -> Unit {
|
|
30
|
+
val listener = object : LocationListener {
|
|
31
|
+
override fun onLocationChanged(location: Location) = next(location)
|
|
32
|
+
|
|
33
|
+
override fun onProviderDisabled(provider: String) = disabled()
|
|
34
|
+
}
|
|
35
|
+
manager.requestLocationUpdates(provider(), highAccuracy(1000), context.mainExecutor, listener)
|
|
36
|
+
return { manager.removeUpdates(listener) }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private fun provider(): String =
|
|
40
|
+
listOf(LocationManager.FUSED_PROVIDER, LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER)
|
|
41
|
+
.firstOrNull(manager::isProviderEnabled)
|
|
42
|
+
?: manager.getProviders(true).firstOrNull()
|
|
43
|
+
?: throw TokamakPluginError("NotReadableError", "No location provider is available")
|
|
44
|
+
|
|
45
|
+
/** A request for the most accurate fixes the provider gives, every [interval] milliseconds. */
|
|
46
|
+
private fun highAccuracy(interval: Long): LocationRequest =
|
|
47
|
+
LocationRequest.Builder(interval).setQuality(LocationRequest.QUALITY_HIGH_ACCURACY).build()
|
|
48
|
+
|
|
49
|
+
/** The milliseconds since Android took [location]. */
|
|
50
|
+
private fun age(location: Location): Double =
|
|
51
|
+
(SystemClock.elapsedRealtimeNanos() - location.elapsedRealtimeNanos) / 1_000_000.0
|
|
52
|
+
}
|
|
@@ -152,4 +152,13 @@ extension TokamakPluginError {
|
|
|
152
152
|
static func locationUnavailable(_ message: String) -> Self {
|
|
153
153
|
Self(name: "NotReadableError", message: message)
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
/// Core Location's `error`: `NotAllowedError` without permission, and
|
|
157
|
+
/// `NotReadableError` otherwise.
|
|
158
|
+
static func location(_ error: Error) -> Self {
|
|
159
|
+
if (error as NSError).code == CLError.Code.denied.rawValue {
|
|
160
|
+
return Self(name: "NotAllowedError", message: "Location permission was denied")
|
|
161
|
+
}
|
|
162
|
+
return .locationUnavailable(error.localizedDescription)
|
|
163
|
+
}
|
|
155
164
|
}
|
|
@@ -19,10 +19,6 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
19
19
|
{
|
|
20
20
|
let id = "location"
|
|
21
21
|
|
|
22
|
-
private static let permissionDenied = TokamakPluginError(
|
|
23
|
-
name: "NotAllowedError",
|
|
24
|
-
message: "Location permission was denied"
|
|
25
|
-
)
|
|
26
22
|
/// A `requestPermission` waiting for the user to answer a prompt.
|
|
27
23
|
private struct Prompt {
|
|
28
24
|
/// The purpose key of the temporary precise location to ask for next.
|
|
@@ -91,6 +87,13 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
91
87
|
apply(options)
|
|
92
88
|
defaults.set(try? JSONSerialization.data(withJSONObject: options), forKey: setupKey)
|
|
93
89
|
reply(.success(nil))
|
|
90
|
+
case "recentPosition":
|
|
91
|
+
reply(.success(recentPosition(maximumAge: (options["maximumAge"] as? Double ?? 0) / 1000)))
|
|
92
|
+
case "currentPosition":
|
|
93
|
+
let fix = TokamakLocationPositions(reply: reply)
|
|
94
|
+
fix.locate()
|
|
95
|
+
// The cancellation owns the location manager until the call ends.
|
|
96
|
+
return fix.stop
|
|
94
97
|
case "permission":
|
|
95
98
|
reply(.success(permission()))
|
|
96
99
|
case "requestPermission":
|
|
@@ -151,6 +154,12 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
151
154
|
arguments: Any,
|
|
152
155
|
reply: @escaping TokamakPluginReply
|
|
153
156
|
) throws(TokamakPluginError) -> (() -> Void) {
|
|
157
|
+
if method == "watchPosition" {
|
|
158
|
+
let watch = TokamakLocationPositions(reply: reply)
|
|
159
|
+
watch.watch()
|
|
160
|
+
// The release owns the location manager until the subscription ends.
|
|
161
|
+
return watch.stop
|
|
162
|
+
}
|
|
154
163
|
guard let remove = events.listen(method, reply) else {
|
|
155
164
|
throw .notSupported("\(id).\(method) is not supported")
|
|
156
165
|
}
|
|
@@ -185,7 +194,7 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
185
194
|
) {
|
|
186
195
|
guard manager === monitoring, (error as NSError).code != CLError.Code.locationUnknown.rawValue
|
|
187
196
|
else { return }
|
|
188
|
-
events.fail(
|
|
197
|
+
events.fail(.location(error))
|
|
189
198
|
}
|
|
190
199
|
|
|
191
200
|
/// Core Location delivers each visit to every manager's delegate.
|
|
@@ -195,6 +204,14 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
195
204
|
}
|
|
196
205
|
}
|
|
197
206
|
|
|
207
|
+
/// Core Location's latest position when it is no older than `maximumAge`
|
|
208
|
+
/// seconds, or nil.
|
|
209
|
+
private func recentPosition(maximumAge: TimeInterval) -> Any? {
|
|
210
|
+
guard let recent = authorization.location, -recent.timestamp.timeIntervalSinceNow <= maximumAge
|
|
211
|
+
else { return nil }
|
|
212
|
+
return TokamakLocationEvents.position(recent)
|
|
213
|
+
}
|
|
214
|
+
|
|
198
215
|
/// Starts the significant changes and visits `config` names, and stops the
|
|
199
216
|
/// others. After a launch for one of their events, starting them again
|
|
200
217
|
/// delivers it.
|
|
@@ -381,11 +398,4 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
381
398
|
reply(opened == true ? .success(nil) : .failure(notOpened))
|
|
382
399
|
#endif
|
|
383
400
|
}
|
|
384
|
-
|
|
385
|
-
private func locationError(_ error: Error) -> TokamakPluginError {
|
|
386
|
-
if (error as NSError).code == CLError.Code.denied.rawValue {
|
|
387
|
-
return Self.permissionDenied
|
|
388
|
-
}
|
|
389
|
-
return .locationUnavailable(error.localizedDescription)
|
|
390
|
-
}
|
|
391
401
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import CoreLocation
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
/// Positions from a location manager of its own, for one `getCurrentPosition`
|
|
5
|
+
/// or `watchPosition`. Use it on the main thread.
|
|
6
|
+
final class TokamakLocationPositions: NSObject, CLLocationManagerDelegate {
|
|
7
|
+
private let manager = CLLocationManager()
|
|
8
|
+
private let reply: TokamakPluginReply
|
|
9
|
+
private var watching = false
|
|
10
|
+
|
|
11
|
+
/// Passes `reply` the new fix, or each position as the device moves, or a
|
|
12
|
+
/// failure.
|
|
13
|
+
init(reply: @escaping TokamakPluginReply) {
|
|
14
|
+
self.reply = reply
|
|
15
|
+
super.init()
|
|
16
|
+
manager.delegate = self
|
|
17
|
+
manager.desiredAccuracy = kCLLocationAccuracyBest
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func locate() {
|
|
21
|
+
manager.requestLocation()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func watch() {
|
|
25
|
+
watching = true
|
|
26
|
+
manager.startUpdatingLocation()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func stop() {
|
|
30
|
+
manager.stopUpdatingLocation()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
|
34
|
+
for location in watching ? locations : locations.suffix(1) {
|
|
35
|
+
reply(.success(TokamakLocationEvents.position(location)))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Asks again, or keeps watching, while Core Location does not know the
|
|
40
|
+
/// position yet.
|
|
41
|
+
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
|
42
|
+
guard (error as NSError).code == CLError.Code.locationUnknown.rawValue else {
|
|
43
|
+
return reply(.failure(.location(error)))
|
|
44
|
+
}
|
|
45
|
+
if !watching {
|
|
46
|
+
manager.requestLocation()
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokamakdev/plugin-location",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.128",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/mantty/tokamak.git",
|
|
@@ -9,12 +9,10 @@
|
|
|
9
9
|
"type": "module",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./src/index.ts",
|
|
12
|
-
"./events": "./events/index.ts"
|
|
13
|
-
"./apple": "./apple/bindings.ts",
|
|
14
|
-
"./android": "./android/bindings.ts"
|
|
12
|
+
"./events": "./events/index.ts"
|
|
15
13
|
},
|
|
16
14
|
"peerDependencies": {
|
|
17
|
-
"@tokamakdev/plugin": "0.1.0-beta.
|
|
15
|
+
"@tokamakdev/plugin": "0.1.0-beta.128"
|
|
18
16
|
},
|
|
19
17
|
"files": [
|
|
20
18
|
"android",
|
package/src/errors.ts
CHANGED
|
@@ -15,20 +15,3 @@ export function timedOut(): DOMException {
|
|
|
15
15
|
export function unavailable(message: string): DOMException {
|
|
16
16
|
return new DOMException(message, "NotReadableError");
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Rejects once `timeout` milliseconds pass without `found` settling, running `stop` either way. An
|
|
21
|
-
* undefined `timeout` waits as long as it takes.
|
|
22
|
-
*/
|
|
23
|
-
export async function within<T>(found: Promise<T>, timeout: number | undefined, stop: () => void): Promise<T> {
|
|
24
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
25
|
-
const expired = new Promise<never>((_, reject) => {
|
|
26
|
-
if (timeout !== undefined) timer = setTimeout(() => { reject(timedOut()); }, timeout);
|
|
27
|
-
});
|
|
28
|
-
try {
|
|
29
|
-
return await Promise.race([found, expired]);
|
|
30
|
-
} finally {
|
|
31
|
-
clearTimeout(timer);
|
|
32
|
-
stop();
|
|
33
|
-
}
|
|
34
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { Plugin, lifecycleStage, type JsonStream, type TokamakContext } from "@tokamakdev/plugin";
|
|
2
|
-
import { valueStream } from "@tokamakdev/plugin/streams";
|
|
3
2
|
|
|
4
|
-
import
|
|
5
|
-
import * as apple from "./apple.js";
|
|
6
|
-
import { backgroundDenied, permissionDenied, unavailable } from "./errors.js";
|
|
3
|
+
import { backgroundDenied, permissionDenied, timedOut, unavailable } from "./errors.js";
|
|
7
4
|
import type {
|
|
8
5
|
LocationErrorEvent,
|
|
9
6
|
LocationPermission,
|
|
@@ -41,9 +38,15 @@ class Location extends Plugin {
|
|
|
41
38
|
* when location is unavailable. Asking off screen rejects with `NeedsUIError`, as
|
|
42
39
|
* `requestPermission` does.
|
|
43
40
|
*/
|
|
44
|
-
async getCurrentPosition(
|
|
41
|
+
async getCurrentPosition({ maximumAge = 0, timeout }: PositionOptions = {}): Promise<Position> {
|
|
45
42
|
await this.#authorize();
|
|
46
|
-
|
|
43
|
+
// JSON has no Infinity, which accepts any recent position.
|
|
44
|
+
const recent = await this.call<Position | null>("recentPosition", { maximumAge: Math.min(maximumAge, Number.MAX_VALUE) });
|
|
45
|
+
if (recent) return recent;
|
|
46
|
+
const located = new AbortController();
|
|
47
|
+
const timer = timeout === undefined ? undefined : setTimeout(() => { located.abort(timedOut()); }, timeout);
|
|
48
|
+
const position = await this.call<Position | null>("currentPosition", null, { signal: located.signal })
|
|
49
|
+
.finally(() => { clearTimeout(timer); });
|
|
47
50
|
if (position) return position;
|
|
48
51
|
// Android finds no position in the background without background permission.
|
|
49
52
|
const background = await lifecycleStage(this.ctx) === "background";
|
|
@@ -55,10 +58,7 @@ class Location extends Plugin {
|
|
|
55
58
|
* with `NeedsUIError` off screen. A slow reader receives the newest.
|
|
56
59
|
*/
|
|
57
60
|
watchPosition(): JsonStream<Position> {
|
|
58
|
-
return
|
|
59
|
-
await this.#authorize();
|
|
60
|
-
return this.#platform().watchPositions(this.ctx, next, error);
|
|
61
|
-
}, "dropOldest");
|
|
61
|
+
return this.stream("watchPosition", this.#authorize().then(() => null), "dropOldest");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/** Requires location services and in-use permission, asking for it where the user has not answered. */
|
|
@@ -69,19 +69,6 @@ class Location extends Plugin {
|
|
|
69
69
|
if (inUse !== "granted") throw permissionDenied();
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
/** The platform's composition of its location SDK. */
|
|
73
|
-
#platform(): typeof apple | typeof android {
|
|
74
|
-
switch (this.ctx.platform) {
|
|
75
|
-
case "ios":
|
|
76
|
-
case "macos":
|
|
77
|
-
return apple;
|
|
78
|
-
case "android":
|
|
79
|
-
return android;
|
|
80
|
-
default:
|
|
81
|
-
throw new DOMException("Location is not supported on this platform", "NotSupportedError");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
72
|
/** The app's in-use and background permission, and the precision it gets. Never asks. */
|
|
86
73
|
permission(): Promise<LocationPermission> {
|
|
87
74
|
return this.call("permission");
|
package/tokamak-plugin.json
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"id": "location",
|
|
4
|
-
"bindings": {
|
|
5
|
-
"apple": {
|
|
6
|
-
"sdk": "26.2",
|
|
7
|
-
"modules": [
|
|
8
|
-
"CoreLocation",
|
|
9
|
-
"_LocationEssentials"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"android": {
|
|
13
|
-
"sdk": 35,
|
|
14
|
-
"modules": [
|
|
15
|
-
"android.location",
|
|
16
|
-
"android.content.Context",
|
|
17
|
-
"android.os.CancellationSignal",
|
|
18
|
-
"android.os.SystemClock",
|
|
19
|
-
"java.util.concurrent.Executor",
|
|
20
|
-
"java.util.function.Consumer"
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
4
|
"settings": {
|
|
25
5
|
"background": {
|
|
26
6
|
"kind": "boolean",
|
|
@@ -62,6 +42,7 @@
|
|
|
62
42
|
"sources": [
|
|
63
43
|
"apple/LocationEvents.swift",
|
|
64
44
|
"apple/LocationPlugin.swift",
|
|
45
|
+
"apple/LocationPositions.swift",
|
|
65
46
|
"apple/LocationRegions.swift",
|
|
66
47
|
"apple/LocationUpdates.swift"
|
|
67
48
|
]
|
|
@@ -71,6 +52,7 @@
|
|
|
71
52
|
"sources": [
|
|
72
53
|
"apple/LocationEvents.swift",
|
|
73
54
|
"apple/LocationPlugin.swift",
|
|
55
|
+
"apple/LocationPositions.swift",
|
|
74
56
|
"apple/LocationRegions.swift",
|
|
75
57
|
"apple/LocationUpdates.swift"
|
|
76
58
|
]
|
|
@@ -80,6 +62,7 @@
|
|
|
80
62
|
"sources": [
|
|
81
63
|
"android/LocationEvents.kt",
|
|
82
64
|
"android/LocationPlugin.kt",
|
|
65
|
+
"android/LocationPositions.kt",
|
|
83
66
|
"android/LocationReceiver.kt",
|
|
84
67
|
"android/LocationRegions.kt",
|
|
85
68
|
"android/LocationService.kt",
|