Source code for enamlnative.android.android_location

"""
Copyright (c) 2017-2022, CodeLV.

Distributed under the terms of the MIT License.

The full license is in the file LICENSE, distributed with this software.

Created on Sept 5, 2017


"""
from atom.api import List
from .android_content import Context, SystemService
from .app import AndroidApplication
from .bridge import JavaCallback, JavaMethod, JavaProxy


class LocationAccessDenied(RuntimeError):
    """User denied access or it's disabled by the system"""


[docs]class LocationManager(SystemService): SERVICE_TYPE = Context.LOCATION_SERVICE __nativeclass__ = "android.location.LocationManager" ACCESS_FINE_PERMISSION = "android.permission.ACCESS_FINE_LOCATION" ACCESS_COARSE_PERMISSION = "android.permission.ACCESS_COARSE_LOCATION" GPS_PROVIDER = "gps" NETWORK_PROVIDER = "network" PASSIVE_PROVIDER = "passive" PROVIDERS = { "gps": GPS_PROVIDER, "network": NETWORK_PROVIDER, "passive": PASSIVE_PROVIDER, } requestLocationUpdates = JavaMethod( str, "long", float, "android.location.LocationListener" ) removeUpdates = JavaMethod("android.location.LocationListener")
[docs] class LocationListener(JavaProxy): __nativeclass__ = "android.location.LocationListener"
# ------------------------------------------------------------------------- # LocationListener API # ------------------------------------------------------------------------- onLocationChanged = JavaCallback("android.location.Location") onProviderDisabled = JavaCallback(str) onProviderEnabled = JavaCallback(str) onStatusChanged = JavaCallback(str, int, "android.os.Bundle") #: Active listeners listeners = List(LocationListener)
[docs] @classmethod async def start(cls, callback, provider="gps", min_time=1000, min_distance=0): """Convenience method that checks and requests permission if necessary and if successful calls the callback with a populated `Location` instance on updates. Note you must have the permissions in your manifest or requests will be denied immediately. """ request_fine = provider == "gps" has_perm = await LocationManager.check_permission(fine=request_fine) if not has_perm: has_perm = await LocationManager.request_permission(fine=request_fine) if not has_perm: raise RuntimeError("Location permission denied") mgr = await LocationManager.get() #: When we have finally have permission mgr.onLocationChanged.connect(callback) #: Save a reference to our listener #: because we may want to stop updates listener = LocationManager.LocationListener(mgr) mgr.listeners.append(listener) mgr.requestLocationUpdates(provider, min_time, min_distance, listener)
[docs] @classmethod def stop(cls): """Stops location updates if currently updating.""" manager = LocationManager.instance() if manager is not None: for listener in manager.listeners: manager.removeUpdates(listener) manager.listeners = []
[docs] @classmethod async def check_permission(cls, fine=True) -> bool: """Returns a future that returns a boolean indicating if permission is currently granted or denied. If permission is denied, you can request using `LocationManager.request_permission()` below. """ app = AndroidApplication.instance() if fine: permission = cls.ACCESS_FINE_PERMISSION else: permission = cls.ACCESS_COARSE_PERMISSION return await app.has_permission(permission)
[docs] @classmethod async def request_permission(cls, fine=True) -> bool: """Requests permission and returns an async result that returns a boolean indicating if the permission was granted or denied. """ app = AndroidApplication.instance() if fine: permission = cls.ACCESS_FINE_PERMISSION else: permission = cls.ACCESS_COARSE_PERMISSION perms = await app.request_permissions(permission) return perms.get(permission)
[docs] def __del__(self): """Remove any listeners before destroying""" self.stop() super().__del__()