WIP DND override

This commit is contained in:
Philipp Heckel 2022-04-14 10:54:17 -04:00
parent 3af5d60811
commit debba63a5d
6 changed files with 52 additions and 6 deletions

View file

@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <!-- Only required on SDK <= 28 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> <!-- To install packages downloaded through ntfy; craazyy! -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <!-- To reschedule the websocket retry -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /> <!-- To override DND -->
<application
android:name=".app.Application"

View file

@ -218,6 +218,11 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
return sharedPrefs.getInt(SHARED_PREFS_MIN_PRIORITY, 1) // 1/low means all priorities
}
fun getDnsOverridePriority(): Int {
return sharedPrefs.getInt(SHARED_PREFS_DND_OVERRIDE_PRIORITY, 5)
}
fun getAutoDownloadMaxSize(): Long {
val defaultValue = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
AUTO_DOWNLOAD_NEVER // Need to request permission on older versions
@ -435,6 +440,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
const val SHARED_PREFS_AUTO_RESTART_WORKER_VERSION = "AutoRestartWorkerVersion"
const val SHARED_PREFS_MUTED_UNTIL_TIMESTAMP = "MutedUntil"
const val SHARED_PREFS_MIN_PRIORITY = "MinPriority"
const val SHARED_PREFS_DND_OVERRIDE_PRIORITY = "DndOverridePriority"
const val SHARED_PREFS_AUTO_DOWNLOAD_MAX_SIZE = "AutoDownload"
const val SHARED_PREFS_AUTO_DELETE_SECONDS = "AutoDelete"
const val SHARED_PREFS_CONNECTION_PROTOCOL = "ConnectionProtocol"

View file

@ -1,7 +1,11 @@
package io.heckel.ntfy.msg
import android.app.*
import android.content.*
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.TaskStackBuilder
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.RingtoneManager
import android.net.Uri
@ -10,15 +14,15 @@ import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import io.heckel.ntfy.R
import io.heckel.ntfy.db.*
import io.heckel.ntfy.db.Notification
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.ui.Colors
import io.heckel.ntfy.ui.DetailActivity
import io.heckel.ntfy.ui.MainActivity
import io.heckel.ntfy.util.*
class NotificationService(val context: Context) {
private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val repository = Repository.getInstance(context)
fun display(subscription: Subscription, notification: Notification) {
Log.d(TAG, "Displaying notification $notification")
@ -218,6 +222,7 @@ class NotificationService(val context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Note: To change a notification channel, you must delete the old one and create a new one!
val dndOverridePriority = repository.getDnsOverridePriority()
val pause = 300L
val channel = when (priority) {
1 -> NotificationChannel(CHANNEL_ID_MIN, context.getString(R.string.channel_notifications_min_name), NotificationManager.IMPORTANCE_MIN)
@ -225,6 +230,7 @@ class NotificationService(val context: Context) {
4 -> {
val channel = NotificationChannel(CHANNEL_ID_HIGH, context.getString(R.string.channel_notifications_high_name), NotificationManager.IMPORTANCE_HIGH)
channel.enableVibration(true)
channel.setBypassDnd(dndOverridePriority >= 4)
channel.vibrationPattern = longArrayOf(
pause, 100, pause, 100, pause, 100,
pause, 2000
@ -235,6 +241,7 @@ class NotificationService(val context: Context) {
val channel = NotificationChannel(CHANNEL_ID_MAX, context.getString(R.string.channel_notifications_max_name), NotificationManager.IMPORTANCE_HIGH) // IMPORTANCE_MAX does not exist
channel.enableLights(true)
channel.enableVibration(true)
channel.setBypassDnd(dndOverridePriority >= 4)
channel.vibrationPattern = longArrayOf(
pause, 100, pause, 100, pause, 100,
pause, 2000,

View file

@ -30,7 +30,6 @@ import io.heckel.ntfy.app.Application
import io.heckel.ntfy.db.Repository
import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.firebase.FirebaseMessenger
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.msg.ApiService
import io.heckel.ntfy.msg.NotificationDispatcher
import io.heckel.ntfy.service.SubscriberService
@ -376,7 +375,9 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
true
}
R.id.main_menu_docs -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_docs_url))))
//startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_docs_url))))
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
startActivity(intent)
true
}
else -> super.onOptionsItemSelected(item)

View file

@ -2,6 +2,7 @@ package io.heckel.ntfy.ui
import android.Manifest
import android.app.AlertDialog
import android.app.NotificationManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
@ -120,6 +121,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var repository: Repository
private lateinit var serviceManager: SubscriberServiceManager
private lateinit var notificationManager: NotificationManager
private var autoDownloadSelection = AUTO_DOWNLOAD_SELECTION_NOT_SET
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
@ -129,6 +131,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
repository = Repository.getInstance(requireActivity())
serviceManager = SubscriberServiceManager(requireActivity())
autoDownloadSelection = repository.getAutoDownloadMaxSize() // Only used for <= Android P, due to permissions request
notificationManager = requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Important note: We do not use the default shared prefs to store settings. Every
// preferenceDataStore is overridden to use the repository. This is convenient, because
@ -200,6 +203,33 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
}
}
// DND override priority
val dndOverrideEnabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && notificationManager.isNotificationPolicyAccessGranted
val dndOverridePriorityPrefId = context?.getString(R.string.settings_notifications_dnd_override_priority_key) ?: return
val dndOverridePriority: ListPreference? = findPreference(minPriorityPrefId)
dndOverridePriority?.isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
dndOverridePriority?.value = repository.getDnsOverridePriority().toString()
dndOverridePriority?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
val dndOverridePriorityValue = value?.toIntOrNull() ?:return
//repository.setMinPriority(minPriorityValue)
}
override fun getString(key: String?, defValue: String?): String {
return repository.getDnsOverridePriority().toString()
}
}
dndOverridePriority?.summaryProvider = Preference.SummaryProvider<ListPreference> { pref ->
val priorityValue = pref.value.toIntOrNull() ?: 1 // 1/low means all priorities
when (priorityValue) {
1 -> getString(R.string.settings_notifications_min_priority_summary_any)
5 -> getString(R.string.settings_notifications_min_priority_summary_max)
else -> {
val minPriorityString = toPriorityString(requireContext(), priorityValue)
getString(R.string.settings_notifications_min_priority_summary_x_or_higher, priorityValue, minPriorityString)
}
}
}
// Auto download
val autoDownloadPrefId = context?.getString(R.string.settings_notifications_auto_download_key) ?: return
val autoDownload: ListPreference? = findPreference(autoDownloadPrefId)

View file

@ -15,6 +15,7 @@
<!-- Settings constants -->
<string name="settings_notifications_muted_until_key" translatable="false">MutedUntil</string>
<string name="settings_notifications_min_priority_key" translatable="false">MinPriority</string>
<string name="settings_notifications_dnd_override_priority_key" translatable="false">DndOverridePriority</string>
<string name="settings_notifications_auto_download_key" translatable="false">AutoDownload</string>
<string name="settings_notifications_auto_delete_key" translatable="false">AutoDelete</string>
<string name="settings_general_default_base_url_key" translatable="false">DefaultBaseURL</string>