From 54769cc0c46f0b5dcabb96735564008fd19a6a39 Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 00:07:05 -0500 Subject: [PATCH 1/8] Added basic DND functionality --- app/src/main/AndroidManifest.xml | 1 + .../hu/vmiklos/plees_tracker/MainActivity.kt | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 18a49b5..95cf319 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + (R.id.start_stop) val startStopText = findViewById(R.id.start_stop_text) + val dndManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (DataModel.start != null && DataModel.stop != null) { + // When user stops tracking sleep + if (dndManager.isNotificationPolicyAccessGranted) { + dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + } else { + Log.w(TAG, "Failed to disable DND, permissions not enabled") + } status.text = getString(R.string.tracking_stopped) startStop.contentDescription = getString(R.string.start_again) startStop.setImageResource(R.drawable.ic_start) @@ -326,6 +337,14 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { return } DataModel.start?.let { start -> + // When user starts tracking sleep + if (dndManager.isNotificationPolicyAccessGranted) { + dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE) + } else { + val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + startActivity(intent) + Log.w(TAG, "Failed to enable DND, permissions not enabled") + } status.text = String.format( getString(R.string.sleeping_since), DataModel.formatTimestamp(start, DataModel.getCompactView()) From e8ca9e3787f5c16ca52673158bd744d994463322 Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 04:35:52 -0500 Subject: [PATCH 2/8] Added DND in settings --- .idea/deploymentTargetDropDown.xml | 10 +++ .../hu/vmiklos/plees_tracker/MainActivity.kt | 2 - .../hu/vmiklos/plees_tracker/Preferences.kt | 80 +++++++++++++++++++ .../plees_tracker/PreferencesActivity.kt | 5 ++ app/src/main/res/values/strings.xml | 6 ++ app/src/main/res/xml/preferences.xml | 9 +++ 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index 4d12c3a..dd7cbe0 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -341,8 +341,6 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { if (dndManager.isNotificationPolicyAccessGranted) { dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE) } else { - val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) - startActivity(intent) Log.w(TAG, "Failed to enable DND, permissions not enabled") } status.text = String.format( diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt index b0e5fae..5ee7efb 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt @@ -6,11 +6,24 @@ package hu.vmiklos.plees_tracker +import android.app.AlertDialog +import android.app.NotificationManager +import android.content.Context +import android.content.DialogInterface +import android.content.Intent import android.os.Bundle +import android.provider.Settings +import android.util.Log +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceManager class Preferences : PreferenceFragmentCompat() { + companion object { + private const val TAG = "PreferencesActivity" + } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) val autoBackupPath = findPreference("auto_backup_path") @@ -20,6 +33,73 @@ class Preferences : PreferenceFragmentCompat() { it.summary = path } } + + override fun onPreferenceTreeClick(preference: Preference): Boolean { + val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } + + if (preference.key == "enable_dnd") { // If someone toggled the enable_dnd preference + if (sharedPreferences != null) { + if (sharedPreferences.getBoolean("enable_dnd", false)) { + val activity = activity ?: return super.onPreferenceTreeClick(preference) + val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val hasPermission = dndManager.isNotificationPolicyAccessGranted + + if (!hasPermission) { + // If we don't have permissions for DND + AlertDialog.Builder(context) + .setTitle(R.string.settings_enable_dnd_question_title) + .setMessage(R.string.settings_enable_dnd_question_message) + .setPositiveButton(R.string.settings_enable_dnd_question_ok) { _, _ -> + val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + startActivity(intent) + } + .setNegativeButton(R.string.settings_enable_dnd_question_cancel) { _, _ -> + val editor = sharedPreferences.edit() + if (editor != null) { + editor.putBoolean("enable_dnd", false) + editor.apply() + } else { + Log.wtf(TAG, "editor is null") + } + checkDnd() + } + .create() + .show() + } + } + } else { + Log.wtf(TAG, "sharedPreferences is null") + } + } + return super.onPreferenceTreeClick(preference) + } + + override fun onResume() { + super.onResume() + checkDnd() + } + + fun checkDnd() { + val activity = activity ?: return + val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val hasPermission = dndManager.isNotificationPolicyAccessGranted + + val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } + val editor = sharedPreferences?.edit() + + if (!hasPermission) { + if (editor != null) { + editor.putBoolean("enable_dnd", false) + editor.apply() + Log.d(TAG, "Set enable_dnd to false!") + // Refresh screen, not the "cleanest way" but it works + preferenceScreen.removeAll(); + addPreferencesFromResource(R.xml.preferences); + } else { + Log.wtf(TAG, "editor is null") + } + } + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt index 2e016eb..a81369d 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt @@ -6,11 +6,15 @@ package hu.vmiklos.plees_tracker +import android.app.NotificationManager +import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import android.provider.Settings +import androidx.activity.result.ActivityResultLauncher class PreferencesActivity : AppCompatActivity() { companion object { @@ -19,6 +23,7 @@ class PreferencesActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // To my knowledge you have to use getSystemService in activity code supportFragmentManager .beginTransaction() .replace(R.id.settings_container, Preferences()) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a0f5e7..9bd5870 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,12 @@ Toggle tracking Dashboard Duration + Miscellaneous + Do not disturb when tracking + Permissions Required + Please allow Do Not Disturb permissions for this app on the next screen. + OK + Cancel Last week Last two weeks Last month diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 2dde6aa..f295d1a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -74,5 +74,14 @@ android:key="show_rating" android:title="@string/show_rating" /> + + + From 4779b396b6dc4525dc3904fa90cf6c5a4dce4b5f Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 04:36:45 -0500 Subject: [PATCH 3/8] Fix warnings --- app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt | 1 - app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt | 7 ++----- .../java/hu/vmiklos/plees_tracker/PreferencesActivity.kt | 4 ---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index dd7cbe0..47def02 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -14,7 +14,6 @@ import android.content.pm.PackageManager import android.content.res.ColorStateList import android.net.Uri import android.os.Bundle -import android.provider.Settings import android.util.Log import android.view.Menu import android.view.MenuItem diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt index 5ee7efb..deceafd 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt @@ -9,13 +9,10 @@ package hu.vmiklos.plees_tracker import android.app.AlertDialog import android.app.NotificationManager import android.content.Context -import android.content.DialogInterface import android.content.Intent import android.os.Bundle import android.provider.Settings import android.util.Log -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager @@ -93,8 +90,8 @@ class Preferences : PreferenceFragmentCompat() { editor.apply() Log.d(TAG, "Set enable_dnd to false!") // Refresh screen, not the "cleanest way" but it works - preferenceScreen.removeAll(); - addPreferencesFromResource(R.xml.preferences); + preferenceScreen.removeAll() + addPreferencesFromResource(R.xml.preferences) } else { Log.wtf(TAG, "editor is null") } diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt index a81369d..7955e79 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt @@ -6,15 +6,11 @@ package hu.vmiklos.plees_tracker -import android.app.NotificationManager -import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity -import android.provider.Settings -import androidx.activity.result.ActivityResultLauncher class PreferencesActivity : AppCompatActivity() { companion object { From 30235ab3c60e4e20918450e7d2ed32bdcfc56cfa Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 04:56:28 -0500 Subject: [PATCH 4/8] Tied sleep tracker to DND preference and getting last DND state --- .../hu/vmiklos/plees_tracker/MainActivity.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index 47def02..66360d8 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -316,14 +316,18 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { val startStopText = findViewById(R.id.start_stop_text) val dndManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val preferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) + val dndEnabled = preferences.getBoolean("enable_dnd", false) if (DataModel.start != null && DataModel.stop != null) { // When user stops tracking sleep - if (dndManager.isNotificationPolicyAccessGranted) { - dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { + // Restore Do Not Disturb status when user started tracking + dndManager.setInterruptionFilter(preferences.getInt("current_dnd", NotificationManager.INTERRUPTION_FILTER_ALL)) } else { Log.w(TAG, "Failed to disable DND, permissions not enabled") } + status.text = getString(R.string.tracking_stopped) startStop.contentDescription = getString(R.string.start_again) startStop.setImageResource(R.drawable.ic_start) @@ -335,10 +339,14 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { return } + DataModel.start?.let { start -> // When user starts tracking sleep - if (dndManager.isNotificationPolicyAccessGranted) { - dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE) + preferences.edit() + .putInt("current_dnd", dndManager.currentInterruptionFilter) + .apply() // Saves current Do Not Disturb status + if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { + dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) } else { Log.w(TAG, "Failed to enable DND, permissions not enabled") } From b011762c2933010c59b9e36dc1b5c1f9d205a4ca Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 11:52:53 -0500 Subject: [PATCH 5/8] Fix KtLint issues --- .../java/hu/vmiklos/plees_tracker/MainActivity.kt | 3 ++- .../java/hu/vmiklos/plees_tracker/Preferences.kt | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index 66360d8..bfc3f55 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -323,7 +323,8 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { // When user stops tracking sleep if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { // Restore Do Not Disturb status when user started tracking - dndManager.setInterruptionFilter(preferences.getInt("current_dnd", NotificationManager.INTERRUPTION_FILTER_ALL)) + dndManager.setInterruptionFilter(preferences.getInt("current_dnd", + NotificationManager.INTERRUPTION_FILTER_ALL)) } else { Log.w(TAG, "Failed to disable DND, permissions not enabled") } diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt index deceafd..93dd61f 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt @@ -38,7 +38,8 @@ class Preferences : PreferenceFragmentCompat() { if (sharedPreferences != null) { if (sharedPreferences.getBoolean("enable_dnd", false)) { val activity = activity ?: return super.onPreferenceTreeClick(preference) - val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) + as NotificationManager val hasPermission = dndManager.isNotificationPolicyAccessGranted if (!hasPermission) { @@ -46,11 +47,14 @@ class Preferences : PreferenceFragmentCompat() { AlertDialog.Builder(context) .setTitle(R.string.settings_enable_dnd_question_title) .setMessage(R.string.settings_enable_dnd_question_message) - .setPositiveButton(R.string.settings_enable_dnd_question_ok) { _, _ -> - val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + .setPositiveButton( + R.string.settings_enable_dnd_question_ok) { _, _ -> + val intent = Intent( + Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) startActivity(intent) } - .setNegativeButton(R.string.settings_enable_dnd_question_cancel) { _, _ -> + .setNegativeButton( + R.string.settings_enable_dnd_question_cancel) { _, _ -> val editor = sharedPreferences.edit() if (editor != null) { editor.putBoolean("enable_dnd", false) @@ -78,7 +82,8 @@ class Preferences : PreferenceFragmentCompat() { fun checkDnd() { val activity = activity ?: return - val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) + as NotificationManager val hasPermission = dndManager.isNotificationPolicyAccessGranted val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } From 74f3229ae3ca2400e8f6eebb1a5501c9d91e3726 Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 12:06:56 -0500 Subject: [PATCH 6/8] Fix KtLint issues (2nd try) --- .../hu/vmiklos/plees_tracker/MainActivity.kt | 4 ++-- .../hu/vmiklos/plees_tracker/Preferences.kt | 22 +++++++++---------- app/src/main/res/values/strings.xml | 8 +++---- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index bfc3f55..f8a5347 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -323,8 +323,8 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { // When user stops tracking sleep if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { // Restore Do Not Disturb status when user started tracking - dndManager.setInterruptionFilter(preferences.getInt("current_dnd", - NotificationManager.INTERRUPTION_FILTER_ALL)) + val filterAll = NotificationManager.INTERRUPTION_FILTER_ALL + dndManager.setInterruptionFilter(preferences.getInt("current_dnd", filterAll)) } else { Log.w(TAG, "Failed to disable DND, permissions not enabled") } diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt index 93dd61f..9c258dd 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt @@ -38,23 +38,21 @@ class Preferences : PreferenceFragmentCompat() { if (sharedPreferences != null) { if (sharedPreferences.getBoolean("enable_dnd", false)) { val activity = activity ?: return super.onPreferenceTreeClick(preference) - val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) - as NotificationManager + val noteServ = Context.NOTIFICATION_SERVICE // 100 char limit + val dndManager = activity.getSystemService(noteServ) as NotificationManager val hasPermission = dndManager.isNotificationPolicyAccessGranted if (!hasPermission) { // If we don't have permissions for DND AlertDialog.Builder(context) - .setTitle(R.string.settings_enable_dnd_question_title) - .setMessage(R.string.settings_enable_dnd_question_message) - .setPositiveButton( - R.string.settings_enable_dnd_question_ok) { _, _ -> - val intent = Intent( - Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + .setTitle(R.string.settings_enable_dnd_q_title) + .setMessage(R.string.settings_enable_dnd_q_message) + .setPositiveButton(R.string.settings_enable_dnd_q_ok) { _, _ -> + val setting_id = Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS + val intent = Intent(setting_id) startActivity(intent) } - .setNegativeButton( - R.string.settings_enable_dnd_question_cancel) { _, _ -> + .setNegativeButton(R.string.settings_enable_dnd_q_cancel) { _, _ -> val editor = sharedPreferences.edit() if (editor != null) { editor.putBoolean("enable_dnd", false) @@ -82,8 +80,8 @@ class Preferences : PreferenceFragmentCompat() { fun checkDnd() { val activity = activity ?: return - val dndManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) - as NotificationManager + val noteServ = Context.NOTIFICATION_SERVICE // 100 char limit + val dndManager = activity.getSystemService(noteServ) as NotificationManager val hasPermission = dndManager.isNotificationPolicyAccessGranted val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9bd5870..8e4ccd2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -65,10 +65,10 @@ Duration Miscellaneous Do not disturb when tracking - Permissions Required - Please allow Do Not Disturb permissions for this app on the next screen. - OK - Cancel + Permissions Required + Please allow Do Not Disturb permissions for this app on the next screen. + OK + Cancel Last week Last two weeks Last month From 1b55f7b8cadeb7a1ef4a14b90c050ceb249bb951 Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Tue, 20 Feb 2024 12:33:48 -0500 Subject: [PATCH 7/8] DND Documentation --- guide/src/usage.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/guide/src/usage.md b/guide/src/usage.md index 7dcadeb..dbdfba7 100644 --- a/guide/src/usage.md +++ b/guide/src/usage.md @@ -99,6 +99,12 @@ The past sleeps section allow configuring the contents of the individual sleep c The sleep cards are not re-created when changing settings, so you need to restart plees-tracker to see the effect. +### Do not disturb when tracking + +This option enables automatic activation of DND (Do Not Disturb) mode when you start tracking your sleep. When toggled on for the first time, you will be prompted to grant Plees Tracker permissions to modify DND settings. + +Upon ceasing sleep tracking, the DND setting you had enabled prior to initiating the tracking will be restored. + ## Sleep activity The sleep activity allows modifying the start, stop time or rating of a single recorded sleep, From e9e35aafb860ef52986a232cc4dfb14923cd99f0 Mon Sep 17 00:00:00 2001 From: Mason Fisher Date: Wed, 21 Feb 2024 07:34:03 -0500 Subject: [PATCH 8/8] Implement vmiklos' suggestions from code review --- .../hu/vmiklos/plees_tracker/MainActivity.kt | 17 ++-- .../hu/vmiklos/plees_tracker/Preferences.kt | 80 ------------------- .../plees_tracker/PreferencesActivity.kt | 1 - .../SharedPreferencesChangeListener.kt | 61 ++++++++++---- 4 files changed, 57 insertions(+), 102 deletions(-) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt index f8a5347..94beaf2 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/MainActivity.kt @@ -321,10 +321,12 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { if (DataModel.start != null && DataModel.stop != null) { // When user stops tracking sleep - if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { - // Restore Do Not Disturb status when user started tracking - val filterAll = NotificationManager.INTERRUPTION_FILTER_ALL - dndManager.setInterruptionFilter(preferences.getInt("current_dnd", filterAll)) + if (dndManager.isNotificationPolicyAccessGranted) { + if (dndEnabled) { + // Restore Do Not Disturb status when user started tracking + val filterAll = NotificationManager.INTERRUPTION_FILTER_ALL + dndManager.setInterruptionFilter(preferences.getInt("current_dnd", filterAll)) + } } else { Log.w(TAG, "Failed to disable DND, permissions not enabled") } @@ -346,8 +348,11 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { preferences.edit() .putInt("current_dnd", dndManager.currentInterruptionFilter) .apply() // Saves current Do Not Disturb status - if (dndManager.isNotificationPolicyAccessGranted and dndEnabled) { - dndManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) + if (dndManager.isNotificationPolicyAccessGranted) { + if (dndEnabled) { + val filterPri = NotificationManager.INTERRUPTION_FILTER_PRIORITY + dndManager.setInterruptionFilter(filterPri) + } } else { Log.w(TAG, "Failed to enable DND, permissions not enabled") } diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt index 9c258dd..b0e5fae 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/Preferences.kt @@ -6,21 +6,11 @@ package hu.vmiklos.plees_tracker -import android.app.AlertDialog -import android.app.NotificationManager -import android.content.Context -import android.content.Intent import android.os.Bundle -import android.provider.Settings -import android.util.Log import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import androidx.preference.PreferenceManager class Preferences : PreferenceFragmentCompat() { - companion object { - private const val TAG = "PreferencesActivity" - } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) val autoBackupPath = findPreference("auto_backup_path") @@ -30,76 +20,6 @@ class Preferences : PreferenceFragmentCompat() { it.summary = path } } - - override fun onPreferenceTreeClick(preference: Preference): Boolean { - val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } - - if (preference.key == "enable_dnd") { // If someone toggled the enable_dnd preference - if (sharedPreferences != null) { - if (sharedPreferences.getBoolean("enable_dnd", false)) { - val activity = activity ?: return super.onPreferenceTreeClick(preference) - val noteServ = Context.NOTIFICATION_SERVICE // 100 char limit - val dndManager = activity.getSystemService(noteServ) as NotificationManager - val hasPermission = dndManager.isNotificationPolicyAccessGranted - - if (!hasPermission) { - // If we don't have permissions for DND - AlertDialog.Builder(context) - .setTitle(R.string.settings_enable_dnd_q_title) - .setMessage(R.string.settings_enable_dnd_q_message) - .setPositiveButton(R.string.settings_enable_dnd_q_ok) { _, _ -> - val setting_id = Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS - val intent = Intent(setting_id) - startActivity(intent) - } - .setNegativeButton(R.string.settings_enable_dnd_q_cancel) { _, _ -> - val editor = sharedPreferences.edit() - if (editor != null) { - editor.putBoolean("enable_dnd", false) - editor.apply() - } else { - Log.wtf(TAG, "editor is null") - } - checkDnd() - } - .create() - .show() - } - } - } else { - Log.wtf(TAG, "sharedPreferences is null") - } - } - return super.onPreferenceTreeClick(preference) - } - - override fun onResume() { - super.onResume() - checkDnd() - } - - fun checkDnd() { - val activity = activity ?: return - val noteServ = Context.NOTIFICATION_SERVICE // 100 char limit - val dndManager = activity.getSystemService(noteServ) as NotificationManager - val hasPermission = dndManager.isNotificationPolicyAccessGranted - - val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } - val editor = sharedPreferences?.edit() - - if (!hasPermission) { - if (editor != null) { - editor.putBoolean("enable_dnd", false) - editor.apply() - Log.d(TAG, "Set enable_dnd to false!") - // Refresh screen, not the "cleanest way" but it works - preferenceScreen.removeAll() - addPreferencesFromResource(R.xml.preferences) - } else { - Log.wtf(TAG, "editor is null") - } - } - } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt index 7955e79..2e016eb 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/PreferencesActivity.kt @@ -19,7 +19,6 @@ class PreferencesActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // To my knowledge you have to use getSystemService in activity code supportFragmentManager .beginTransaction() .replace(R.id.settings_container, Preferences()) diff --git a/app/src/main/java/hu/vmiklos/plees_tracker/SharedPreferencesChangeListener.kt b/app/src/main/java/hu/vmiklos/plees_tracker/SharedPreferencesChangeListener.kt index 666307d..43ad832 100644 --- a/app/src/main/java/hu/vmiklos/plees_tracker/SharedPreferencesChangeListener.kt +++ b/app/src/main/java/hu/vmiklos/plees_tracker/SharedPreferencesChangeListener.kt @@ -6,7 +6,12 @@ package hu.vmiklos.plees_tracker +import android.app.AlertDialog +import android.app.NotificationManager +import android.content.Context +import android.content.Intent import android.content.SharedPreferences +import android.provider.Settings import android.util.Log import androidx.appcompat.app.AppCompatDelegate @@ -16,25 +21,51 @@ class SharedPreferencesChangeListener : SharedPreferences.OnSharedPreferenceChan } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { - if (key == "auto_backup") { - val autoBackup = sharedPreferences.getBoolean("auto_backup", false) - val autoBackupPath = sharedPreferences.getString("auto_backup_path", "") - if (autoBackup) { - if (autoBackupPath.isNullOrEmpty()) { + when (key) { + "auto_backup" -> { + val autoBackup = sharedPreferences.getBoolean("auto_backup", false) + val autoBackupPath = sharedPreferences.getString("auto_backup_path", "") + if (autoBackup) { + if (autoBackupPath.isNullOrEmpty()) { + val preferencesActivity = DataModel.preferencesActivity + if (preferencesActivity != null) { + Log.i(TAG, "onSharedPreferenceChanged: setting new backup path") + preferencesActivity.openFolderChooser() + } + } + } else { + // Forget old path, so it's possible to set a different one later. + Log.i(TAG, "onSharedPreferenceChanged: clearing old backup path") + val editor = DataModel.preferences.edit() + editor.remove("auto_backup_path") + editor.apply() + } + return + } + "enable_dnd" -> { + if (sharedPreferences.getBoolean("enable_dnd", false)) { val preferencesActivity = DataModel.preferencesActivity - if (preferencesActivity != null) { - Log.i(TAG, "onSharedPreferenceChanged: setting new backup path") - preferencesActivity.openFolderChooser() + val noteServ = Context.NOTIFICATION_SERVICE // 100 char limit + val dndManager = preferencesActivity?.getSystemService(noteServ) + as NotificationManager + val hasPermission = dndManager.isNotificationPolicyAccessGranted + + if (!hasPermission) { + // If we don't have permissions for DND + AlertDialog.Builder(preferencesActivity) + .setTitle(R.string.settings_enable_dnd_q_title) + .setMessage(R.string.settings_enable_dnd_q_message) + .setPositiveButton(R.string.settings_enable_dnd_q_ok) { _, _ -> + val settingId = Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS + val intent = Intent(settingId) + preferencesActivity.startActivity(intent) + } + .setNegativeButton(R.string.settings_enable_dnd_q_cancel) { _, _ -> } + .create() + .show() } } - } else { - // Forget old path, so it's possible to set a different one later. - Log.i(TAG, "onSharedPreferenceChanged: clearing old backup path") - val editor = DataModel.preferences.edit() - editor.remove("auto_backup_path") - editor.apply() } - return } applyTheme(sharedPreferences)