mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-05-05 12:25:10 +02:00
feat: Add geolocation and haptics plugins (#1599)
* init geolocation plugin * ios impl (w/o js api) * generate ts api * use newer tauri commit * add temporary postinstall * include src in files * guest-js * just ship dist-js for now * fix watcher * fix android compile error * fix android build for real * fix heading type * initial getCurrentPosition android impl (wip) * prevent panics if errors (strings) are sent over the channel * Add android watchPosition implementation * init haptics plugin (android) * ios and new apis (ANDROID IS LIKELY BROKEN - MAY NOT EVEN COMPILE) * use tauri-specta that accounts for raw fn arg idents * add complete android support (it's not working great due to random soft-/hardware support) * fix(haptics): Fix the NotificationFeedbackType::Success and Version (#1) * Fix success feedback and version * Apply suggestions from code review * Update package.json --------- Co-authored-by: Fabian-Lars <118197967+FabianLars-crabnebula@users.noreply.github.com> * android: improve permission callback handling * keep track of ongoing perms requests * rebuild * license headers * rm sqlite feat * fmt * what diff u talkin bout? * ignore dist-js again * fix audits * dedupe api.js * clippy * changefiles * readmes * clean up todos * rm dsstore * rm wrong feats * mirror * covector * rebuild * ios requires the wry feature * lint * update lock --------- Co-authored-by: fabianlars <fabianlars@fabianlars.de> Co-authored-by: Brendan Allan <brendonovich@outlook.com> Co-authored-by: Naman Garg <155433377+naman-crabnebula@users.noreply.github.com> Co-authored-by: Lucas Nogueira <lucas@crabnebula.dev>
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package app.tauri.geolocation
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import android.os.SystemClock
|
||||
import androidx.core.location.LocationManagerCompat
|
||||
import app.tauri.Logger
|
||||
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.LocationResult
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.location.Priority
|
||||
|
||||
|
||||
public class Geolocation(private val context: Context) {
|
||||
private var fusedLocationClient: FusedLocationProviderClient? = null
|
||||
private var locationCallback: LocationCallback? = null
|
||||
|
||||
|
||||
fun isLocationServicesEnabled(): Boolean {
|
||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
return LocationManagerCompat.isLocationEnabled(lm)
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingPermission")
|
||||
fun sendLocation(enableHighAccuracy: Boolean, successCallback: (location: Location) -> Unit, errorCallback: (error: String) -> Unit) {
|
||||
val resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
|
||||
if (resultCode == ConnectionResult.SUCCESS) {
|
||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
|
||||
if (this.isLocationServicesEnabled()) {
|
||||
var networkEnabled = false
|
||||
|
||||
try {
|
||||
networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
|
||||
} catch (_: Exception) {
|
||||
Logger.error("isProviderEnabled failed")
|
||||
}
|
||||
|
||||
val lowPrio = if (networkEnabled) Priority.PRIORITY_BALANCED_POWER_ACCURACY else Priority.PRIORITY_LOW_POWER
|
||||
val prio = if (enableHighAccuracy) Priority.PRIORITY_HIGH_ACCURACY else lowPrio
|
||||
|
||||
Logger.error(prio.toString())
|
||||
|
||||
LocationServices
|
||||
.getFusedLocationProviderClient(context)
|
||||
.getCurrentLocation(prio, null)
|
||||
.addOnFailureListener { e -> e.message?.let { errorCallback(it) } }
|
||||
.addOnSuccessListener { location ->
|
||||
if (location == null) {
|
||||
errorCallback("Location unavailable.")
|
||||
} else {
|
||||
successCallback(location)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errorCallback("Location disabled.")
|
||||
}
|
||||
} else {
|
||||
errorCallback("Google Play Services unavailable.")
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun requestLocationUpdates(enableHighAccuracy: Boolean, timeout: Long, successCallback: (location: Location) -> Unit, errorCallback: (error: String) -> Unit) {
|
||||
val resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
|
||||
if (resultCode == ConnectionResult.SUCCESS) {
|
||||
clearLocationUpdates()
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
|
||||
|
||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
|
||||
if (this.isLocationServicesEnabled()) {
|
||||
var networkEnabled = false
|
||||
|
||||
try {
|
||||
networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
|
||||
} catch (_: Exception) {
|
||||
Logger.error("isProviderEnabled failed")
|
||||
}
|
||||
|
||||
val lowPrio = if (networkEnabled) Priority.PRIORITY_BALANCED_POWER_ACCURACY else Priority.PRIORITY_LOW_POWER
|
||||
val prio = if (enableHighAccuracy) Priority.PRIORITY_HIGH_ACCURACY else lowPrio
|
||||
|
||||
Logger.error(prio.toString())
|
||||
|
||||
val locationRequest = LocationRequest.Builder(10000)
|
||||
.setMaxUpdateDelayMillis(timeout)
|
||||
.setMinUpdateIntervalMillis(5000)
|
||||
.setPriority(prio)
|
||||
.build()
|
||||
|
||||
locationCallback =
|
||||
object : LocationCallback() {
|
||||
override fun onLocationResult(locationResult: LocationResult) {
|
||||
val lastLocation = locationResult.lastLocation
|
||||
if (lastLocation == null) {
|
||||
errorCallback("Location unavailable.")
|
||||
} else {
|
||||
successCallback(lastLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fusedLocationClient?.requestLocationUpdates(locationRequest, locationCallback!!, null)
|
||||
} else {
|
||||
errorCallback("Location disabled.")
|
||||
}
|
||||
} else {
|
||||
errorCallback("Google Play Services not available.")
|
||||
}
|
||||
}
|
||||
|
||||
fun clearLocationUpdates() {
|
||||
if (locationCallback != null) {
|
||||
fusedLocationClient?.removeLocationUpdates(locationCallback!!)
|
||||
locationCallback = null
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getLastLocation(maximumAge: Long): Location? {
|
||||
var lastLoc: Location? = null
|
||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
|
||||
for (provider in lm.allProviders) {
|
||||
val tmpLoc = lm.getLastKnownLocation(provider)
|
||||
if (tmpLoc != null) {
|
||||
val locationAge = SystemClock.elapsedRealtimeNanos() - tmpLoc.elapsedRealtimeNanos
|
||||
val maxAgeNano = maximumAge * 1000000L
|
||||
if (locationAge <= maxAgeNano && (lastLoc == null || lastLoc.elapsedRealtimeNanos > tmpLoc.elapsedRealtimeNanos)) {
|
||||
lastLoc = tmpLoc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastLoc
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user