emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d7ded996082 2/2: Implement notification residency on Android


From: Po Lu
Subject: master d7ded996082 2/2: Implement notification residency on Android
Date: Mon, 11 Mar 2024 21:49:12 -0400 (EDT)

branch: master
commit d7ded996082503ca00546c220c7ce8d96e16b76a
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Implement notification residency on Android
    
    * doc/lispref/os.texi (Desktop Notifications): Document support
    for `:resident'.
    
    * java/org/gnu/emacs/EmacsService.java (cancelNotification):
    
    * src/android.c (android_init_emacs_service):
    
    * src/android.h (struct android_emacs_service): New function.
    
    * src/androidselect.c (android_notifications_notify_1)
    (Fandroid_notifications_notify): New parameter QCresident; save
    it within notification lists.
    (android_notification_deleted, android_notification_action):
    Adjust for changes to the format of notification lists and
    cancel non-resident notifications when an action is selected.
    (syms_of_androidselect): <QCresident>: New symbol.
---
 doc/lispref/os.texi                  |  6 ++--
 java/org/gnu/emacs/EmacsService.java | 25 ++++++++++++++++
 src/android.c                        |  2 ++
 src/android.h                        |  1 +
 src/androidselect.c                  | 55 ++++++++++++++++++++++++++++--------
 5 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index ecd88a39489..65c5ed2b4cc 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -3244,11 +3244,13 @@ of parameters analogous to its namesake in
 @item :on-action @var{on-action}
 @item :on-cancel @var{on-cancel}
 @item :actions @var{actions}
+@item :resident @var{resident}
 These have the same meaning as they do when used in calls to
-@code{notifications-notify}.
+@code{notifications-notify}, except that no more than three non-default
+actions will be displayed.
 
 @item :urgency @var{urgency}
-The set of values for @var{urgency} is the same as with
+The set of accepted values for @var{urgency} is the same as with
 @code{notifications-notify}, but the urgency applies to all
 notifications displayed with the defined @var{group}, except under
 Android 7.1 and earlier.
diff --git a/java/org/gnu/emacs/EmacsService.java 
b/java/org/gnu/emacs/EmacsService.java
index d17ba597d8e..9bc40d63311 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -1967,4 +1967,29 @@ public final class EmacsService extends Service
     else
       requestStorageAccess30 ();
   }
+
+
+
+  /* Notification miscellany.  */
+
+  /* Cancel any notification displayed with the tag TAG.  */
+
+  public void
+  cancelNotification (final String string)
+  {
+    Object tem;
+    final NotificationManager manager;
+
+    tem = getSystemService (Context.NOTIFICATION_SERVICE);
+    manager = (NotificationManager) tem;
+
+    runOnUiThread (new Runnable () {
+       @Override
+       public void
+       run ()
+       {
+         manager.cancel (string, 2);
+       }
+      });
+  }
 };
diff --git a/src/android.c b/src/android.c
index 125bb5209c3..dcd5c6d99c7 100644
--- a/src/android.c
+++ b/src/android.c
@@ -1688,6 +1688,8 @@ android_init_emacs_service (void)
               "externalStorageAvailable", "()Z");
   FIND_METHOD (request_storage_access,
               "requestStorageAccess", "()V");
+  FIND_METHOD (cancel_notification,
+              "cancelNotification", "(Ljava/lang/String;)V");
 #undef FIND_METHOD
 }
 
diff --git a/src/android.h b/src/android.h
index ee634a3e76c..2ca3d7e1446 100644
--- a/src/android.h
+++ b/src/android.h
@@ -302,6 +302,7 @@ struct android_emacs_service
   jmethodID valid_authority;
   jmethodID external_storage_available;
   jmethodID request_storage_access;
+  jmethodID cancel_notification;
 };
 
 extern JNIEnv *android_java_env;
diff --git a/src/androidselect.c b/src/androidselect.c
index 04f4cf1573f..bcb7bcd2c3b 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -567,15 +567,15 @@ android_locate_icon (const char *name)
 }
 
 /* Display a desktop notification with the provided TITLE, BODY,
-   REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, ACTION_CB and CANCEL_CB.
-   Return an identifier for the resulting notification.  */
+   REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, RESIDENT, ACTION_CB and
+   CANCEL_CB.  Return an identifier for the resulting notification.  */
 
 static intmax_t
 android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
                                Lisp_Object replaces_id,
                                Lisp_Object group, Lisp_Object icon,
                                Lisp_Object urgency, Lisp_Object actions,
-                               Lisp_Object action_cb,
+                               Lisp_Object resident, Lisp_Object action_cb,
                                Lisp_Object cancel_cb)
 {
   static intmax_t counter;
@@ -740,8 +740,9 @@ android_notifications_notify_1 (Lisp_Object title, 
Lisp_Object body,
 
   /* If callbacks are provided, save them into notification_table. */
 
-  if (!NILP (action_cb) || !NILP (cancel_cb))
-    Fputhash (build_string (identifier), Fcons (action_cb, cancel_cb),
+  if (!NILP (action_cb) || !NILP (cancel_cb) || !NILP (resident))
+    Fputhash (build_string (identifier), list3 (action_cb, cancel_cb,
+                                               resident),
              notification_table);
 
   /* Return the ID.  */
@@ -755,12 +756,12 @@ ARGS must contain keywords followed by values.  Each of 
the following
 keywords is understood:
 
   :title       The notification title.
-  :body        The notification body.
+  :body                The notification body.
   :replaces-id The ID of a previous notification to supersede.
   :group       The notification group, or nil.
   :urgency     One of the symbols `low', `normal' or `critical',
                defining the importance of the notification group.
-  :icon        The name of a drawable resource to display as the
+  :icon                The name of a drawable resource to display as the
                notification's icon.
   :actions     A list of actions of the form:
                  (KEY TITLE KEY TITLE ...)
@@ -770,6 +771,8 @@ keywords is understood:
                its existence is implied, and its TITLE is ignored.
                No more than three actions can be defined, not
                counting any action with "default" as its key.
+  :resident     When set the notification will not be automatically
+               dismissed when it or an action is selected.
   :on-action   Function to call when an action is invoked.
                The notification id and the key of the action are
                provided as arguments to the function.
@@ -811,7 +814,7 @@ this function.
 usage: (android-notifications-notify &rest ARGS) */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  Lisp_Object title, body, replaces_id, group, urgency;
+  Lisp_Object title, body, replaces_id, group, urgency, resident;
   Lisp_Object icon;
   Lisp_Object key, value, actions, action_cb, cancel_cb;
   ptrdiff_t i;
@@ -821,7 +824,7 @@ usage: (android-notifications-notify &rest ARGS) */)
 
   /* Clear each variable above.  */
   title = body = replaces_id = group = icon = urgency = actions = Qnil;
-  action_cb = cancel_cb = Qnil;
+  resident = action_cb = cancel_cb = Qnil;
 
   /* If NARGS is odd, error.  */
 
@@ -849,6 +852,8 @@ usage: (android-notifications-notify &rest ARGS) */)
        icon = value;
       else if (EQ (key, QCactions))
        actions = value;
+      else if (EQ (key, QCresident))
+       resident = value;
       else if (EQ (key, QCon_action))
        action_cb = value;
       else if (EQ (key, QCon_cancel))
@@ -878,8 +883,8 @@ usage: (android-notifications-notify &rest ARGS) */)
 
   return make_int (android_notifications_notify_1 (title, body, replaces_id,
                                                   group, icon, urgency,
-                                                  actions, action_cb,
-                                                  cancel_cb));
+                                                  actions, resident,
+                                                  action_cb, cancel_cb));
 }
 
 /* Run callbacks in response to a notification being deleted.
@@ -899,7 +904,7 @@ android_notification_deleted (struct 
android_notification_event *event,
   if (!NILP (item))
     Fremhash (tag, notification_table);
 
-  if (CONSP (item) && FUNCTIONP (XCDR (item))
+  if (CONSP (item) && FUNCTIONP (XCAR (XCDR (item)))
       && sscanf (event->tag, "%*d.%*ld.%jd", &id) > 0)
     {
       ie->kind = NOTIFICATION_EVENT;
@@ -919,6 +924,8 @@ android_notification_action (struct 
android_notification_event *event,
 {
   Lisp_Object item, tag;
   intmax_t id;
+  jstring tag_object;
+  jmethodID method;
 
   tag  = build_string (event->tag);
   item = Fgethash (tag, notification_table, Qnil);
@@ -929,6 +936,29 @@ android_notification_action (struct 
android_notification_event *event,
       ie->kind = NOTIFICATION_EVENT;
       ie->arg  = list3 (XCAR (item), make_int (id), action);
     }
+
+  /* Test whether ITEM is resident.  Non-resident notifications must be
+     removed when activated.  */
+
+  if (!CONSP (item) || NILP (XCAR (XCDR (XCDR (item)))))
+    {
+      method = service_class.cancel_notification;
+      tag_object
+       = (*android_java_env)->NewStringUTF (android_java_env,
+                                            event->tag);
+      android_exception_check ();
+
+      (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
+                                                    emacs_service,
+                                                    service_class.class,
+                                                    method, tag_object);
+      android_exception_check_1 (tag_object);
+      ANDROID_DELETE_LOCAL_REF (tag_object);
+
+      /* Remove the notification from the callback table.  */
+      if (!NILP (item))
+       Fremhash (tag, notification_table);
+    }
 }
 
 
@@ -971,6 +1001,7 @@ syms_of_androidselect (void)
   DEFSYM (QCurgency, ":urgency");
   DEFSYM (QCicon, ":icon");
   DEFSYM (QCactions, ":actions");
+  DEFSYM (QCresident, ":resident");
   DEFSYM (QCon_action, ":on-action");
   DEFSYM (QCon_cancel, ":on-cancel");
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]