diff --git a/OsmAnd-telegram/AndroidManifest.xml b/OsmAnd-telegram/AndroidManifest.xml index 9b89517512..f5f012c063 100644 --- a/OsmAnd-telegram/AndroidManifest.xml +++ b/OsmAnd-telegram/AndroidManifest.xml @@ -7,6 +7,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml b/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml index 7d5f238f99..b196c0372b 100644 --- a/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml +++ b/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml @@ -200,8 +200,8 @@ diff --git a/OsmAnd-telegram/res/layout/user_list_item.xml b/OsmAnd-telegram/res/layout/user_list_item.xml index 4f9647b080..d9cec851a1 100644 --- a/OsmAnd-telegram/res/layout/user_list_item.xml +++ b/OsmAnd-telegram/res/layout/user_list_item.xml @@ -22,8 +22,8 @@ 64dp 14dp - 40dp + 24dp + 40dp 12dp 20dp diff --git a/OsmAnd-telegram/res/values/strings.xml b/OsmAnd-telegram/res/values/strings.xml index 910a6482ab..c88b4420d7 100644 --- a/OsmAnd-telegram/res/values/strings.xml +++ b/OsmAnd-telegram/res/values/strings.xml @@ -1,4 +1,10 @@ + Change battery optimization settings, for stable location sharing + Background work + For stable sharing of your position in the background, it is advisable to disable battery optimization for OsmAnd Telegram.\n\nIf optimization is enabled, the system may automatically turn off the application running in the background (when the screen is locked and/or the app is minimized). This happens without notification and causes the geo position broadcast to stop. + Sharing in the background + Go to settings + Later Not sent yet Not found yet Re-send location diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index a1d2c9bef3..0f59fc24a4 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -67,6 +67,8 @@ private const val LIVE_NOW_SORT_TYPE_KEY = "live_now_sort_type" private const val SHARE_CHATS_INFO_KEY = "share_chats_info" +private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked" + class TelegramSettings(private val app: TelegramApplication) { private var shareChatsInfo = ConcurrentHashMap() @@ -91,6 +93,8 @@ class TelegramSettings(private val app: TelegramApplication) { val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref()) + var batteryOptimisationAsked = false + init { updatePrefs() read() @@ -208,7 +212,7 @@ class TelegramSettings(private val app: TelegramApplication) { SharingStatusType.NO_GPS } else { var sendChatsErrors = false - shareChatsInfo.forEach { _, shareInfo -> + shareChatsInfo.forEach { (_, shareInfo) -> if (shareInfo.hasSharingError || shareInfo.lastSuccessfulSendTimeMs == -1L) { sendChatsErrors = true locationTime = shareInfo.lastSuccessfulSendTimeMs @@ -274,6 +278,8 @@ class TelegramSettings(private val app: TelegramApplication) { edit.putString(LIVE_NOW_SORT_TYPE_KEY, liveNowSortType.name) + edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked) + try { val jArray = JSONArray() shareChatsInfo.forEach { (chatId, chatInfo) -> @@ -332,6 +338,8 @@ class TelegramSettings(private val app: TelegramApplication) { liveNowSortType = LiveNowSortType.valueOf( prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name) ) + + batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false) } private fun parseShareChatsInfo(json: JSONArray) { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index 4cb3125c0b..cf21651e84 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -335,12 +335,10 @@ class TelegramHelper private constructor() { } } - fun getUserGreyPhotoPath(user: TdApi.User): String? { - return if (hasGrayscaleUserPhoto(user.id)) { - "$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT" - } else { - null - } + fun getUserGreyPhotoPath(user: TdApi.User?) = when { + user == null -> null + hasGrayscaleUserPhoto(user.id) -> "$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT" + else -> null } fun getOsmAndBotDeviceName(message: TdApi.Message): String { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/BatteryOptimizationBottomSheet.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/BatteryOptimizationBottomSheet.kt new file mode 100644 index 0000000000..258015d897 --- /dev/null +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/BatteryOptimizationBottomSheet.kt @@ -0,0 +1,91 @@ +package net.osmand.telegram.ui + +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.os.PowerManager +import android.provider.Settings +import android.support.design.widget.BottomSheetBehavior +import android.support.v4.app.DialogFragment +import android.support.v4.app.FragmentManager +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import net.osmand.PlatformUtil +import net.osmand.telegram.R +import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.ui.views.BottomSheetDialog + +class BatteryOptimizationBottomSheet : DialogFragment() { + + private val app: TelegramApplication + get() = activity?.application as TelegramApplication + + private val log = PlatformUtil.getLog(BatteryOptimizationBottomSheet::class.java) + + override fun onCreateDialog(savedInstanceState: Bundle?) = BottomSheetDialog(context!!) + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val mainView = inflater.inflate(R.layout.bottom_sheet_battery_optimization, container, false) + + mainView.findViewById(R.id.scroll_view_container).setOnClickListener { dismiss() } + + BottomSheetBehavior.from(mainView.findViewById(R.id.scroll_view)) + .setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + + override fun onStateChanged(bottomSheet: View, newState: Int) { + if (newState == BottomSheetBehavior.STATE_HIDDEN) { + dismiss() + } + } + + override fun onSlide(bottomSheet: View, slideOffset: Float) {} + }) + + mainView.findViewById(R.id.secondary_btn).apply { + setText(R.string.shared_string_later) + setOnClickListener { dismiss() } + } + + mainView.findViewById(R.id.primary_btn).apply { + setText(R.string.go_to_settings) + setOnClickListener { + if (Build.VERSION.SDK_INT > 26) { + val pkg = app.packageName + val pm = app.getSystemService(PowerManager::class.java) + if (pm != null) { + val intent = if (!pm.isIgnoringBatteryOptimizations(pkg)) { + Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).setData(Uri.parse("package:$pkg")) + } else { + Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) + } + if (intent.resolveActivity(app.packageManager) != null) { + startActivity(intent) + } else { + log.error("No Intent available to handle action") + } + } + } + dismiss() + } + } + + return mainView + } + + companion object { + + private const val TAG = "BatteryOptimizationBottomSheet" + + fun showInstance(fm: FragmentManager): Boolean { + return try { + BatteryOptimizationBottomSheet().show(fm, TAG) + true + } catch (e: RuntimeException) { + false + } + } + } +} \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt index cac0f6a229..684c5b954f 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt @@ -245,6 +245,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener { sharingMode = settings.hasAnyChatToShareLocation() clearSelection() updateContent() + if (sharingMode && !settings.batteryOptimisationAsked && Build.VERSION.SDK_INT >= 26) { + fragmentManager?.also { fm -> + BatteryOptimizationBottomSheet.showInstance(fm) + settings.batteryOptimisationAsked = true + } + } } DisableSharingBottomSheet.SHARING_DISABLED_REQUEST_CODE -> { sharingMode = false diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt index 9e79964551..1d749d87fb 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt @@ -1,6 +1,7 @@ package net.osmand.telegram.ui import android.content.Intent +import android.os.Build import android.os.Bundle import android.support.v4.app.FragmentManager import android.support.v7.widget.ListPopupWindow @@ -15,6 +16,7 @@ import net.osmand.telegram.TelegramSettings import net.osmand.telegram.TelegramSettings.DurationPref import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.utils.AndroidUtils +import org.drinkless.td.libcore.telegram.TdApi class SettingsDialogFragment : BaseDialogFragment() { @@ -50,6 +52,19 @@ class SettingsDialogFragment : BaseDialogFragment() { } } + if (Build.VERSION.SDK_INT >= 26) { + inflater.inflate(R.layout.item_with_desc_and_right_value, container, false).apply { + findViewById(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_background_work)) + findViewById(R.id.title).text = getText(R.string.background_work) + findViewById(R.id.description).text = getText(R.string.background_work_description) + findViewById(R.id.value).visibility = View.GONE + setOnClickListener { + fragmentManager?.also { BatteryOptimizationBottomSheet.showInstance(it) } + } + container.addView(this) + } + } + container = mainView.findViewById(R.id.osmand_connect_container) for (appConn in TelegramSettings.AppConnect.values()) { val pack = appConn.appPackage @@ -141,11 +156,15 @@ class SettingsDialogFragment : BaseDialogFragment() { private fun addItemToContainer(inflater: LayoutInflater, container: ViewGroup, tag: String, title: String) { inflater.inflate(R.layout.item_with_rb_and_btn, container, false).apply { + val checked = tag == settings.currentSharingMode + + setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag) + findViewById(R.id.title).text = title findViewById(R.id.primary_btn).visibility = View.GONE findViewById(R.id.radio_button).apply { visibility = View.VISIBLE - isChecked = tag == settings.currentSharingMode + isChecked = checked } setOnClickListener { settings.currentSharingMode = tag @@ -186,12 +205,31 @@ class SettingsDialogFragment : BaseDialogFragment() { } } + private fun setupSharingModeIcon(view: View, checked: Boolean, user: TdApi.User?, tag: String) { + if (tag == user?.id.toString()) { + val path = if (checked) { + telegramHelper.getUserPhotoPath(user) + } else { + telegramHelper.getUserGreyPhotoPath(user) + } + TelegramUiHelper.setupPhoto(app, view.findViewById(R.id.icon), path, R.drawable.img_user_picture, false) + } else { + val icon = if (checked) { + uiUtils.getActiveIcon(R.drawable.ic_device_picture) + } else { + uiUtils.getThemedIcon(R.drawable.ic_device_picture) + } + view.findViewById(R.id.icon).setImageDrawable(icon) + } + } + private fun updateSelectedSharingMode() { view?.findViewById(R.id.share_as_container)?.apply { for (i in 0 until childCount) { getChildAt(i).apply { - findViewById(R.id.radio_button).isChecked = - tag == settings.currentSharingMode + val checked = tag == app.settings.currentSharingMode + setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag.toString()) + findViewById(R.id.radio_button).isChecked = checked } } }