Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit debba63a authored by Philipp Heckel's avatar Philipp Heckel
Browse files

WIP DND override

parent 3af5d608
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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"
+6 −0
Original line number Diff line number Diff line
@@ -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"
+11 −4
Original line number Diff line number Diff line
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,
+3 −2
Original line number Diff line number Diff line
@@ -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)
+30 −0
Original line number Diff line number Diff line
@@ -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)
Loading