1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-30 22:12:55 +01:00

Allow configuration of notification times

This commit is contained in:
José Rebelo 2024-07-13 19:44:41 +01:00 committed by José Rebelo
parent dc0b044977
commit 20f4248e1c
5 changed files with 112 additions and 12 deletions

View File

@ -22,14 +22,12 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */ along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.externalevents; package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.app.ActivityManager;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -53,6 +51,7 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.time.LocalTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -81,6 +80,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil; import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue; import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
import nodomain.freeyourgadget.gadgetbridge.util.MediaManager; import nodomain.freeyourgadget.gadgetbridge.util.MediaManager;
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils; import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
@ -120,8 +120,8 @@ public class NotificationListener extends NotificationListenerService {
add("mikado.bizcalpro"); add("mikado.bizcalpro");
}}; }};
public static ArrayList<String> notificationStack = new ArrayList<>(); public static final ArrayList<String> notificationStack = new ArrayList<>();
private static ArrayList<Integer> notificationsActive = new ArrayList<Integer>(); private static final ArrayList<Integer> notificationsActive = new ArrayList<>();
private long activeCallPostTime; private long activeCallPostTime;
private int mLastCallCommand = CallSpec.CALL_UNDEFINED; private int mLastCallCommand = CallSpec.CALL_UNDEFINED;
@ -130,7 +130,7 @@ public class NotificationListener extends NotificationListenerService {
private Runnable mSetMusicInfoRunnable = null; private Runnable mSetMusicInfoRunnable = null;
private Runnable mSetMusicStateRunnable = null; private Runnable mSetMusicStateRunnable = null;
private GoogleMapsNotificationHandler googleMapsNotificationHandler = new GoogleMapsNotificationHandler(); private final GoogleMapsNotificationHandler googleMapsNotificationHandler = new GoogleMapsNotificationHandler();
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@ -163,8 +163,8 @@ public class NotificationListener extends NotificationListenerService {
if (pi != null) { if (pi != null) {
pi.send(); pi.send();
} }
} catch (PendingIntent.CanceledException e) { } catch (final PendingIntent.CanceledException e) {
e.printStackTrace(); LOG.error("Failed to open notification {}", sbn.getId());
} }
} }
} }
@ -176,7 +176,7 @@ public class NotificationListener extends NotificationListenerService {
LOG.info("could not lookup handle for mute action"); LOG.info("could not lookup handle for mute action");
break; break;
} }
LOG.info("going to mute " + packageName); LOG.info("going to mute {}", packageName);
if (GBApplication.getPrefs().getString("notification_list_is_blacklist", "true").equals("true")) { if (GBApplication.getPrefs().getString("notification_list_is_blacklist", "true").equals("true")) {
GBApplication.addAppToNotifBlacklist(packageName); GBApplication.addAppToNotifBlacklist(packageName);
} else { } else {
@ -206,6 +206,10 @@ public class NotificationListener extends NotificationListenerService {
String reply = intent.getStringExtra("reply"); String reply = intent.getStringExtra("reply");
if (wearableAction != null) { if (wearableAction != null) {
PendingIntent actionIntent = wearableAction.getActionIntent(); PendingIntent actionIntent = wearableAction.getActionIntent();
if (actionIntent == null) {
LOG.warn("Action intent is null");
break;
}
Intent localIntent = new Intent(); Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (wearableAction.getRemoteInputs() != null && wearableAction.getRemoteInputs().length > 0) { if (wearableAction.getRemoteInputs() != null && wearableAction.getRemoteInputs().length > 0) {
@ -218,8 +222,8 @@ public class NotificationListener extends NotificationListenerService {
LOG.info("will send exec intent to remote application"); LOG.info("will send exec intent to remote application");
actionIntent.send(context, 0, localIntent); actionIntent.send(context, 0, localIntent);
mActionLookup.remove(handle); mActionLookup.remove(handle);
} catch (PendingIntent.CanceledException e) { } catch (final PendingIntent.CanceledException e) {
LOG.warn("replyToLastNotification error: " + e.getLocalizedMessage()); LOG.warn("replyToLastNotification error", e);
} }
} else { } else {
LOG.warn("Received ACTION_REPLY but cannot find the corresponding wearableAction"); LOG.warn("Received ACTION_REPLY but cannot find the corresponding wearableAction");
@ -264,7 +268,11 @@ public class NotificationListener extends NotificationListenerService {
if (isServiceNotRunningAndShouldIgnoreNotifications()) return; if (isServiceNotRunningAndShouldIgnoreNotifications()) return;
final Prefs prefs = GBApplication.getPrefs(); final GBPrefs prefs = GBApplication.getPrefs();
if (isOutsideNotificationTimes(prefs)) {
return;
}
final boolean ignoreWorkProfile = prefs.getBoolean("notifications_ignore_work_profile", false); final boolean ignoreWorkProfile = prefs.getBoolean("notifications_ignore_work_profile", false);
if (ignoreWorkProfile && isWorkProfile(sbn)) { if (ignoreWorkProfile && isWorkProfile(sbn)) {
@ -458,6 +466,30 @@ public class NotificationListener extends NotificationListenerService {
GBApplication.deviceService().onNotification(notificationSpec); GBApplication.deviceService().onNotification(notificationSpec);
} }
private static boolean isOutsideNotificationTimes(final GBPrefs prefs) {
if (!prefs.getNotificationTimesEnabled()) {
return false;
}
final LocalTime now = LocalTime.now();
final LocalTime start = prefs.getNotificationTimesStart();
final LocalTime end = prefs.getNotificationTimesEnd();
final boolean shouldIgnore;
if (start.isBefore(end)) {
// eg. 06:00 -> 22:00
shouldIgnore = now.isAfter(start) && now.isBefore(end);
} else {
// goes past midnight, eg. 22:00 -> 06:00
shouldIgnore = now.isAfter(start) || now.isBefore(end);
}
if (shouldIgnore) {
LOG.debug("Ignoring notification outside of notification times {}/{}", start, end);
}
return shouldIgnore;
}
private boolean checkNotificationContentForWhiteAndBlackList(String packageName, String body) { private boolean checkNotificationContentForWhiteAndBlackList(String packageName, String body) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -707,7 +739,11 @@ public class NotificationListener extends NotificationListenerService {
if (isServiceNotRunningAndShouldIgnoreNotifications()) return; if (isServiceNotRunningAndShouldIgnoreNotifications()) return;
final Prefs prefs = GBApplication.getPrefs(); final GBPrefs prefs = GBApplication.getPrefs();
if (isOutsideNotificationTimes(prefs)) {
return;
}
final boolean ignoreWorkProfile = prefs.getBoolean("notifications_ignore_work_profile", false); final boolean ignoreWorkProfile = prefs.getBoolean("notifications_ignore_work_profile", false);
if (ignoreWorkProfile && isWorkProfile(sbn)) { if (ignoreWorkProfile && isWorkProfile(sbn)) {

View File

@ -31,6 +31,7 @@ import android.util.Log;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import java.text.ParseException; import java.text.ParseException;
import java.time.LocalTime;
import java.util.Date; import java.util.Date;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -153,4 +154,16 @@ public class GBPrefs extends Prefs {
} }
return new float[]{longitude, latitude}; return new float[]{longitude, latitude};
} }
public boolean getNotificationTimesEnabled() {
return getBoolean("notification_times_enabled", false);
}
public LocalTime getNotificationTimesStart() {
return getLocalTime("notification_times_start", "08:00");
}
public LocalTime getNotificationTimesEnd() {
return getLocalTime("notification_times_end", "22:00");
}
} }

View File

@ -21,8 +21,11 @@ import android.util.Log;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -178,6 +181,7 @@ public class Prefs {
return getList(key, defaultValue, ","); return getList(key, defaultValue, ",");
} }
@Deprecated // use getLocalTime
public Date getTimePreference(final String key, final String defaultValue) { public Date getTimePreference(final String key, final String defaultValue) {
final String time = getString(key, defaultValue); final String time = getString(key, defaultValue);
@ -191,6 +195,23 @@ public class Prefs {
return new Date(); return new Date();
} }
public LocalTime getLocalTime(final String key, final String defaultValue) {
final String time = getString(key, defaultValue);
final DateFormat df = new SimpleDateFormat("HH:mm", Locale.ROOT);
try {
final Date parse = df.parse(time);
final Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime(parse);
return LocalTime.of(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), 0);
} catch (final Exception e) {
Log.e(TAG, "Error reading localtime preference value: " + key + "; returning default current time", e); // log the first exception
}
return LocalTime.now();
}
private void logReadError(String key, Exception ex) { private void logReadError(String key, Exception ex) {
Log.e(TAG, "Error reading preference value: " + key + "; returning default value", ex); // log the first exception Log.e(TAG, "Error reading preference value: " + key + "; returning default value", ex); // log the first exception
} }

View File

@ -269,6 +269,8 @@
<string name="pref_summary_notification_cache_while_disconnected">Send missed notifications when a device reconnects after being out of range</string> <string name="pref_summary_notification_cache_while_disconnected">Send missed notifications when a device reconnects after being out of range</string>
<string name="pref_title_notification_filter">Do Not Disturb</string> <string name="pref_title_notification_filter">Do Not Disturb</string>
<string name="pref_summary_notification_filter">Block all notifications when Do Not Disturb is enabled on the phone</string> <string name="pref_summary_notification_filter">Block all notifications when Do Not Disturb is enabled on the phone</string>
<string name="pref_title_notification_times_enabled">Notification times</string>
<string name="pref_summary_notification_times_enabled">Only send notifications between specific times</string>
<string name="pref_title_notification_media_ignores_application_list">Media notifications ignore app list</string> <string name="pref_title_notification_media_ignores_application_list">Media notifications ignore app list</string>
<string name="pref_summary_notification_media_ignores_application_list">Process media notifications before the app list. If this preference is unchecked, media applications need to be allowed in the application list for media controls to work on the device.</string> <string name="pref_summary_notification_media_ignores_application_list">Process media notifications before the app list. If this preference is unchecked, media applications need to be allowed in the application list for media controls to work on the device.</string>
<string name="pref_header_notification_application_settings">Per application settings</string> <string name="pref_header_notification_application_settings">Per application settings</string>

View File

@ -130,6 +130,34 @@
android:summary="@string/pref_summary_notification_filter" android:summary="@string/pref_summary_notification_filter"
android:title="@string/pref_title_notification_filter" android:title="@string/pref_title_notification_filter"
app:iconSpaceReserved="false" /> app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_title_notification_times_enabled"
app:iconSpaceReserved="false">
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="notification_times_enabled"
android:layout="@layout/preference_checkbox"
android:summary="@string/pref_summary_notification_times_enabled"
android:title="@string/pref_title_notification_times_enabled"
app:iconSpaceReserved="false" />
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
android:defaultValue="08:00"
android:dependency="notification_times_enabled"
android:key="notification_times_start"
android:title="@string/mi2_prefs_do_not_disturb_start"
app:iconSpaceReserved="false"/>
<nodomain.freeyourgadget.gadgetbridge.util.XTimePreference
android:defaultValue="22:00"
android:dependency="notification_times_enabled"
android:key="notification_times_end"
android:title="@string/mi2_prefs_do_not_disturb_end"
app:iconSpaceReserved="false"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory