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.
This commit is contained in:
parent
bf38783c32
commit
d7ded99608
5 changed files with 75 additions and 14 deletions
|
@ -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.
|
||||
|
|
|
@ -1967,4 +1967,29 @@ In addition, arbitrary runtime exceptions (such as
|
|||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue