Notification settings for pre-Oreo android

This commit is contained in:
Koitharu
2020-04-12 09:58:20 +03:00
parent 12b13f98f8
commit 3014ebdfd4
14 changed files with 185 additions and 22 deletions

View File

@@ -15,7 +15,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode gitCommits versionCode gitCommits
versionName '0.1.4' versionName '0.2-b1'
buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\"" buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\""

View File

@@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -47,11 +48,10 @@
android:name=".ui.reader.SimpleSettingsActivity" android:name=".ui.reader.SimpleSettingsActivity"
android:label="@string/settings" /> android:label="@string/settings" />
<activity android:name=".ui.browser.BrowserActivity" /> <activity android:name=".ui.browser.BrowserActivity" />
<activity <activity
android:name=".ui.utils.CrashActivity" android:name=".ui.utils.CrashActivity"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:label="@string/error_occurred" android:label="@string/error_occurred"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:windowSoftInputMode="stateAlwaysHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<service <service
@@ -59,16 +59,10 @@
android:foregroundServiceType="dataSync" /> android:foregroundServiceType="dataSync" />
<service android:name=".ui.settings.AppUpdateService" /> <service android:name=".ui.settings.AppUpdateService" />
<service
android:name=".ui.tracker.TrackerJobService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<provider <provider
android:name=".ui.search.MangaSuggestionsProvider" android:name=".ui.search.MangaSuggestionsProvider"
android:authorities="${applicationId}.MangaSuggestionsProvider" android:authorities="${applicationId}.MangaSuggestionsProvider"
android:exported="false" /> android:exported="false" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.files" android:authorities="${applicationId}.files"

View File

@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.core.prefs
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.Resources import android.content.res.Resources
import android.provider.Settings
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@@ -57,6 +58,21 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
true true
) )
var notificationSound by StringPreferenceDelegate(
resources.getString(R.string.key_notifications_sound),
Settings.System.DEFAULT_NOTIFICATION_URI.toString()
)
val notificationVibrate by BoolPreferenceDelegate(
resources.getString(R.string.key_notifications_vibrate),
false
)
val notificationLight by BoolPreferenceDelegate(
resources.getString(R.string.key_notifications_light),
true
)
private var sourcesOrderStr by NullableStringPreferenceDelegate(resources.getString(R.string.key_sources_order)) private var sourcesOrderStr by NullableStringPreferenceDelegate(resources.getString(R.string.key_sources_order))
var sourcesOrder: List<Int> var sourcesOrder: List<Int>

View File

@@ -3,12 +3,11 @@ package org.koitharu.kotatsu.ui.common
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import org.koin.core.KoinComponent import org.koin.android.ext.android.inject
import org.koin.core.inject
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
PreferenceFragmentCompat(), KoinComponent { PreferenceFragmentCompat() {
protected val settings by inject<AppSettings>() protected val settings by inject<AppSettings>()

View File

@@ -1,7 +1,10 @@
package org.koitharu.kotatsu.ui.settings package org.koitharu.kotatsu.ui.settings
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.arrayMapOf import androidx.collection.arrayMapOf
@@ -15,6 +18,8 @@ import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.ui.common.BasePreferenceFragment import org.koitharu.kotatsu.ui.common.BasePreferenceFragment
import org.koitharu.kotatsu.ui.main.list.ListModeSelectDialog import org.koitharu.kotatsu.ui.main.list.ListModeSelectDialog
import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
import org.koitharu.kotatsu.ui.tracker.TrackWorker
class MainSettingsFragment : BasePreferenceFragment(R.string.settings), class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
@@ -70,6 +75,17 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
ListModeSelectDialog.show(childFragmentManager) ListModeSelectDialog.show(childFragmentManager)
true true
} }
getString(R.string.key_notifications_settings) -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
.putExtra(Settings.EXTRA_CHANNEL_ID, TrackWorker.CHANNEL_ID)
startActivity(intent)
} else {
(activity as? SettingsActivity)?.openNotificationSettingsLegacy()
}
true
}
else -> super.onPreferenceTreeClick(preference) else -> super.onPreferenceTreeClick(preference)
} }
} }

View File

@@ -0,0 +1,66 @@
package org.koitharu.kotatsu.ui.settings
import android.app.Activity
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import androidx.preference.Preference
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.ui.common.BasePreferenceFragment
import org.koitharu.kotatsu.utils.ext.toUriOrNull
class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notifications) {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_notifications)
findPreference<Preference>(R.string.key_notifications_sound)?.run {
val uri = settings.notificationSound.toUriOrNull()
summary = RingtoneManager.getRingtone(context, uri).getTitle(context)
}
}
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
return when (preference?.key) {
getString(R.string.key_notifications_sound) -> {
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_NOTIFICATION)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
Settings.System.DEFAULT_NOTIFICATION_URI)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, preference.title)
val existingValue = settings.notificationSound.toUriOrNull()
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existingValue)
startActivityForResult(intent, REQUEST_RINGTONE)
true
}
else -> super.onPreferenceTreeClick(preference)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_RINGTONE -> {
if (resultCode == Activity.RESULT_OK) {
val uri =
data?.getParcelableExtra<Uri>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
settings.notificationSound = uri?.toString().orEmpty()
findPreference<Preference>(R.string.key_notifications_sound)?.run {
summary = RingtoneManager.getRingtone(context, uri).getTitle(context)
}
}
}
else -> {
super.onActivityResult(requestCode, resultCode, data)
}
}
}
private companion object {
const val REQUEST_RINGTONE = 340
}
}

View File

@@ -3,6 +3,9 @@ package org.koitharu.kotatsu.ui.settings
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.transition.Slide
import android.view.Gravity
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit import androidx.fragment.app.commit
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
@@ -20,7 +23,9 @@ class SettingsActivity : BaseActivity(),
if (supportFragmentManager.findFragmentById(R.id.container) == null) { if (supportFragmentManager.findFragmentById(R.id.container) == null) {
supportFragmentManager.commit { supportFragmentManager.commit {
replace(R.id.container, MainSettingsFragment()) replace(R.id.container, MainSettingsFragment().also {
it.exitTransition = Slide(Gravity.START)
})
} }
} }
} }
@@ -30,16 +35,23 @@ class SettingsActivity : BaseActivity(),
val fragment = fm.fragmentFactory.instantiate(classLoader, pref.fragment) val fragment = fm.fragmentFactory.instantiate(classLoader, pref.fragment)
fragment.arguments = pref.extras fragment.arguments = pref.extras
fragment.setTargetFragment(caller, 0) fragment.setTargetFragment(caller, 0)
fm.commit { openFragment(fragment)
replace(R.id.container, fragment)
addToBackStack(null)
}
return true return true
} }
fun openMangaSourceSettings(mangaSource: MangaSource) { fun openMangaSourceSettings(mangaSource: MangaSource) {
openFragment(SourceSettingsFragment.newInstance(mangaSource))
}
fun openNotificationSettingsLegacy() {
openFragment(NotificationSettingsLegacyFragment())
}
private fun openFragment(fragment: Fragment) {
fragment.enterTransition = Slide(Gravity.END)
fragment.exitTransition = Slide(Gravity.START)
supportFragmentManager.commit { supportFragmentManager.commit {
replace(R.id.container, SourceSettingsFragment.newInstance(mangaSource)) replace(R.id.container, fragment)
addToBackStack(null) addToBackStack(null)
} }
} }

View File

@@ -24,6 +24,7 @@ import org.koitharu.kotatsu.domain.MangaProviderFactory
import org.koitharu.kotatsu.domain.tracking.TrackingRepository import org.koitharu.kotatsu.domain.tracking.TrackingRepository
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.safe
import org.koitharu.kotatsu.utils.ext.toUriOrNull
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class TrackWorker(context: Context, workerParams: WorkerParameters) : class TrackWorker(context: Context, workerParams: WorkerParameters) :
@@ -151,8 +152,19 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
intent, PendingIntent.FLAG_UPDATE_CURRENT)) intent, PendingIntent.FLAG_UPDATE_CURRENT))
setAutoCancel(true) setAutoCancel(true)
color = colorPrimary color = colorPrimary
setLights(colorPrimary, 1000, 5000) priority = NotificationCompat.PRIORITY_DEFAULT
setPriority(NotificationCompat.PRIORITY_DEFAULT) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
builder.setSound(settings.notificationSound.toUriOrNull())
var defaults = if (settings.notificationLight) {
setLights(colorPrimary, 1000, 5000)
NotificationCompat.DEFAULT_LIGHTS
} else 0
if (settings.notificationVibrate) {
builder.setVibrate(longArrayOf(500, 500, 500, 500))
defaults = defaults or NotificationCompat.DEFAULT_VIBRATE
}
builder.setDefaults(defaults)
}
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
notificationManager.notify(TAG, id, builder.build()) notificationManager.notify(TAG, id, builder.build())
@@ -161,7 +173,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
companion object { companion object {
private const val CHANNEL_ID = "tracking" const val CHANNEL_ID = "tracking"
private const val TAG = "tracking" private const val TAG = "tracking"
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.utils.ext package org.koitharu.kotatsu.utils.ext
import android.net.Uri
import java.net.URLEncoder import java.net.URLEncoder
fun String.longHashCode(): Long { fun String.longHashCode(): Long {
@@ -65,4 +66,10 @@ fun String.ellipsize(maxLength: Int) = if (this.length > maxLength) {
this.take(maxLength - 1) + Typography.ellipsis this.take(maxLength - 1) + Typography.ellipsis
} else this } else this
fun String.urlEncoded(): String = URLEncoder.encode(this, Charsets.UTF_8.name()) fun String.urlEncoded(): String = URLEncoder.encode(this, Charsets.UTF_8.name())
fun String.toUriOrNull(): Uri? = if (isEmpty()) {
null
} else {
Uri.parse(this)
}

View File

@@ -118,4 +118,8 @@
<string name="download">Загрузить</string> <string name="download">Загрузить</string>
<string name="read_from_start">Читать с начала</string> <string name="read_from_start">Читать с начала</string>
<string name="restart">Перезапустить</string> <string name="restart">Перезапустить</string>
<string name="notifications_settings">Настройки уведомлений</string>
<string name="notification_sound">Звук уведомления</string>
<string name="light_indicator">Световая индикация</string>
<string name="vibration">Вибросигнал</string>
</resources> </resources>

View File

@@ -15,6 +15,10 @@
<string name="key_app_update">app_update</string> <string name="key_app_update">app_update</string>
<string name="key_app_update_auto">app_update_auto</string> <string name="key_app_update_auto">app_update_auto</string>
<string name="key_tracker_notifications">tracker_notifications</string> <string name="key_tracker_notifications">tracker_notifications</string>
<string name="key_notifications_settings">notifications_settings</string>
<string name="key_notifications_sound">notifications_sound</string>
<string name="key_notifications_vibrate">notifications_vibrate</string>
<string name="key_notifications_light">notifications_light</string>
<string name="key_parser_domain">domain</string> <string name="key_parser_domain">domain</string>
<string-array name="values_theme"> <string-array name="values_theme">

View File

@@ -119,4 +119,8 @@
<string name="download">Download</string> <string name="download">Download</string>
<string name="read_from_start">Read from start</string> <string name="read_from_start">Read from start</string>
<string name="restart">Restart</string> <string name="restart">Restart</string>
<string name="notifications_settings">Notifications settings</string>
<string name="notification_sound">Notification sound</string>
<string name="light_indicator">Light indicator</string>
<string name="vibration">Vibration</string>
</resources> </resources>

View File

@@ -70,6 +70,12 @@
android:title="@string/new_chapters" android:title="@string/new_chapters"
app:iconSpaceReserved="false" /> app:iconSpaceReserved="false" />
<Preference
android:title="@string/notifications_settings"
app:iconSpaceReserved="false"
android:dependency="@string/key_tracker_notifications"
android:key="@string/key_notifications_settings" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
android:key="@string/key_notifications_sound"
android:title="@string/notification_sound"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_notifications_vibrate"
android:title="@string/vibration"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="true"
android:key="@string/key_notifications_light"
android:title="@string/light_indicator"
app:iconSpaceReserved="false" />
</PreferenceScreen>