]> git.eshelyaron.com Git - emacs.git/commitdiff
Enable providing icons for Android desktop notifications
authorPo Lu <luangruo@yahoo.com>
Mon, 21 Aug 2023 01:36:52 +0000 (09:36 +0800)
committerPo Lu <luangruo@yahoo.com>
Mon, 21 Aug 2023 01:36:52 +0000 (09:36 +0800)
* doc/lispref/os.texi (Desktop Notifications)
<android-notifications-notify>: Mention the :icon parameter.

* java/org/gnu/emacs/EmacsDesktopNotification.java
(EmacsDesktopNotification) <icon>: New field.
(<init>): New argument ICON.  Set this.icon to its value.
(display1): Use provided icon and always supply a pending intent
to open Emacs once the notification is clicked.

* java/res/layout/sdk8_notifications_view.xml
(sdk8_notifications_title, sdk8_notifications_content): Set
foreground color to #000000.

* src/androidselect.c (android_init_emacs_desktop_notification):
Update signature of <init>.
(android_locate_icon): New function.
(android_notifications_notify_1): New arg ICON.
(Fandroid_notifications_notify): New parameter icon.
(syms_of_androidselect): <QCicon>: New symbol.

doc/lispref/os.texi
java/org/gnu/emacs/EmacsDesktopNotification.java
java/res/layout/sdk8_notifications_view.xml
src/androidselect.c

index cf65380a3acd8a76fdb687c1b8ba7f8e08ed5f9c..8a3e5663468d6143207f67216761e33e7d6c83de 100644 (file)
@@ -3228,6 +3228,16 @@ all notifications displayed with the defined @var{group}.
 
 If @var{group} is nil or not present within @var{params}, it is
 replaced by the string @samp{"Desktop Notifications"}.
+
+@item :icon @var{icon}
+This parameter controls the symbolic icon the notification will be
+displayed with.  Its value is a string designating an icon within the
+@code{android.R.drawable} system package.  See
+@url{https://developer.android.com/reference/android/R.drawable,,R.drawable
+| Android Developers} for a list of such icons.
+
+If it is not provided within @var{params} or @var{icon} does not
+exist, it defaults to @samp{"ic_dialog_alert"}.
 @end table
 
 It returns a number identifying the notification, which may be
index b73ef1022fa965ca9d4388805923b34cc9849fd1..c6ebbc6ae4826f22b97693d417c04901962de8f5 100644 (file)
@@ -60,17 +60,22 @@ public final class EmacsDesktopNotification
      function.  */
   public final String tag;
 
+  /* The identifier of this notification's icon.  */
+  public final int icon;
+
   /* The importance of this notification's group.  */
   public final int importance;
 
   public
   EmacsDesktopNotification (String title, String content,
-                           String group, String tag, int importance)
+                           String group, String tag, int icon,
+                           int importance)
   {
     this.content    = content;
     this.title     = title;
     this.group     = group;
     this.tag        = tag;
+    this.icon       = icon;
     this.importance = importance;
   }
 
@@ -107,19 +112,19 @@ public final class EmacsDesktopNotification
        notification = (new Notification.Builder (context, group)
                        .setContentTitle (title)
                        .setContentText (content)
-                       .setSmallIcon (R.drawable.emacs)
+                       .setSmallIcon (icon)
                        .build ());
       }
     else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
       notification = (new Notification.Builder (context)
                      .setContentTitle (title)
                      .setContentText (content)
-                     .setSmallIcon (R.drawable.emacs)
+                     .setSmallIcon (icon)
                      .build ());
     else
       {
        notification = new Notification ();
-       notification.icon = R.drawable.emacs;
+       notification.icon = icon;
 
        /* This remote widget tree is defined in
           java/res/layout/sdk8_notifications_view.xml.  */
@@ -131,15 +136,21 @@ public final class EmacsDesktopNotification
                                     title);
        contentView.setTextViewText (R.id.sdk8_notifications_content,
                                     content);
+      }
 
-       /* A content intent must be provided on these old versions of
-          Android.  */
+    /* Provide a content intent which starts Emacs when the
+       notification is clicked.  */
 
-       intent = new Intent (context, EmacsActivity.class);
-       intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
-        pending = PendingIntent.getActivity (context, 0, intent, 0);
-       notification.contentIntent = pending;
-      }
+    intent = new Intent (context, EmacsActivity.class);
+    intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
+
+    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S)
+      pending = PendingIntent.getActivity (context, 0, intent,
+                                          PendingIntent.FLAG_IMMUTABLE);
+    else
+      pending = PendingIntent.getActivity (context, 0, intent, 0);
+
+    notification.contentIntent = pending;
 
     manager.notify (tag, 2, notification);
   }
index 2daa5beea868992dee526ce763416ccda9c76ee6..0572f350cff494c2d23394a665907a6a3f449b98 100644 (file)
@@ -23,9 +23,11 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>. -->
              android:layout_height="wrap_content"
              android:padding="8dp">
   <TextView android:id="@+id/sdk8_notifications_title"
+           android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
   <TextView android:id="@+id/sdk8_notifications_content"
+           android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
 </LinearLayout>
index 5551598032d15fad6bac2c30cdc7cbca7aa25896..5735eda2dd5661cb6f0ec21e593bb2b1835d826e 100644 (file)
@@ -515,24 +515,60 @@ android_init_emacs_desktop_notification (void)
 
   FIND_METHOD (init, "<init>", "(Ljava/lang/String;"
               "Ljava/lang/String;Ljava/lang/String;"
-              "Ljava/lang/String;I)V");
+              "Ljava/lang/String;II)V");
   FIND_METHOD (display, "display", "()V");
 #undef FIND_METHOD
 }
 
+/* Return the numeric resource ID designating the icon within the
+   ``android.R.drawable'' package by the supplied NAME.
+
+   If no icon is found, return that of
+   ``android.R.drawable.ic_dialog_alert''.  */
+
+static jint
+android_locate_icon (const char *name)
+{
+  jclass drawable;
+  jfieldID field;
+  jint rc;
+
+  if (android_verify_jni_string (name))
+    /* If NAME isn't valid, return the default value.  */
+    return 17301543; /* android.R.drawable.ic_dialog_alert.  */
+
+  drawable = (*android_java_env)->FindClass (android_java_env,
+                                            "android/R$drawable");
+  android_exception_check ();
+
+  field = (*android_java_env)->GetStaticFieldID (android_java_env,
+                                                drawable, name, "I");
+  (*android_java_env)->ExceptionClear (android_java_env);
+
+  if (!field)
+    rc = 17301543; /* android.R.drawable.ic_dialog_alert.  */
+  else
+    rc = (*android_java_env)->GetStaticIntField (android_java_env,
+                                                drawable, field);
+
+  ANDROID_DELETE_LOCAL_REF (drawable);
+  return rc;
+}
+
 /* Display a desktop notification with the provided TITLE, BODY,
-   REPLACES_ID, GROUP and URGENCY.  Return an identifier for the
-   resulting notification.  */
+   REPLACES_ID, GROUP, ICON, and URGENCY.  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 urgency)
+                               Lisp_Object group, Lisp_Object icon,
+                               Lisp_Object urgency)
 {
   static intmax_t counter;
   intmax_t id;
   jstring title1, body1, group1, identifier1;
-  jint type;
+  jint type, icon1;
   jobject notification;
   char identifier[INT_STRLEN_BOUND (int)
                  + INT_STRLEN_BOUND (long int)
@@ -562,6 +598,9 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
        id = -1; /* Overflow.  */
     }
 
+  /* Locate the integer ID linked to ICON.  */
+  icon1 = android_locate_icon (SSDATA (icon));
+
   /* Generate a unique identifier for this notification.  Because
      Android persists notifications past system shutdown, also include
      the boot time within IDENTIFIER.  Scale it down to avoid being
@@ -585,7 +624,7 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
                                      notification_class.class,
                                      notification_class.init,
                                      title1, body1, group1,
-                                     identifier1, type);
+                                     identifier1, icon1, type);
   android_exception_check_4 (title1, body1, group1, identifier1);
 
   /* Delete unused local references.  */
@@ -618,6 +657,8 @@ keywords is understood:
   :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
+                notification's icon.
 
 The notification group and urgency are ignored on Android 7.1 and
 earlier versions of Android.  Outside such older systems, it
@@ -626,6 +667,11 @@ menu.  The urgency provided always extends to affect all notifications
 displayed within that category.  If the group is not provided, it
 defaults to the string "Desktop Notifications".
 
+The provided icon should be the name of a "drawable resource" present
+within the "android.R.drawable" class designating an icon with a
+transparent background.  If no icon is provided (or the icon is absent
+from this system), it defaults to "ic_dialog_alert".
+
 When the system is running Android 13 or later, notifications sent
 will be silently disregarded unless permission to display
 notifications is expressly granted from the "App Info" settings panel
@@ -640,6 +686,7 @@ usage: (android-notifications-notify &rest ARGS) */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object title, body, replaces_id, group, urgency;
+  Lisp_Object icon;
   Lisp_Object key, value;
   ptrdiff_t i;
 
@@ -647,7 +694,7 @@ usage: (android-notifications-notify &rest ARGS) */)
     error ("No Android display connection!");
 
   /* Clear each variable above.  */
-  title = body = replaces_id = group = urgency = Qnil;
+  title = body = replaces_id = group = icon = urgency = Qnil;
 
   /* If NARGS is odd, error.  */
 
@@ -671,6 +718,8 @@ usage: (android-notifications-notify &rest ARGS) */)
        group = value;
       else if (EQ (key, QCurgency))
        urgency = value;
+      else if (EQ (key, QCicon))
+       icon = value;
     }
 
   /* Demand at least TITLE and BODY be present.  */
@@ -687,10 +736,15 @@ usage: (android-notifications-notify &rest ARGS) */)
     urgency = Qlow;
 
   if (NILP (group))
-    group   = build_string ("Desktop Notifications");
+    group = build_string ("Desktop Notifications");
+
+  if (NILP (icon))
+    icon = build_string ("ic_dialog_alert");
+  else
+    CHECK_STRING (icon);
 
   return make_int (android_notifications_notify_1 (title, body, replaces_id,
-                                                  group, urgency));
+                                                  group, icon, urgency));
 }
 
 \f
@@ -731,6 +785,7 @@ syms_of_androidselect (void)
   DEFSYM (QCreplaces_id, ":replaces-id");
   DEFSYM (QCgroup, ":group");
   DEFSYM (QCurgency, ":urgency");
+  DEFSYM (QCicon, ":icon");
 
   DEFSYM (Qlow, "low");
   DEFSYM (Qnormal, "normal");