diff --git a/OsmAnd-telegram/src/net/osmand/OnNavigationServiceAlarmReceiver.kt b/OsmAnd-telegram/src/net/osmand/OnNavigationServiceAlarmReceiver.kt new file mode 100644 index 0000000000..1b0be01661 --- /dev/null +++ b/OsmAnd-telegram/src/net/osmand/OnNavigationServiceAlarmReceiver.kt @@ -0,0 +1,44 @@ +package net.osmand + +import android.annotation.SuppressLint +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.location.LocationManager +import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.TelegramService +import net.osmand.telegram.utils.AndroidUtils + +class OnNavigationServiceAlarmReceiver : BroadcastReceiver() { + @SuppressLint("MissingPermission") + override fun onReceive(context: Context, intent: Intent) { + val lock = TelegramService.getLock(context) + val app = context.applicationContext as TelegramApplication + val service = app.telegramService + // do not do nothing + if (lock.isHeld || service == null) { + return + } + lock.acquire(10 * 60 * 1000L /*10 minutes*/) + + // request location updates + val locationManager = service.getSystemService(Context.LOCATION_SERVICE) as LocationManager + try { + if (AndroidUtils.isLocationPermissionAvailable(app)) { + locationManager.requestLocationUpdates(service.serviceOffProvider, 0, 0f, service) + val handler = service.handler + if (service.serviceOffInterval > service.serviceError && handler != null) { + handler.postDelayed({ + // if lock is not anymore held + if (lock.isHeld) { + lock.release() + locationManager.removeUpdates(service) + } + }, service.serviceError) + } + } + } catch (e: RuntimeException) { + e.printStackTrace() + } + } +} \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt index 1e0ceb8d1f..ec9b01254f 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt @@ -1,5 +1,7 @@ package net.osmand.telegram +import android.app.AlarmManager +import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent @@ -9,8 +11,10 @@ import android.location.LocationManager import android.os.* import android.util.Log import android.widget.Toast +import net.osmand.OnNavigationServiceAlarmReceiver import net.osmand.PlatformUtil import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener +import net.osmand.telegram.notifications.TelegramNotification.NotificationType import org.drinkless.td.libcore.telegram.TdApi import java.util.concurrent.Executors @@ -22,7 +26,17 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis private var shouldCleanupResources: Boolean = false var handler: Handler? = null + private set var usedBy = 0 + private set + var serviceOffProvider: String = LocationManager.GPS_PROVIDER + private set + var serviceOffInterval = 0L + private set + var serviceError = 0L + private set + + private var pendingIntent: PendingIntent? = null class LocationServiceBinder : Binder() @@ -39,7 +53,21 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis val serviceIntent = Intent(ctx, TelegramService::class.java) ctx.stopService(serviceIntent) } else if (!needLocation()) { - removeLocationUpdates() + // Issue #3604 + val app = app() + if (usedBy == 2 && app.settings.sendMyLocationInterval >= 30000 && serviceOffInterval == 0L) { + serviceOffInterval = app.settings.sendMyLocationInterval + // From onStartCommand: + serviceError = serviceOffInterval / 5 + serviceError = Math.min(serviceError, 12 * 60 * 1000) + serviceError = Math.max(serviceError, 30 * 1000) + serviceError = Math.min(serviceError, serviceOffInterval) + + val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager + pendingIntent = PendingIntent.getBroadcast(this, 0, Intent(this, OnNavigationServiceAlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT) + alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval.toLong(), pendingIntent) + } + app.notificationHelper.refreshNotification(NotificationType.LOCATION) } } @@ -48,6 +76,17 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis handler = Handler() usedBy = intent.getIntExtra(USAGE_INTENT, 0) + serviceOffInterval = intent.getLongExtra(USAGE_OFF_INTERVAL, 0) + // use only gps provider + serviceOffProvider = LocationManager.GPS_PROVIDER + serviceError = serviceOffInterval / 5 + // 1. not more than 12 mins + serviceError = Math.min(serviceError, 12 * 60 * 1000) + // 2. not less than 30 seconds + serviceError = Math.max(serviceError, 30 * 1000) + // 3. not more than serviceOffInterval + serviceError = Math.min(serviceError, serviceOffInterval) + app.telegramService = this app.telegramHelper.incomingMessagesListener = this @@ -108,6 +147,10 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis return (usedBy and USED_BY_MY_LOCATION) > 0 } + private fun isContinuous(): Boolean { + return serviceOffInterval == 0L + } + override fun onLocationChanged(l: Location?) { if (l != null) { val location = convertLocation(l) @@ -156,6 +199,22 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis const val USED_BY_MY_LOCATION: Int = 1 const val USED_BY_USERS_LOCATIONS: Int = 2 const val USAGE_INTENT = "SERVICE_USED_BY" + const val USAGE_OFF_INTERVAL = "SERVICE_OFF_INTERVAL" + + private var lockStatic: PowerManager.WakeLock? = null + + @Synchronized + fun getLock(context: Context): PowerManager.WakeLock { + var lockStatic = lockStatic + if (lockStatic == null) { + val mgr = context.getSystemService(Context.POWER_SERVICE) as PowerManager + lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "OsmandServiceLock") + this.lockStatic = lockStatic + return lockStatic + } else { + return lockStatic + } + } fun convertLocation(l: Location?): net.osmand.Location? { if (l == null) { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index 95205f7d3e..d3de2d4fa2 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -16,7 +16,8 @@ class TelegramSettings(private val app: TelegramApplication) { private const val METRICS_CONSTANTS_KEY = "metrics_constants" private const val SPEED_CONSTANTS_KEY = "speed_constants" - private const val SHOW_NOTIFICATION_ALWAYS_KEY = "show_notification_always" + private const val SEND_MY_LOCATION_INTERVAL_KEY = "send_my_location_interval" + private const val SEND_MY_LOCATION_INTERVAL_DEFAULT = 5000L } private var shareLocationChats: Set = emptySet() @@ -25,7 +26,7 @@ class TelegramSettings(private val app: TelegramApplication) { var metricsConstants = MetricsConstants.KILOMETERS_AND_METERS var speedConstants = SpeedConstants.KILOMETERS_PER_HOUR - var showNotificationAlways = true + var sendMyLocationInterval = SEND_MY_LOCATION_INTERVAL_DEFAULT init { read() @@ -103,7 +104,7 @@ class TelegramSettings(private val app: TelegramApplication) { edit.putString(METRICS_CONSTANTS_KEY, metricsConstants.name) edit.putString(SPEED_CONSTANTS_KEY, speedConstants.name) - edit.putBoolean(SHOW_NOTIFICATION_ALWAYS_KEY, showNotificationAlways) + edit.putLong(SEND_MY_LOCATION_INTERVAL_KEY, sendMyLocationInterval) edit.apply() } @@ -128,6 +129,6 @@ class TelegramSettings(private val app: TelegramApplication) { metricsConstants = MetricsConstants.valueOf(prefs.getString(METRICS_CONSTANTS_KEY, MetricsConstants.KILOMETERS_AND_METERS.name)) speedConstants = SpeedConstants.valueOf(prefs.getString(SPEED_CONSTANTS_KEY, SpeedConstants.KILOMETERS_PER_HOUR.name)) - showNotificationAlways = prefs.getBoolean(SHOW_NOTIFICATION_ALWAYS_KEY, true) + sendMyLocationInterval = prefs.getLong(SEND_MY_LOCATION_INTERVAL_KEY, SEND_MY_LOCATION_INTERVAL_DEFAULT) } }