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
targetSdkVersion 29
versionCode gitCommits
versionName '0.1.4'
versionName '0.2-b1'
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.FOREGROUND_SERVICE" />
<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.RECEIVE_BOOT_COMPLETED" />
@@ -47,11 +48,10 @@
android:name=".ui.reader.SimpleSettingsActivity"
android:label="@string/settings" />
<activity android:name=".ui.browser.BrowserActivity" />
<activity
android:name=".ui.utils.CrashActivity"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:label="@string/error_occurred"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:windowSoftInputMode="stateAlwaysHidden" />
<service
@@ -59,16 +59,10 @@
android:foregroundServiceType="dataSync" />
<service android:name=".ui.settings.AppUpdateService" />
<service
android:name=".ui.tracker.TrackerJobService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<provider
android:name=".ui.search.MangaSuggestionsProvider"
android:authorities="${applicationId}.MangaSuggestionsProvider"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.files"

View File

@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.core.prefs
import android.content.Context
import android.content.SharedPreferences
import android.content.res.Resources
import android.provider.Settings
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import org.koitharu.kotatsu.R
@@ -57,6 +58,21 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
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))
var sourcesOrder: List<Int>

View File

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

View File

@@ -1,7 +1,10 @@
package org.koitharu.kotatsu.ui.settings
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.View
import androidx.appcompat.app.AppCompatDelegate
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.main.list.ListModeSelectDialog
import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
import org.koitharu.kotatsu.ui.tracker.TrackWorker
class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
SharedPreferences.OnSharedPreferenceChangeListener {
@@ -70,6 +75,17 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
ListModeSelectDialog.show(childFragmentManager)
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)
}
}

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.Intent
import android.os.Bundle
import android.transition.Slide
import android.view.Gravity
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
@@ -20,7 +23,9 @@ class SettingsActivity : BaseActivity(),
if (supportFragmentManager.findFragmentById(R.id.container) == null) {
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)
fragment.arguments = pref.extras
fragment.setTargetFragment(caller, 0)
fm.commit {
replace(R.id.container, fragment)
addToBackStack(null)
}
openFragment(fragment)
return true
}
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 {
replace(R.id.container, SourceSettingsFragment.newInstance(mangaSource))
replace(R.id.container, fragment)
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.ui.details.MangaDetailsActivity
import org.koitharu.kotatsu.utils.ext.safe
import org.koitharu.kotatsu.utils.ext.toUriOrNull
import java.util.concurrent.TimeUnit
class TrackWorker(context: Context, workerParams: WorkerParameters) :
@@ -151,8 +152,19 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
intent, PendingIntent.FLAG_UPDATE_CURRENT))
setAutoCancel(true)
color = colorPrimary
setLights(colorPrimary, 1000, 5000)
setPriority(NotificationCompat.PRIORITY_DEFAULT)
priority = 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) {
notificationManager.notify(TAG, id, builder.build())
@@ -161,7 +173,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
companion object {
private const val CHANNEL_ID = "tracking"
const val CHANNEL_ID = "tracking"
private const val TAG = "tracking"
@RequiresApi(Build.VERSION_CODES.O)

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.utils.ext
import android.net.Uri
import java.net.URLEncoder
fun String.longHashCode(): Long {
@@ -65,4 +66,10 @@ fun String.ellipsize(maxLength: Int) = if (this.length > maxLength) {
this.take(maxLength - 1) + Typography.ellipsis
} 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="read_from_start">Читать с начала</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>

View File

@@ -15,6 +15,10 @@
<string name="key_app_update">app_update</string>
<string name="key_app_update_auto">app_update_auto</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-array name="values_theme">

View File

@@ -119,4 +119,8 @@
<string name="download">Download</string>
<string name="read_from_start">Read from start</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>

View File

@@ -70,6 +70,12 @@
android:title="@string/new_chapters"
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>
</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>