Improve alert setup and access guidance

This commit is contained in:
ajp_anton
2026-08-31 01:14:34 +00:00
parent 0a8405e171
commit a7c9a2a22f
8 changed files with 78 additions and 78 deletions
@@ -1,38 +0,0 @@
package se.ajpanton.notificationsmaster
import android.content.ComponentName
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import android.view.View
import androidx.fragment.app.Fragment
import se.ajpanton.notificationsmaster.alerts.AlertConfigurationStore
import se.ajpanton.notificationsmaster.capture.NotificationCaptureService
import se.ajpanton.notificationsmaster.databinding.FragmentAlertStatusBinding
class AlertStatusFragment : Fragment(R.layout.fragment_alert_status) {
private var binding: FragmentAlertStatusBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = FragmentAlertStatusBinding.bind(view)
binding!!.notificationAccess.setOnClickListener { startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)) }
}
override fun onResume() {
super.onResume()
val context = requireContext()
val config = AlertConfigurationStore(context).load()
val access = context.getSystemService(android.app.NotificationManager::class.java)
.isNotificationListenerAccessGranted(ComponentName(context, NotificationCaptureService::class.java))
binding?.status?.text = buildString {
append(if (access) "Notification access is enabled." else "Notification access is disabled.")
append("\n\nCustom alerts are ")
append(if (config.enabled) "enabled" else "disabled")
append(" with ${config.rules.count { it.enabled }} active rule")
append(if (config.rules.count { it.enabled } == 1) "." else "s.")
}
binding?.notificationAccess?.text = if (access) "Notification access enabled" else "Enable notification access"
}
override fun onDestroyView() { binding = null; super.onDestroyView() }
}
@@ -1,12 +1,19 @@
package se.ajpanton.notificationsmaster package se.ajpanton.notificationsmaster
import android.app.NotificationManager
import android.content.ComponentName
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.view.View import android.view.View
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import se.ajpanton.notificationsmaster.alerts.AlertConfigurationStore import se.ajpanton.notificationsmaster.alerts.AlertConfigurationStore
import se.ajpanton.notificationsmaster.alerts.AlertQueueOverflow import se.ajpanton.notificationsmaster.alerts.AlertQueueOverflow
import se.ajpanton.notificationsmaster.alerts.AlertQueueSettings import se.ajpanton.notificationsmaster.alerts.AlertQueueSettings
import se.ajpanton.notificationsmaster.capture.NotificationCaptureService
import se.ajpanton.notificationsmaster.databinding.FragmentAlertsBinding import se.ajpanton.notificationsmaster.databinding.FragmentAlertsBinding
class AlertsFragment : Fragment(R.layout.fragment_alerts) { class AlertsFragment : Fragment(R.layout.fragment_alerts) {
@@ -26,9 +33,28 @@ class AlertsFragment : Fragment(R.layout.fragment_alerts) {
(1..10).map(Int::toString), (1..10).map(Int::toString),
) )
binding!!.queueLength.setSelection(configuration.queueSettings.maximumLength - 1, false) binding!!.queueLength.setSelection(configuration.queueSettings.maximumLength - 1, false)
binding!!.notificationAccess.setOnClickListener {
startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
}
bindChanges() bindChanges()
} }
override fun onResume() {
super.onResume()
val context = requireContext()
val access = context.getSystemService(NotificationManager::class.java)
.isNotificationListenerAccessGranted(ComponentName(context, NotificationCaptureService::class.java))
binding?.notificationAccess?.apply {
text = if (access) "Notification access enabled" else "Enable notification access"
backgroundTintList = ColorStateList.valueOf(
ContextCompat.getColor(
context,
if (access) R.color.notification_access_granted else R.color.notification_access_missing,
),
)
}
}
override fun onDestroyView() { override fun onDestroyView() {
binding = null binding = null
super.onDestroyView() super.onDestroyView()
@@ -163,7 +163,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
page == Page.VIEW_LOGS -> ViewLogsFragment() page == Page.VIEW_LOGS -> ViewLogsFragment()
page == Page.SETTINGS -> SettingsFragment() page == Page.SETTINGS -> SettingsFragment()
page == Page.ALERTS -> AlertsFragment() page == Page.ALERTS -> AlertsFragment()
page == Page.ALERT_STATUS -> AlertStatusFragment()
page == Page.PROFILES -> ProfilesFragment() page == Page.PROFILES -> ProfilesFragment()
page == Page.RULES -> RulesFragment() page == Page.RULES -> RulesFragment()
page == Page.APPS -> AppsFragment() page == Page.APPS -> AppsFragment()
@@ -371,7 +370,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
VIEW_LOGS(R.id.nav_view_logs, R.string.page_view_logs), VIEW_LOGS(R.id.nav_view_logs, R.string.page_view_logs),
SETTINGS(R.id.nav_settings, R.string.page_settings), SETTINGS(R.id.nav_settings, R.string.page_settings),
ALERTS(R.id.nav_alerts, R.string.page_alerts), ALERTS(R.id.nav_alerts, R.string.page_alerts),
ALERT_STATUS(R.id.nav_alert_status, R.string.page_alert_status),
PROFILES(R.id.nav_profiles, R.string.page_profiles), PROFILES(R.id.nav_profiles, R.string.page_profiles),
RULES(R.id.nav_rules, R.string.page_rules), RULES(R.id.nav_rules, R.string.page_rules),
APPS(R.id.nav_apps, R.string.page_apps), APPS(R.id.nav_apps, R.string.page_apps),
@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/page_padding">
<TextView
android:id="@+id/status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp" />
<Button
android:id="@+id/notification_access"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Without optional system integration, Android keeps the source apps own sound and vibration. Matching custom alerts play in addition; they do not replace it."
android:textSize="14sp" />
</LinearLayout>
</ScrollView>
+50 -1
View File
@@ -9,6 +9,40 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="@dimen/page_padding"> android:padding="@dimen/page_padding">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Notification access"
android:textAppearance="?attr/textAppearanceHeadline6" />
<com.google.android.material.button.MaterialButton
android:id="@+id/notification_access"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/on_primary" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Notification access lets Notifications Master detect notifications and play matching custom alerts."
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="To replace an apps original sound and vibration, enable Notifications Master in LSPosed with the Android/system server scope, then restart Android. Without this integration, custom alerts play in addition to the apps native alert."
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Custom alerts"
android:textAppearance="?attr/textAppearanceHeadline6" />
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enable_alerts" android:id="@+id/enable_alerts"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -22,11 +56,26 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:text="Ignore detected routine updates" /> android:text="Ignore detected routine updates" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Detected routine updates are notification edits Android identifies as chronometer or progress changes, such as timers and download counters. Ignoring them prevents repeated custom alerts as those values change."
android:textSize="14sp" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="Queue" /> android:text="Alert queue"
android:textAppearance="?attr/textAppearanceHeadline6" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="The queue contains the alert currently playing and any alerts waiting behind it. It usually grows when an alert set to play to completion prevents a new alert from interrupting it."
android:textSize="14sp" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
-3
View File
@@ -9,9 +9,6 @@
<item <item
android:id="@+id/nav_alerts" android:id="@+id/nav_alerts"
android:title="@string/navigation_alerts_header" /> android:title="@string/navigation_alerts_header" />
<item
android:id="@+id/nav_alert_status"
android:title="@string/navigation_indented_alert_status" />
<item <item
android:id="@+id/nav_profiles" android:id="@+id/nav_profiles"
android:title="@string/navigation_indented_profiles" /> android:title="@string/navigation_indented_profiles" />
+2
View File
@@ -17,6 +17,8 @@
<color name="app_filter_override_icon">#34588E</color> <color name="app_filter_override_icon">#34588E</color>
<color name="visibility_hidden_cross">#B00020</color> <color name="visibility_hidden_cross">#B00020</color>
<color name="visibility_edited_background">#183B5C9C</color> <color name="visibility_edited_background">#183B5C9C</color>
<color name="notification_access_granted">#2E7D32</color>
<color name="notification_access_missing">#B3261E</color>
<color name="launcher_icon_background">#D9E2FF</color> <color name="launcher_icon_background">#D9E2FF</color>
<color name="launcher_icon_foreground">#10264F</color> <color name="launcher_icon_foreground">#10264F</color>
</resources> </resources>
-2
View File
@@ -10,7 +10,6 @@
<string name="page_view_logs">View logs</string> <string name="page_view_logs">View logs</string>
<string name="page_settings">Settings</string> <string name="page_settings">Settings</string>
<string name="page_alerts">Alerts</string> <string name="page_alerts">Alerts</string>
<string name="page_alert_status">Alert status</string>
<string name="debug_notifications_description">Post up to 50 real, silent notifications to test icon filtering and layout.</string> <string name="debug_notifications_description">Post up to 50 real, silent notifications to test icon filtering and layout.</string>
<string name="debug_cycle_notifications">Cycle between zero and the selected count every two seconds</string> <string name="debug_cycle_notifications">Cycle between zero and the selected count every two seconds</string>
<string name="debug_reset_notifications">Reset</string> <string name="debug_reset_notifications">Reset</string>
@@ -26,7 +25,6 @@
<string name="page_log_display">Log display</string> <string name="page_log_display">Log display</string>
<string name="page_filter_logging">Filter logging</string> <string name="page_filter_logging">Filter logging</string>
<string name="navigation_indented_log_display">&#160;&#160;&#160;&#160;Log display</string> <string name="navigation_indented_log_display">&#160;&#160;&#160;&#160;Log display</string>
<string name="navigation_indented_alert_status">&#160;&#160;&#160;&#160;Alert status</string>
<string name="navigation_indented_profiles">&#160;&#160;&#160;&#160;Profiles</string> <string name="navigation_indented_profiles">&#160;&#160;&#160;&#160;Profiles</string>
<string name="navigation_indented_rules">&#160;&#160;&#160;&#160;Rules</string> <string name="navigation_indented_rules">&#160;&#160;&#160;&#160;Rules</string>
<string name="navigation_indented_apps">&#160;&#160;&#160;&#160;Apps</string> <string name="navigation_indented_apps">&#160;&#160;&#160;&#160;Apps</string>