From ade94c9932149c43f995559a54c20a8100a52b66 Mon Sep 17 00:00:00 2001 From: max-klaus Date: Sat, 16 Jan 2021 22:02:46 +0300 Subject: [PATCH] Move tracker to gms location --- OsmAnd-telegram/AndroidManifest.xml | 11 + OsmAnd-telegram/build.gradle | 2 + .../osmand/telegram/TelegramApplication.kt | 2 - .../telegram/TelegramLocationProvider.kt | 202 +++--------------- .../net/osmand/telegram/TelegramService.kt | 142 ++++++------ .../net/osmand/telegram/TelegramSettings.kt | 1 - 6 files changed, 121 insertions(+), 239 deletions(-) diff --git a/OsmAnd-telegram/AndroidManifest.xml b/OsmAnd-telegram/AndroidManifest.xml index 625e51ee8e..d3d2a945a9 100644 --- a/OsmAnd-telegram/AndroidManifest.xml +++ b/OsmAnd-telegram/AndroidManifest.xml @@ -8,6 +8,7 @@ + + + + + + + () private val compassListeners = ArrayList() - private var gpsStatusListener: GpsStatus.Listener? = null private val mRotationM = FloatArray(9) - private var agpsDataLastTimeDownloaded: Long = 0 private val useMagneticFieldSensorCompass = false - private val gpsListener = object : LocationListener { - override fun onLocationChanged(location: Location?) { - if (location != null) { - lastTimeGPSLocationFixed = location.time - } - setLocation(convertLocation(location)) - } - - override fun onProviderDisabled(provider: String) {} - - override fun onProviderEnabled(provider: String) {} - - override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {} - } - private val networkListeners = LinkedList() - val lastKnownLocationLatLon: LatLon? get() = if (lastKnownLocation != null) { LatLon(lastKnownLocation!!.latitude, lastKnownLocation!!.longitude) @@ -87,109 +83,20 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve @SuppressLint("MissingPermission") fun resumeAllUpdates() { - val service = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager - if (app.isInternetConnectionAvailable) { - if (System.currentTimeMillis() - agpsDataLastTimeDownloaded > AGPS_TO_REDOWNLOAD) { - //force an updated check for internet connectivity here before destroying A-GPS-data - if (app.isInternetConnectionAvailable(true)) { - //redownloadAGPS() - } - } + if (AndroidUtils.isLocationPermissionAvailable(app) && fusedLocationProviderClient == null) { + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(app) } - if (AndroidUtils.isLocationPermissionAvailable(app)) { - service.addGpsStatusListener(getGpsStatusListener(service)) - try { - service.requestLocationUpdates( - LocationManager.GPS_PROVIDER, - GPS_TIMEOUT_REQUEST.toLong(), - GPS_DIST_REQUEST.toFloat(), - gpsListener - ) - } catch (e: IllegalArgumentException) { - Log.d(PlatformUtil.TAG, "GPS location provider not available") //$NON-NLS-1$ - } - // try to always ask for network provide : it is faster way to find location - - val providers = service.getProviders(true) ?: return - for (provider in providers) { - if (provider == null || provider == LocationManager.GPS_PROVIDER) { - continue - } - try { - val networkListener = NetworkListener() - service.requestLocationUpdates( - provider, - GPS_TIMEOUT_REQUEST.toLong(), - GPS_DIST_REQUEST.toFloat(), - networkListener - ) - networkListeners.add(networkListener) - } catch (e: IllegalArgumentException) { - Log.d( - PlatformUtil.TAG, - "$provider location provider not available" - ) //$NON-NLS-1$ - } - - } + try { + fusedLocationProviderClient?.requestLocationUpdates( + locationRequest, locationCallback, Looper.myLooper()) + } catch (unlikely: SecurityException) { + Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't request updates. $unlikely") } registerOrUnregisterCompassListener(true) } - private fun redownloadAGPS() { - try { - val service = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager - service.sendExtraCommand(LocationManager.GPS_PROVIDER, "delete_aiding_data", null) - val bundle = Bundle() - service.sendExtraCommand("gps", "force_xtra_injection", bundle) - service.sendExtraCommand("gps", "force_time_injection", bundle) - agpsDataLastTimeDownloaded = System.currentTimeMillis() - } catch (e: Exception) { - agpsDataLastTimeDownloaded = 0L - e.printStackTrace() - } - } - - private fun getGpsStatusListener(service: LocationManager): GpsStatus.Listener { - gpsStatusListener = object : GpsStatus.Listener { - private var gpsStatus: GpsStatus? = null - - @SuppressLint("MissingPermission") - override fun onGpsStatusChanged(event: Int) { - try { - gpsStatus = service.getGpsStatus(gpsStatus) - } catch (e: Exception) { - e.printStackTrace() - } - updateGPSInfo(gpsStatus) - updateLocation(lastKnownLocation) - } - } - return gpsStatusListener!! - } - - private fun updateGPSInfo(s: GpsStatus?) { - var fixed = false - var n = 0 - var u = 0 - if (s != null) { - val iterator = s.satellites.iterator() - while (iterator.hasNext()) { - val g = iterator.next() - n++ - if (g.usedInFix()) { - u++ - fixed = true - } - } - } - gpsInfo.fixed = fixed - gpsInfo.foundSatellites = n - gpsInfo.usedSatellites = u - } - fun updateScreenOrientation(orientation: Int) { currentScreenOrientation = orientation } @@ -217,12 +124,12 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve @Synchronized fun registerOrUnregisterCompassListener(register: Boolean) { if (sensorRegistered && !register) { - Log.d(PlatformUtil.TAG, "Disable sensor") //$NON-NLS-1$ + Log.d(PlatformUtil.TAG, "Disable sensor") (app.getSystemService(Context.SENSOR_SERVICE) as SensorManager).unregisterListener(this) sensorRegistered = false heading = null } else if (!sensorRegistered && register) { - Log.d(PlatformUtil.TAG, "Enable sensor") //$NON-NLS-1$ + Log.d(PlatformUtil.TAG, "Enable sensor") val sensorMgr = app.getSystemService(Context.SENSOR_SERVICE) as SensorManager if (useMagneticFieldSensorCompass) { var s: Sensor? = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) @@ -360,7 +267,7 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve } private fun getAngle(sinA: Float, cosA: Float) = MapUtils.unifyRotationTo360( - (Math.atan2(sinA.toDouble(), cosA.toDouble()) * 180 / Math.PI).toFloat() + (atan2(sinA.toDouble(), cosA.toDouble()) * 180 / Math.PI).toFloat() ) private fun updateLocation(loc: net.osmand.Location?) { @@ -369,31 +276,11 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve } } - private fun useOnlyGPS() = - System.currentTimeMillis() - lastTimeGPSLocationFixed < NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS - - // Working with location checkListeners - private inner class NetworkListener : LocationListener { - - override fun onLocationChanged(location: Location) { - if (!useOnlyGPS()) { - setLocation(convertLocation(location)) - } - } - - override fun onProviderDisabled(provider: String) {} - - override fun onProviderEnabled(provider: String) {} - - override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {} - } - private fun stopLocationRequests() { - val service = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager - service.removeGpsStatusListener(gpsStatusListener) - service.removeUpdates(gpsListener) - while (!networkListeners.isEmpty()) { - service.removeUpdates(networkListeners.poll()) + try { + fusedLocationProviderClient?.removeLocationUpdates(locationCallback) + } catch (unlikely: SecurityException) { + Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't remove updates. $unlikely") } } @@ -403,17 +290,7 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve } private fun setLocation(location: net.osmand.Location?) { - if (location == null) { - updateGPSInfo(null) - } - if (location != null) { - if (gpsSignalLost) { - gpsSignalLost = false - } - } this.lastKnownLocation = location - - // Update information updateLocation(this.lastKnownLocation) } @@ -424,21 +301,10 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve } } - class GPSInfo { - var foundSatellites = 0 - var usedSatellites = 0 - var fixed = false - } - companion object { private const val INTERVAL_TO_CLEAR_SET_LOCATION = 30 * 1000 - private const val GPS_TIMEOUT_REQUEST = 0 - private const val GPS_DIST_REQUEST = 0 - private const val NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS = 12000 - private const val AGPS_TO_REDOWNLOAD = 16L * 60 * 60 * 1000 // 16 hours - fun convertLocation(l: Location?): net.osmand.Location? { if (l == null) { return null diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt index c3dde54e76..2d85e971b0 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt @@ -4,30 +4,27 @@ import android.annotation.SuppressLint import android.app.Service import android.content.Context import android.content.Intent -import android.content.pm.ServiceInfo import android.location.Location -import android.location.LocationListener -import android.location.LocationManager import android.os.* +import android.util.Log import android.widget.Toast +import com.google.android.gms.location.* import net.osmand.PlatformUtil import net.osmand.telegram.TelegramSettings.ShareChatInfo import net.osmand.telegram.helpers.TelegramHelper -import net.osmand.telegram.helpers.TelegramHelper.* +import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener +import net.osmand.telegram.helpers.TelegramHelper.TelegramOutgoingMessagesListener import net.osmand.telegram.notifications.TelegramNotification.NotificationType import net.osmand.telegram.utils.AndroidUtils import org.drinkless.td.libcore.telegram.TdApi -import java.util.* private const val UPDATE_WIDGET_INTERVAL_MS = 1000L // 1 sec private const val UPDATE_LIVE_MESSAGES_INTERVAL_MS = 10000L // 10 sec private const val UPDATE_LIVE_TRACKS_INTERVAL_MS = 30000L // 30 sec -class TelegramService : Service(), LocationListener, TelegramIncomingMessagesListener, +class TelegramService : Service(), TelegramIncomingMessagesListener, TelegramOutgoingMessagesListener { - - private val log = PlatformUtil.getLog(TelegramService::class.java) - + private fun app() = application as TelegramApplication private val binder = LocationServiceBinder() private var shouldCleanupResources: Boolean = false @@ -41,10 +38,18 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis private var updateWidgetHandler: Handler? = null private var updateWidgetThread = HandlerThread("WidgetUpdateServiceThread") + // FusedLocationProviderClient - Main class for receiving location updates. + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + + // LocationRequest - Requirements for the location updates, i.e., how often you should receive + // updates, the priority, etc. + private lateinit var locationRequest: LocationRequest + + // LocationCallback - Called when FusedLocationProviderClient has a new Location. + private lateinit var locationCallback: LocationCallback + var usedBy = 0 private set - var serviceOffProvider: String = LocationManager.GPS_PROVIDER - private set var sendLocationInterval = 0L private set @@ -60,6 +65,42 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis updateShareInfoHandler = Handler(mHandlerThread.looper) updateTracksHandler = Handler(tracksHandlerThread.looper) updateWidgetHandler = Handler(updateWidgetThread.looper) + + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) + + locationRequest = LocationRequest().apply { + // Sets the desired interval for active location updates. This interval is inexact. You + // may not receive updates at all if no location sources are available, or you may + // receive them less frequently than requested. You may also receive updates more + // frequently than requested if other applications are requesting location at a more + // frequent interval. + // + // IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of + // targetSdkVersion) may receive updates less frequently than this interval when the app + // is no longer in the foreground. + interval = 1000 + + // Sets the fastest rate for active location updates. This interval is exact, and your + // application will never receive updates more frequently than this value. + fastestInterval = 500 + + // Sets the maximum time when batched location updates are delivered. Updates may be + // delivered sooner than this interval. + maxWaitTime = 2000 + + priority = LocationRequest.PRIORITY_HIGH_ACCURACY + } + + locationCallback = object : LocationCallback() { + override fun onLocationResult(locationResult: LocationResult?) { + super.onLocationResult(locationResult) + val location = convertLocation(locationResult?.lastLocation) + if (System.currentTimeMillis() - lastLocationSentTime > sendLocationInterval * 1000) { + lastLocationSentTime = System.currentTimeMillis() + app().shareLocationHelper.updateLocation(location) + } + } + } } override fun onBind(intent: Intent): IBinder { @@ -144,27 +185,27 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis } fun forceLocationUpdate() { - val location = getFirstTimeRunDefaultLocation() - app().shareLocationHelper.updateLocation(location) + getFirstTimeRunDefaultLocation { location -> + app().shareLocationHelper.updateLocation(location) + } } private fun initLocationUpdates() { - val firstLocation = getFirstTimeRunDefaultLocation() - app().shareLocationHelper.updateLocation(firstLocation) + getFirstTimeRunDefaultLocation { location -> + app().shareLocationHelper.updateLocation(location) + } // request location updates - /* - val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager try { - locationManager.requestLocationUpdates(serviceOffProvider, 0, 0f, this@TelegramService) - } catch (e: SecurityException) { + fusedLocationProviderClient.requestLocationUpdates( + locationRequest, locationCallback, Looper.myLooper()) + } catch (unlikely: SecurityException) { Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show() - log.debug("Location service permission not granted") + Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't request updates. $unlikely") } catch (e: IllegalArgumentException) { Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show() - log.debug("GPS location provider not available") + Log.d(PlatformUtil.TAG, "GPS location provider not available") } - */ } private fun startShareInfoUpdates() { @@ -219,62 +260,27 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis } @SuppressLint("MissingPermission") - private fun getFirstTimeRunDefaultLocation(): net.osmand.Location? { + private fun getFirstTimeRunDefaultLocation(locationListener: (net.osmand.Location?) -> Unit) { val app = app() if (!AndroidUtils.isLocationPermissionAvailable(app)) { - return null + locationListener(null) + return } - var location: net.osmand.Location? = null - /* - val service = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager - val ps = service.getProviders(true) ?: return null - val providers = ArrayList(ps) - // note, passive provider is from API_LEVEL 8 but it is a constant, we can check for it. - // constant should not be changed in future - val passiveFirst = providers.indexOf("passive") // LocationManager.PASSIVE_PROVIDER - // put passive provider to first place - if (passiveFirst > -1) { - providers.add(0, providers.removeAt(passiveFirst)) - } - // find location - for (provider in providers) { - val loc = convertLocation(service.getLastKnownLocation(provider)) - if (loc != null && (location == null || loc.hasAccuracy() && loc.accuracy < location.accuracy)) { - location = loc - } - } - */ - return location + fusedLocationProviderClient.lastLocation + .addOnSuccessListener { location : Location? -> + locationListener(convertLocation(location)) + } } private fun removeLocationUpdates() { // remove updates - /* - val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager try { - locationManager.removeUpdates(this) - } catch (e: SecurityException) { - log.debug("Location service permission not granted") - } - */ - } - - override fun onLocationChanged(l: Location?) { - val location = convertLocation(l) - if (System.currentTimeMillis() - lastLocationSentTime > sendLocationInterval * 1000) { - lastLocationSentTime = System.currentTimeMillis() - app().shareLocationHelper.updateLocation(location) + fusedLocationProviderClient.removeLocationUpdates(locationCallback) + } catch (unlikely: SecurityException) { + Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't remove updates. $unlikely") } } - override fun onProviderDisabled(provider: String) { - Toast.makeText(this, getString(R.string.location_service_no_gps_available), Toast.LENGTH_LONG).show() - } - - override fun onProviderEnabled(provider: String) {} - - override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {} - override fun onTaskRemoved(rootIntent: Intent) { val app = app() if (app.telegramService != null) { @@ -316,7 +322,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis } override fun onSendLiveLocationError(code: Int, message: String, shareInfo: ShareChatInfo, messageType: Int) { - log.debug("Send live location error: $code - $message") + Log.d(PlatformUtil.TAG, "Send live location error: $code - $message") when (messageType) { TelegramHelper.MESSAGE_TYPE_TEXT -> shareInfo.pendingTdLibText-- TelegramHelper.MESSAGE_TYPE_MAP -> { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index ae6805fae9..8dec6de092 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -1,7 +1,6 @@ package net.osmand.telegram import android.content.Context -import android.location.LocationManager import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan import androidx.annotation.ColorRes