Add doze disable preference for downloads

pull/592/head
Koitharu 2 years ago
parent ae16110a80
commit 66356dc094
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -574,6 +574,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
const val KEY_CF_CONTRAST = "cf_contrast" const val KEY_CF_CONTRAST = "cf_contrast"
const val KEY_CF_INVERTED = "cf_inverted" const val KEY_CF_INVERTED = "cf_inverted"
const val KEY_CF_GRAYSCALE = "cf_grayscale" const val KEY_CF_GRAYSCALE = "cf_grayscale"
const val KEY_IGNORE_DOZE = "ignore_dose"
// About // About
const val KEY_APP_UPDATE = "app_update" const val KEY_APP_UPDATE = "app_update"

@ -5,7 +5,9 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.WorkInfo import androidx.work.WorkInfo
import coil.ImageLoader import coil.ImageLoader
import coil.request.SuccessResult import coil.request.SuccessResult
@ -59,6 +61,7 @@ fun downloadItemAD(
val chaptersAdapter = BaseListAdapter<DownloadChapter>() val chaptersAdapter = BaseListAdapter<DownloadChapter>()
.addDelegate(ListItemType.CHAPTER, downloadChapterAD()) .addDelegate(ListItemType.CHAPTER, downloadChapterAD())
binding.recyclerViewChapters.addItemDecoration(DividerItemDecoration(context, RecyclerView.VERTICAL))
binding.recyclerViewChapters.adapter = chaptersAdapter binding.recyclerViewChapters.adapter = chaptersAdapter
binding.buttonCancel.setOnClickListener(clickListener) binding.buttonCancel.setOnClickListener(clickListener)
binding.buttonPause.setOnClickListener(clickListener) binding.buttonPause.setOnClickListener(clickListener)

@ -17,6 +17,7 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.local.data.LocalStorageManager
import org.koitharu.kotatsu.settings.storage.MangaDirectorySelectDialog import org.koitharu.kotatsu.settings.storage.MangaDirectorySelectDialog
import org.koitharu.kotatsu.settings.storage.directories.MangaDirectoriesActivity import org.koitharu.kotatsu.settings.storage.directories.MangaDirectoriesActivity
import org.koitharu.kotatsu.settings.utils.DozeHelper
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -24,6 +25,8 @@ class DownloadsSettingsFragment :
BasePreferenceFragment(R.string.downloads), BasePreferenceFragment(R.string.downloads),
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
private val dozeHelper = DozeHelper(this)
@Inject @Inject
lateinit var storageManager: LocalStorageManager lateinit var storageManager: LocalStorageManager
@ -32,6 +35,7 @@ class DownloadsSettingsFragment :
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_downloads) addPreferencesFromResource(R.xml.pref_downloads)
dozeHelper.updatePreference()
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -74,6 +78,10 @@ class DownloadsSettingsFragment :
true true
} }
AppSettings.KEY_IGNORE_DOZE -> {
dozeHelper.startIgnoreDoseActivity()
}
else -> super.onPreferenceTreeClick(preference) else -> super.onPreferenceTreeClick(preference)
} }
} }

@ -1,43 +1,36 @@
package org.koitharu.kotatsu.settings.tracker package org.koitharu.kotatsu.settings.tracker
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings import android.provider.Settings
import android.text.style.URLSpan import android.text.style.URLSpan
import android.view.View import android.view.View
import androidx.core.net.toUri
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans import androidx.core.text.inSpans
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.preference.MultiSelectListPreference import androidx.preference.MultiSelectListPreference
import androidx.preference.Preference import androidx.preference.Preference
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.powerManager
import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet
import org.koitharu.kotatsu.settings.utils.DozeHelper
import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider
import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels
import javax.inject.Inject import javax.inject.Inject
private const val KEY_IGNORE_DOZE = "ignore_dose"
@AndroidEntryPoint @AndroidEntryPoint
class TrackerSettingsFragment : class TrackerSettingsFragment :
BasePreferenceFragment(R.string.check_for_new_chapters), BasePreferenceFragment(R.string.check_for_new_chapters),
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
private val viewModel by viewModels<TrackerSettingsViewModel>() private val viewModel by viewModels<TrackerSettingsViewModel>()
private val dozeHelper = DozeHelper(this)
@Inject @Inject
lateinit var channels: TrackerNotificationChannels lateinit var channels: TrackerNotificationChannels
@ -57,13 +50,12 @@ class TrackerSettingsFragment :
} }
} }
} }
updateDozePreference() dozeHelper.updatePreference()
updateCategoriesEnabled() updateCategoriesEnabled()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
updateDozePreference()
updateNotificationsSummary() updateNotificationsSummary()
} }
@ -111,8 +103,8 @@ class TrackerSettingsFragment :
true true
} }
KEY_IGNORE_DOZE -> { AppSettings.KEY_IGNORE_DOZE -> {
startIgnoreDoseActivity(preference.context) dozeHelper.startIgnoreDoseActivity()
true true
} }
@ -120,12 +112,6 @@ class TrackerSettingsFragment :
} }
} }
private fun updateDozePreference() {
findPreference<Preference>(KEY_IGNORE_DOZE)?.run {
isVisible = isDozeIgnoreAvailable(context)
}
}
private fun updateNotificationsSummary() { private fun updateNotificationsSummary() {
val pref = findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SETTINGS) ?: return val pref = findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SETTINGS) ?: return
pref.setSummary( pref.setSummary(
@ -148,34 +134,4 @@ class TrackerSettingsFragment :
getString(R.string.enabled_d_of_d, count[0], count[1]) getString(R.string.enabled_d_of_d, count[0], count[1])
} }
} }
@SuppressLint("BatteryLife")
private fun startIgnoreDoseActivity(context: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Snackbar.make(listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT).show()
return
}
val packageName = context.packageName
val powerManager = context.powerManager ?: return
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
try {
val intent = Intent(
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
"package:$packageName".toUri(),
)
startActivity(intent)
} catch (e: ActivityNotFoundException) {
Snackbar.make(listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT).show()
}
}
}
private fun isDozeIgnoreAvailable(context: Context): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return false
}
val packageName = context.packageName
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
return !powerManager.isIgnoringBatteryOptimizations(packageName)
}
} }

@ -0,0 +1,69 @@
package org.koitharu.kotatsu.settings.utils
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.net.toUri
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.util.ext.powerManager
@SuppressLint("BatteryLife")
class DozeHelper(
private val fragment: PreferenceFragmentCompat,
) {
private val startForDozeResult = fragment.registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
) {
updatePreference()
}
fun updatePreference() {
val preference = fragment.findPreference<Preference>(AppSettings.KEY_IGNORE_DOZE) ?: return
preference.isVisible = isDozeIgnoreAvailable()
}
fun startIgnoreDoseActivity(): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Snackbar.make(fragment.listView ?: return false, R.string.operation_not_supported, Snackbar.LENGTH_SHORT).show()
return false
}
val context = fragment.context ?: return false
val packageName = context.packageName
val powerManager = context.powerManager ?: return false
return if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
try {
val intent = Intent(
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
"package:$packageName".toUri(),
)
startForDozeResult.launch(intent)
true
} catch (e: ActivityNotFoundException) {
Snackbar.make(fragment.listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT).show()
false
}
} else {
false
}
}
private fun isDozeIgnoreAvailable(): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return false
}
val context = fragment.context ?: return false
val packageName = context.packageName
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
return !powerManager.isIgnoringBatteryOptimizations(packageName)
}
}

@ -543,4 +543,5 @@
<string name="error_filter_locale_genre_not_supported">Filtering by both genres and locale is not supported by this source</string> <string name="error_filter_locale_genre_not_supported">Filtering by both genres and locale is not supported by this source</string>
<string name="error_filter_states_genre_not_supported">Filtering by both genres and states is not supported by this source</string> <string name="error_filter_states_genre_not_supported">Filtering by both genres and states is not supported by this source</string>
<string name="genres_search_hint">Start typing the genre name</string> <string name="genres_search_hint">Start typing the genre name</string>
<string name="disable_battery_optimization_summary_downloads">Might help with getting the download started if you have any issues with it</string>
</resources> </resources>

@ -19,6 +19,14 @@
android:summary="@string/downloads_wifi_only_summary" android:summary="@string/downloads_wifi_only_summary"
android:title="@string/downloads_wifi_only" /> android:title="@string/downloads_wifi_only" />
<Preference
android:key="ignore_dose"
android:persistent="false"
android:summary="@string/disable_battery_optimization_summary_downloads"
android:title="@string/disable_battery_optimization"
app:allowDividerAbove="true"
app:isPreferenceVisible="false" />
<Preference <Preference
android:icon="@drawable/ic_info_outline" android:icon="@drawable/ic_info_outline"
android:key="tracker_notifications_info" android:key="tracker_notifications_info"

Loading…
Cancel
Save