Skip to content

Commit

Permalink
Notification sound even when muted or on DnD
Browse files Browse the repository at this point in the history
  • Loading branch information
Futsch1 committed Feb 25, 2025
1 parent d90f789 commit 7ee3151
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 4 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
android:name="android.permission.ACCESS_NETWORK_STATE"
tools:node="remove" />
<uses-permission android:name="com.futsch1.medtimer.NOTIFICATION_PROCESSED" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />

<application
android:allowBackup="false"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/futsch1/medtimer/ActivityCodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ActivityCodes {
public static final String EXTRA_REMAINING_REPEATS = "com.futsch1.medTimer.EXTRA_REMAINING_REPEATS";
public static final String EXTRA_AMOUNT = "com.futsch1.medTimer.AMOUNT";
public static final String EXTRA_MEDICINE_ID = "com.futsch1.medTimer.MEDICINE_ID";
public static final String EXTRA_RINGER_MODE = "com.futsch1.medTimer.RINGER_MODE";

public static final String REMINDER_ACTION = "com.futsch1.medTimer.REMINDER_ACTION";
public static final String DISMISSED_ACTION = "com.futsch1.medTimer.DISMISSED_ACTION";
Expand Down
35 changes: 34 additions & 1 deletion app/src/main/java/com/futsch1/medtimer/PreferencesFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
Expand Down Expand Up @@ -75,6 +76,15 @@ private void setupNotificationSettings() {
if (preference != null) {
setupNotificationSettingsPreference(preference, ReminderNotificationChannelManager.Importance.DEFAULT);
}
preference = getPreferenceScreen().findPreference(PreferencesNames.OVERRIDE_DND);
if (preference != null) {
preference.setOnPreferenceChangeListener((preference1, value) -> {
if (Boolean.TRUE.equals(value)) {
showDndPermissions();
}
return true;
});
}
}

private void setupPreferencesLink(String preferenceKey, @IdRes int actionId) {
Expand Down Expand Up @@ -112,7 +122,7 @@ private void showExactReminderDialog() {
builder.setMessage(R.string.enable_alarm_dialog).
setPositiveButton(R.string.ok, (dialog, id) -> {
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
requireContext().startActivity(intent);
startActivity(intent);
}).
setNegativeButton(R.string.cancel, (dialog, id) -> {
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit().putBoolean(PreferencesNames.EXACT_REMINDERS, false).apply();
Expand All @@ -136,6 +146,24 @@ private void setupNotificationSettingsPreference(Preference preference, Reminder
);
}

private void showDndPermissions() {
if (!requireContext().getSystemService(NotificationManager.class).isNotificationPolicyAccessGranted()) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.enable_dnd_dialog).
setPositiveButton(R.string.ok, (dialog, id) -> {
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}).
setNegativeButton(R.string.cancel, (dialog, id) -> {
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit().putBoolean(PreferencesNames.OVERRIDE_DND, false).apply();
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.root_preferences);
});
AlertDialog d = builder.create();
d.show();
}
}

@Override
public void onResume() {
super.onResume();
Expand All @@ -146,6 +174,11 @@ public void onResume() {
preference.setChecked(false);
}
}

preference = getPreferenceScreen().findPreference(PreferencesNames.OVERRIDE_DND);
if (preference != null && !requireContext().getSystemService(NotificationManager.class).isNotificationPolicyAccessGranted()) {
preference.setChecked(false);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class PreferencesNames {
public static final String REPEAT_REMINDERS = "repeat_reminders";
public static final String NUMBER_OF_REPETITIONS = "repeat_reminders_repetitions";
public static final String REPEAT_DELAY = "repeat_reminders_delay";
public static final String OVERRIDE_DND = "override_dnd";

private PreferencesNames() {
// Intended empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class ReminderNotificationChannel(
private var notificationChannel: NotificationChannel =
getOrCreateChannel()

init {
notificationChannel.setBypassDnd(true)
}

private fun getOrCreateChannel(): NotificationChannel {
return notificationManager.getNotificationChannel(importance.toString()) ?: createChannel()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.futsch1.medtimer.reminders

import android.app.NotificationManager
import android.content.Context
import android.media.AudioManager
import android.os.Handler
import android.os.Looper
import androidx.preference.PreferenceManager
import com.futsch1.medtimer.PreferencesNames

class NotificationSoundManager(val context: Context) {
private val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val audioManager: AudioManager =
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager

init {
if (notificationManager.isNotificationPolicyAccessGranted()) {
if (PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(PreferencesNames.OVERRIDE_DND, false)
) {
loadPendingRingerMode(audioManager, notificationManager)
} else {
notificationManager.notificationPolicy = NotificationManager.Policy(
0,
NotificationManager.Policy.PRIORITY_SENDERS_ANY,
NotificationManager.Policy.PRIORITY_SENDERS_ANY
)

}
}
}

fun restore() {
restorePendingRingerMode(audioManager)
}

companion object {
private var pending = false
private var pendingWasMuted = false
private var scheduledRunnable: Runnable? = null
private val handler = Handler(Looper.getMainLooper())

@Synchronized
fun loadPendingRingerMode(
audioManager: AudioManager,
notificationManager: NotificationManager
) {
if (!pending) {
pending = true
if (audioManager.isStreamMute(AudioManager.STREAM_RING) && notificationManager.currentInterruptionFilter == NotificationManager.INTERRUPTION_FILTER_ALL) {
audioManager.adjustStreamVolume(
AudioManager.STREAM_RING,
AudioManager.ADJUST_UNMUTE,
0
)
pendingWasMuted = true
}
notificationManager.notificationPolicy = NotificationManager.Policy(
NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS,
NotificationManager.Policy.PRIORITY_SENDERS_ANY,
NotificationManager.Policy.PRIORITY_SENDERS_ANY,
0
)
}
}

@Synchronized
fun restorePendingRingerMode(
audioManager: AudioManager
) {
if (pending) {
if (scheduledRunnable == null) {
scheduledRunnable = Runnable {
if (pendingWasMuted) {
audioManager.adjustStreamVolume(
AudioManager.STREAM_RING,
AudioManager.ADJUST_MUTE,
0
)
audioManager.ringerMode = AudioManager.RINGER_MODE_VIBRATE
}
pending = false
scheduledRunnable = null
}
}
handler.postDelayed(scheduledRunnable!!, 5000)
} else {
handler.removeCallbacks(scheduledRunnable!!)
handler.postDelayed(scheduledRunnable!!, 5000)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.futsch1.medtimer.reminders;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
Expand Down Expand Up @@ -43,7 +44,6 @@ public int showNotification(String remindTime, FullMedicine medicine, Reminder r
int notificationId = getNextNotificationId();
ReminderNotificationChannelManager.Importance importance = (medicine.medicine.notificationImportance == ReminderNotificationChannelManager.Importance.HIGH.getValue()) ? ReminderNotificationChannelManager.Importance.HIGH : ReminderNotificationChannelManager.Importance.DEFAULT;
Color color = medicine.medicine.useColor ? Color.valueOf(medicine.medicine.color) : null;
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);

PendingIntent contentIntent = getStartAppIntent(notificationId);

Expand All @@ -53,6 +53,7 @@ public int showNotification(String remindTime, FullMedicine medicine, Reminder r
.setContentTitle(context.getString(R.string.notification_title))
.setContentText(getNotificationString(remindTime, reminder, medicine))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_REMINDER)
.setContentIntent(contentIntent);
if (medicine.medicine.iconId != 0) {
MedicineIcons icons = new MedicineIcons(context);
Expand All @@ -64,7 +65,7 @@ public int showNotification(String remindTime, FullMedicine medicine, Reminder r

buildActions(builder, notificationId, reminderEvent.reminderEventId, reminder);

notificationManager.notify(notificationId, builder.build());
notify(notificationId, builder.build());
Log.d(LogTags.REMINDER, String.format("Created notification %d", notificationId));

return notificationId;
Expand Down Expand Up @@ -130,6 +131,16 @@ private void buildActions(NotificationCompat.Builder builder, int notificationId
}
}

private void notify(int notificationId, Notification notification) {
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);

NotificationSoundManager soundManager = new NotificationSoundManager(context);

notificationManager.notify(notificationId, notification);

soundManager.restore();
}

private PendingIntent getSnoozePendingIntent(Context context, int reminderId, int reminderEventId, int notificationId, int snoozeTime) {
if (snoozeTime == -1) {
Intent snooze = ReminderProcessor.getCustomSnoozeActionIntent(context, reminderId, reminderEventId, notificationId);
Expand Down Expand Up @@ -176,5 +187,4 @@ public void showOutOfStockNotification(Medicine medicine) {
notificationManager.notify(notificationId, builder.build());
Log.d(LogTags.REMINDER, String.format("Created notification %d", notificationId));
}

}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,7 @@
<string name="are_you_sure_delete_tag">Are you sure to delete the tag?</string>
<string name="unit">Unit</string>
<string name="unlimited">Unlimited</string>
<string name="override_dnd">Always play notification sound</string>
<string name="override_dnd_summary">Plays notifications sound if only vibrate is on or do not disturb with not vibrate or muted</string>
<string name="enable_dnd_dialog">In order to allow always playing notification sounds, enable Do not disturb access for MedTimer in the following menu</string>
</resources>
7 changes: 7 additions & 0 deletions app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
android:layout_height="wrap_content"
android:title="@string/notification_settings_high"
app:key="notification_settings_high" />
<SwitchPreferenceCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="false"
android:summary="@string/override_dnd_summary"
android:title="@string/override_dnd"
app:key="override_dnd" />
<ListPreference
android:defaultValue="0"
android:entries="@array/dismiss_notification_action"
Expand Down

0 comments on commit 7ee3151

Please sign in to comment.