@tokamakdev/plugin-location 0.1.0-beta.107 → 0.1.0-beta.114

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.
@@ -7,14 +7,8 @@ import android.content.Context
7
7
  import android.content.Intent
8
8
  import android.content.pm.PackageManager
9
9
  import android.location.Location
10
- import android.location.LocationListener
11
10
  import android.location.LocationManager
12
11
  import android.net.Uri
13
- import android.os.Bundle
14
- import android.os.CancellationSignal
15
- import android.os.Handler
16
- import android.os.Looper
17
- import android.os.SystemClock
18
12
  import android.provider.Settings
19
13
  import com.tokamak.runtime.TokamakHost
20
14
  import com.tokamak.runtime.TokamakPlugin
@@ -34,7 +28,6 @@ class TokamakLocationPlugin(
34
28
  private val context = host.context
35
29
  private val manager =
36
30
  context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
37
- private val handler = Handler(Looper.getMainLooper())
38
31
 
39
32
  /** The permissions the app's manifest requests. */
40
33
  private val declared: Set<String> by lazy {
@@ -71,13 +64,9 @@ class TokamakLocationPlugin(
71
64
  if (host.isInForeground) startService()
72
65
  }
73
66
 
74
- override fun call(method: String, arguments: Any?, reply: TokamakPluginReply) {
67
+ override fun call(method: String, arguments: Any?, reply: TokamakPluginReply): (() -> Unit)? {
75
68
  when (method) {
76
69
  "setup" -> setup(requireObject(arguments), reply)
77
- "getCurrentPosition" ->
78
- withPermission { granted ->
79
- if (granted) currentPosition(arguments as? JSONObject, reply) else reply(Result.failure(permissionDenied()))
80
- }
81
70
  "permission" -> reply(Result.success(permission()))
82
71
  "requestPermission" -> requestPermission(requireObject(arguments), reply)
83
72
  "servicesEnabled" -> reply(Result.success(manager.isLocationEnabled))
@@ -96,38 +85,19 @@ class TokamakLocationPlugin(
96
85
  }
97
86
  else -> super.call(method, arguments, reply)
98
87
  }
88
+ return null
99
89
  }
100
90
 
101
91
  override fun subscribe(
102
92
  method: String,
103
93
  arguments: Any?,
104
94
  reply: TokamakPluginReply,
105
- ): () -> Unit {
106
- events.listen(method, reply)?.let { return it }
107
- if (method != "watchPosition") return super.subscribe(method, arguments, reply)
108
- var cancelled = false
109
- var stop = {}
110
- withPermission { granted ->
111
- if (!granted) {
112
- reply(Result.failure(permissionDenied()))
113
- } else if (!cancelled) {
114
- stop = watchPosition(reply)
115
- }
116
- }
117
- return {
118
- cancelled = true
119
- stop()
120
- }
121
- }
95
+ ): () -> Unit = events.listen(method, reply) ?: super.subscribe(method, arguments, reply)
122
96
 
123
97
  /**
124
98
  * Passes [action] whether the app may read fine or coarse location, asking when it may not.
125
99
  * Throws `NeedsUIError` when asking would show UI while the app is in the background.
126
100
  */
127
- private fun withPermission(action: (Boolean) -> Unit) {
128
- if (hasForegroundPermission()) action(true) else askForeground(foreground, action)
129
- }
130
-
131
101
  /**
132
102
  * Asks for the foreground [permissions], then passes [action] whether the app has one, first
133
103
  * starting what waited for permission.
@@ -291,82 +261,6 @@ class TokamakLocationPlugin(
291
261
  reply(Result.success(null))
292
262
  }
293
263
 
294
- /**
295
- * Replies with a fix no older than the `maximumAge` option, taking a new one when there is
296
- * none, or fails after the `timeout` option.
297
- */
298
- private fun currentPosition(options: JSONObject?, reply: TokamakPluginReply) {
299
- val provider = availableProvider(reply) ?: return
300
- val maximumAge = options?.optLong("maximumAge", 0) ?: 0
301
- val recent = runCatching { manager.getLastKnownLocation(provider) }.getOrNull()
302
- if (recent != null && ageMillis(recent) <= maximumAge) {
303
- reply(Result.success(position(recent)))
304
- return
305
- }
306
- val cancellation = CancellationSignal()
307
- val timeout = Runnable {
308
- cancellation.cancel()
309
- reply(Result.failure(TokamakPluginError("TimeoutError", "Location was not found in time")))
310
- }
311
- handler.postDelayed(timeout, options?.optLong("timeout", UNLIMITED) ?: UNLIMITED)
312
- runCatching {
313
- manager.getCurrentLocation(
314
- provider,
315
- cancellation,
316
- context.mainExecutor,
317
- ) { location ->
318
- handler.removeCallbacks(timeout)
319
- reply(if (location == null) missingFix() else Result.success(position(location)))
320
- }
321
- }.onFailure {
322
- handler.removeCallbacks(timeout)
323
- reply(locationFailure(it))
324
- }
325
- }
326
-
327
- private fun ageMillis(location: Location): Long =
328
- (SystemClock.elapsedRealtimeNanos() - location.elapsedRealtimeNanos) / 1_000_000
329
-
330
- private fun watchPosition(reply: TokamakPluginReply): () -> Unit {
331
- val provider = availableProvider(reply) ?: return {}
332
- val listener = object : LocationListener {
333
- override fun onLocationChanged(location: Location) {
334
- reply(Result.success(position(location)))
335
- }
336
-
337
- override fun onProviderDisabled(provider: String) {
338
- reply(unavailable("Location provider is unavailable"))
339
- }
340
-
341
- override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) = Unit
342
- }
343
- runCatching {
344
- manager.requestLocationUpdates(provider, 1000, 0F, listener, Looper.getMainLooper())
345
- }.onFailure {
346
- reply(locationFailure(it))
347
- return {}
348
- }
349
- return { manager.removeUpdates(listener) }
350
- }
351
-
352
- /** The provider to use, or null once [reply] has the reason there is none. */
353
- private fun availableProvider(reply: TokamakPluginReply): String? {
354
- val provider = runCatching(::provider).getOrElse {
355
- reply(locationFailure(it))
356
- return null
357
- }
358
- if (provider == null) reply(unavailable("No location provider is available"))
359
- return provider
360
- }
361
-
362
- private fun provider(): String? =
363
- listOf(
364
- LocationManager.GPS_PROVIDER,
365
- LocationManager.NETWORK_PROVIDER,
366
- LocationManager.FUSED_PROVIDER,
367
- ).firstOrNull(manager::isProviderEnabled)
368
- ?: manager.getProviders(true).firstOrNull()
369
-
370
264
  private fun position(location: Location): JSONObject =
371
265
  JSONObject()
372
266
  .put(
@@ -389,19 +283,6 @@ class TokamakLocationPlugin(
389
283
 
390
284
  private fun permissionDenied() = TokamakPluginError("NotAllowedError", "Location permission was denied")
391
285
 
392
- /** Why no fix came: Android gives none in the background without background location permission. */
393
- private fun missingFix(): Result<Any?> =
394
- if (host.isInForeground || granted(BACKGROUND)) {
395
- unavailable("Location is unavailable")
396
- } else {
397
- Result.failure(TokamakPluginError("NotAllowedError", "Location permission does not cover the background"))
398
- }
399
-
400
- private fun unavailable(message: String): Result<Any?> =
401
- Result.failure(TokamakPluginError("NotReadableError", message))
402
-
403
- private fun locationFailure(error: Throwable): Result<Any?> = Result.failure(locationError(error))
404
-
405
286
  private fun locationError(error: Throwable): TokamakPluginError =
406
287
  when (error) {
407
288
  is SecurityException -> permissionDenied()
@@ -411,8 +292,6 @@ class TokamakLocationPlugin(
411
292
  }
412
293
 
413
294
  private companion object {
414
- /** The `timeout` that never expires, as the page sends it. */
415
- const val UNLIMITED = 0xffffffffL
416
295
  const val FINE = Manifest.permission.ACCESS_FINE_LOCATION
417
296
  const val COARSE = Manifest.permission.ACCESS_COARSE_LOCATION
418
297
  const val BACKGROUND = Manifest.permission.ACCESS_BACKGROUND_LOCATION