diff --git a/.changes/geolocation-non-gms.md b/.changes/geolocation-non-gms.md new file mode 100644 index 0000000000..08cb181a12 --- /dev/null +++ b/.changes/geolocation-non-gms.md @@ -0,0 +1,5 @@ +--- +"geolocation": "minor" +--- + +Add support for the geolocation plugin on non-GMS android devices. diff --git a/examples/api/src-tauri/capabilities/mobile.json b/examples/api/src-tauri/capabilities/mobile.json index da77f5e53c..7c9927e834 100644 --- a/examples/api/src-tauri/capabilities/mobile.json +++ b/examples/api/src-tauri/capabilities/mobile.json @@ -16,6 +16,7 @@ "geolocation:allow-request-permissions", "geolocation:allow-watch-position", "geolocation:allow-get-current-position", + "geolocation:allow-clear-watch", "haptics:allow-impact-feedback", "haptics:allow-notification-feedback", "haptics:allow-selection-feedback", diff --git a/examples/api/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties b/examples/api/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties index 0df10d556c..fe17162822 100644 --- a/examples/api/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/api/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue May 10 19:22:52 CST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/examples/api/src/views/Geolocation.svelte b/examples/api/src/views/Geolocation.svelte index cd181dfbe2..7ce25c4133 100644 --- a/examples/api/src/views/Geolocation.svelte +++ b/examples/api/src/views/Geolocation.svelte @@ -2,11 +2,18 @@ import { checkPermissions, requestPermissions, - getCurrentPosition + getCurrentPosition, + + watchPosition, + clearWatch + } from '@tauri-apps/plugin-geolocation' export let onMessage + let pos = null + let watchId = null + async function getPosition() { let permissions = await checkPermissions() if ( @@ -17,13 +24,66 @@ } if (permissions.location === 'granted') { - getCurrentPosition().then(onMessage).catch(onMessage) + getCurrentPosition().then((position) => { + pos = position + onMessage(position) + }).catch((err) => { + pos = null + onMessage(err) + }) + } else { + onMessage('permission denied') + } + } + + async function watchPos() { + let permissions = await checkPermissions() + if ( + permissions.location === 'prompt' || + permissions.location === 'prompt-with-rationale' + ) { + permissions = await requestPermissions(['location']) + } + + if (permissions.location === 'granted') { + watchId = await watchPosition({ + enableHighAccuracy: true, + timeout: 5000, + maximumAge: 0 + }, (position) => { + pos = position + onMessage(position) + }) + onMessage('watchId: ' + watchId) } else { onMessage('permission denied') } } + + async function stopWatching() { + await clearWatch(watchId) + watchId = null + pos = null + } + + + + + + +{#if watchId} + Watch ID: {watchId} +{/if} + +{#if pos} +
{JSON.stringify(pos, null, 2)}
+{/if} diff --git a/plugins/geolocation/android/src/main/java/Geolocation.kt b/plugins/geolocation/android/src/main/java/Geolocation.kt index f93d230718..7d05c24d92 100644 --- a/plugins/geolocation/android/src/main/java/Geolocation.kt +++ b/plugins/geolocation/android/src/main/java/Geolocation.kt @@ -15,16 +15,18 @@ import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback -import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationRequest as GmsLocationRequest import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationServices import com.google.android.gms.location.Priority +import android.location.LocationRequest +import android.location.LocationListener public class Geolocation(private val context: Context) { private var fusedLocationClient: FusedLocationProviderClient? = null - private var locationCallback: LocationCallback? = null - + private var locationCallback: LocationCallback? = null // For gms + private var locationListener: LocationListener? = null // For android fun isLocationServicesEnabled(): Boolean { val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager @@ -64,7 +66,27 @@ public class Geolocation(private val context: Context) { errorCallback("Location disabled.") } } else { - errorCallback("Google Play Services unavailable.") + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + val provider = locationManager.getProviderProperties(LocationManager.GPS_PROVIDER) + if (provider == null) { + errorCallback("Location unavailable.") + return + } + if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + errorCallback("Location disabled.") + return + } + val req = LocationRequest.Builder(1_000L) + .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY) + .setMaxUpdates(1) + .build() + locationManager.getCurrentLocation(LocationManager.GPS_PROVIDER, req, null, context.mainExecutor) { location -> + if (location == null) { + errorCallback("Location unavailable.") + } else { + successCallback(location) + } + } } } @@ -89,7 +111,7 @@ public class Geolocation(private val context: Context) { val lowPrio = if (networkEnabled) Priority.PRIORITY_BALANCED_POWER_ACCURACY else Priority.PRIORITY_LOW_POWER val prio = if (enableHighAccuracy) Priority.PRIORITY_HIGH_ACCURACY else lowPrio - val locationRequest = LocationRequest.Builder(timeout) + val locationRequest = GmsLocationRequest.Builder(timeout) .setMaxUpdateDelayMillis(timeout) .setMinUpdateIntervalMillis(timeout) .setPriority(prio) @@ -112,7 +134,26 @@ public class Geolocation(private val context: Context) { errorCallback("Location disabled.") } } else { - errorCallback("Google Play Services not available.") + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + val provider = locationManager.getProviderProperties(LocationManager.GPS_PROVIDER) + if (provider == null) { + errorCallback("Location unavailable.") + return + } + if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + errorCallback("Location disabled.") + return + } + val req = LocationRequest.Builder(timeout) + .setQuality(if (enableHighAccuracy) LocationRequest.QUALITY_HIGH_ACCURACY else LocationRequest.QUALITY_LOW_POWER) + .build() + val listener = object : android.location.LocationListener { + override fun onLocationChanged(location: android.location.Location) { + successCallback(location) + } + } + locationListener = listener + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, req, context.mainExecutor, listener) } } @@ -121,6 +162,11 @@ public class Geolocation(private val context: Context) { fusedLocationClient?.removeLocationUpdates(locationCallback!!) locationCallback = null } + if (locationListener != null) { + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + locationManager.removeUpdates(locationListener!!) + locationListener = null + } } @SuppressLint("MissingPermission") diff --git a/plugins/geolocation/android/src/main/java/GeolocationPlugin.kt b/plugins/geolocation/android/src/main/java/GeolocationPlugin.kt index cf81f5e3bc..ef36508e0b 100644 --- a/plugins/geolocation/android/src/main/java/GeolocationPlugin.kt +++ b/plugins/geolocation/android/src/main/java/GeolocationPlugin.kt @@ -136,6 +136,8 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) { { error -> args.channel.sendObject(error) }) watchers[args.channel.id] = Pair(invoke, args) + + invoke.resolve() } @Command