Add BatteryOptimization dialog and improve ui in settings

This commit is contained in:
Chumva 2018-10-19 16:03:10 +03:00
parent 2ca1f319f9
commit a67c2affda
14 changed files with 255 additions and 21 deletions

View file

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application <application
android:name="net.osmand.telegram.TelegramApplication" android:name="net.osmand.telegram.TelegramApplication"

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:layout_gravity="bottom">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/scroll_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_hideable="true"
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
app:layout_behavior="@string/bottom_sheet_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_bg_color"
android:orientation="vertical">
<net.osmand.telegram.ui.views.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
android:text="@string/sharing_in_background"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/list_item_title_text_size"
app:firstBaselineToTopHeight="28sp"
app:typeface="@string/font_roboto_medium" />
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
android:text="@string/battery_optimization_description"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/list_item_description_text_size"
app:firstBaselineToTopHeight="28sp"
app:lastBaselineToBottomHeight="16sp"
app:typeface="@string/font_roboto_regular" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/buttons_bottom_bar_height"
android:background="?attr/card_bg_color"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding_half">
<include
layout="@layout/secondary_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<View
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
layout="@layout/primary_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>

View file

@ -200,8 +200,8 @@
<ImageView <ImageView
android:id="@+id/user_icon" android:id="@+id/user_icon"
android:layout_width="@dimen/list_item_icon_size" android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size" android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/content_padding_standard" android:layout_marginEnd="@dimen/content_padding_standard"
android:layout_marginLeft="@dimen/content_padding_half" android:layout_marginLeft="@dimen/content_padding_half"
android:layout_marginRight="@dimen/content_padding_standard" android:layout_marginRight="@dimen/content_padding_standard"

View file

@ -14,8 +14,8 @@
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="wrap_content" android:layout_width="@dimen/list_item_icon_size"
android:layout_height="wrap_content" android:layout_height="@dimen/list_item_icon_size"
android:layout_marginEnd="@dimen/content_padding_big" android:layout_marginEnd="@dimen/content_padding_big"
android:layout_marginRight="@dimen/content_padding_big" android:layout_marginRight="@dimen/content_padding_big"
tools:src="@drawable/ic_action_live_now" tools:src="@drawable/ic_action_live_now"

View file

@ -26,8 +26,8 @@
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size" android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size" android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/list_item_icon_margin_right" android:layout_marginEnd="@dimen/list_item_icon_margin_right"
android:layout_marginLeft="@dimen/list_item_icon_margin_left" android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_right" android:layout_marginRight="@dimen/list_item_icon_margin_right"

View file

@ -21,8 +21,8 @@
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size" android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size" android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginLeft="@dimen/list_item_icon_margin_left" android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_left" android:layout_marginRight="@dimen/list_item_icon_margin_left"
tools:src="@drawable/img_user_picture" /> tools:src="@drawable/img_user_picture" />

View file

@ -22,8 +22,8 @@
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size" android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size" android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/list_item_icon_margin_right" android:layout_marginEnd="@dimen/list_item_icon_margin_right"
android:layout_marginLeft="@dimen/list_item_icon_margin_left" android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_right" android:layout_marginRight="@dimen/list_item_icon_margin_right"

View file

@ -30,7 +30,8 @@
<dimen name="list_item_height_big">64dp</dimen> <dimen name="list_item_height_big">64dp</dimen>
<dimen name="list_item_icon_size_small">14dp</dimen> <dimen name="list_item_icon_size_small">14dp</dimen>
<dimen name="list_item_icon_size">40dp</dimen> <dimen name="list_item_icon_size">24dp</dimen>
<dimen name="list_item_icon_size_big">40dp</dimen>
<dimen name="list_item_icon_margin_left">12dp</dimen> <dimen name="list_item_icon_margin_left">12dp</dimen>
<dimen name="list_item_icon_margin_right">20dp</dimen> <dimen name="list_item_icon_margin_right">20dp</dimen>

View file

@ -1,4 +1,10 @@
<resources> <resources>
<string name="background_work_description">Change battery optimization settings, for stable location sharing</string>
<string name="background_work">Background work</string>
<string name="battery_optimization_description">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.</string>
<string name="sharing_in_background">Sharing in the background</string>
<string name="go_to_settings">Go to settings</string>
<string name="shared_string_later">Later</string>
<string name="not_sent_yet">Not sent yet</string> <string name="not_sent_yet">Not sent yet</string>
<string name="not_found_yet">Not found yet</string> <string name="not_found_yet">Not found yet</string>
<string name="re_send_location">Re-send location</string> <string name="re_send_location">Re-send location</string>

View file

@ -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 SHARE_CHATS_INFO_KEY = "share_chats_info"
private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked"
class TelegramSettings(private val app: TelegramApplication) { class TelegramSettings(private val app: TelegramApplication) {
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>() private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
@ -91,6 +93,8 @@ class TelegramSettings(private val app: TelegramApplication) {
val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref()) val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref())
var batteryOptimisationAsked = false
init { init {
updatePrefs() updatePrefs()
read() read()
@ -208,7 +212,7 @@ class TelegramSettings(private val app: TelegramApplication) {
SharingStatusType.NO_GPS SharingStatusType.NO_GPS
} else { } else {
var sendChatsErrors = false var sendChatsErrors = false
shareChatsInfo.forEach { _, shareInfo -> shareChatsInfo.forEach { (_, shareInfo) ->
if (shareInfo.hasSharingError || shareInfo.lastSuccessfulSendTimeMs == -1L) { if (shareInfo.hasSharingError || shareInfo.lastSuccessfulSendTimeMs == -1L) {
sendChatsErrors = true sendChatsErrors = true
locationTime = shareInfo.lastSuccessfulSendTimeMs locationTime = shareInfo.lastSuccessfulSendTimeMs
@ -274,6 +278,8 @@ class TelegramSettings(private val app: TelegramApplication) {
edit.putString(LIVE_NOW_SORT_TYPE_KEY, liveNowSortType.name) edit.putString(LIVE_NOW_SORT_TYPE_KEY, liveNowSortType.name)
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
try { try {
val jArray = JSONArray() val jArray = JSONArray()
shareChatsInfo.forEach { (chatId, chatInfo) -> shareChatsInfo.forEach { (chatId, chatInfo) ->
@ -332,6 +338,8 @@ class TelegramSettings(private val app: TelegramApplication) {
liveNowSortType = LiveNowSortType.valueOf( liveNowSortType = LiveNowSortType.valueOf(
prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name) prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name)
) )
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
} }
private fun parseShareChatsInfo(json: JSONArray) { private fun parseShareChatsInfo(json: JSONArray) {

View file

@ -335,12 +335,10 @@ class TelegramHelper private constructor() {
} }
} }
fun getUserGreyPhotoPath(user: TdApi.User): String? { fun getUserGreyPhotoPath(user: TdApi.User?) = when {
return if (hasGrayscaleUserPhoto(user.id)) { user == null -> null
"$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT" hasGrayscaleUserPhoto(user.id) -> "$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT"
} else { else -> null
null
}
} }
fun getOsmAndBotDeviceName(message: TdApi.Message): String { fun getOsmAndBotDeviceName(message: TdApi.Message): String {

View file

@ -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<View>(R.id.scroll_view_container).setOnClickListener { dismiss() }
BottomSheetBehavior.from(mainView.findViewById<View>(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<TextView>(R.id.secondary_btn).apply {
setText(R.string.shared_string_later)
setOnClickListener { dismiss() }
}
mainView.findViewById<TextView>(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
}
}
}
}

View file

@ -245,6 +245,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
sharingMode = settings.hasAnyChatToShareLocation() sharingMode = settings.hasAnyChatToShareLocation()
clearSelection() clearSelection()
updateContent() updateContent()
if (sharingMode && !settings.batteryOptimisationAsked && Build.VERSION.SDK_INT >= 26) {
fragmentManager?.also { fm ->
BatteryOptimizationBottomSheet.showInstance(fm)
settings.batteryOptimisationAsked = true
}
}
} }
DisableSharingBottomSheet.SHARING_DISABLED_REQUEST_CODE -> { DisableSharingBottomSheet.SHARING_DISABLED_REQUEST_CODE -> {
sharingMode = false sharingMode = false

View file

@ -1,6 +1,7 @@
package net.osmand.telegram.ui package net.osmand.telegram.ui
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentManager
import android.support.v7.widget.ListPopupWindow 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.TelegramSettings.DurationPref
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.AndroidUtils
import org.drinkless.td.libcore.telegram.TdApi
class SettingsDialogFragment : BaseDialogFragment() { 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<ImageView>(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_background_work))
findViewById<TextView>(R.id.title).text = getText(R.string.background_work)
findViewById<TextView>(R.id.description).text = getText(R.string.background_work_description)
findViewById<TextView>(R.id.value).visibility = View.GONE
setOnClickListener {
fragmentManager?.also { BatteryOptimizationBottomSheet.showInstance(it) }
}
container.addView(this)
}
}
container = mainView.findViewById(R.id.osmand_connect_container) container = mainView.findViewById(R.id.osmand_connect_container)
for (appConn in TelegramSettings.AppConnect.values()) { for (appConn in TelegramSettings.AppConnect.values()) {
val pack = appConn.appPackage val pack = appConn.appPackage
@ -141,11 +156,15 @@ class SettingsDialogFragment : BaseDialogFragment() {
private fun addItemToContainer(inflater: LayoutInflater, container: ViewGroup, tag: String, title: String) { private fun addItemToContainer(inflater: LayoutInflater, container: ViewGroup, tag: String, title: String) {
inflater.inflate(R.layout.item_with_rb_and_btn, container, false).apply { inflater.inflate(R.layout.item_with_rb_and_btn, container, false).apply {
val checked = tag == settings.currentSharingMode
setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag)
findViewById<TextView>(R.id.title).text = title findViewById<TextView>(R.id.title).text = title
findViewById<View>(R.id.primary_btn).visibility = View.GONE findViewById<View>(R.id.primary_btn).visibility = View.GONE
findViewById<RadioButton>(R.id.radio_button).apply { findViewById<RadioButton>(R.id.radio_button).apply {
visibility = View.VISIBLE visibility = View.VISIBLE
isChecked = tag == settings.currentSharingMode isChecked = checked
} }
setOnClickListener { setOnClickListener {
settings.currentSharingMode = tag 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<ImageView>(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<ImageView>(R.id.icon).setImageDrawable(icon)
}
}
private fun updateSelectedSharingMode() { private fun updateSelectedSharingMode() {
view?.findViewById<ViewGroup>(R.id.share_as_container)?.apply { view?.findViewById<ViewGroup>(R.id.share_as_container)?.apply {
for (i in 0 until childCount) { for (i in 0 until childCount) {
getChildAt(i).apply { getChildAt(i).apply {
findViewById<RadioButton>(R.id.radio_button).isChecked = val checked = tag == app.settings.currentSharingMode
tag == settings.currentSharingMode setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag.toString())
findViewById<RadioButton>(R.id.radio_button).isChecked = checked
} }
} }
} }