mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-09 07:40:39 -08:00
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-action @var{on-action}
|
||||||
@item :on-cancel @var{on-cancel}
|
@item :on-cancel @var{on-cancel}
|
||||||
@item :actions @var{actions}
|
@item :actions @var{actions}
|
||||||
|
@item :resident @var{resident}
|
||||||
These have the same meaning as they do when used in calls to
|
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}
|
@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
|
@code{notifications-notify}, but the urgency applies to all
|
||||||
notifications displayed with the defined @var{group}, except under
|
notifications displayed with the defined @var{group}, except under
|
||||||
Android 7.1 and earlier.
|
Android 7.1 and earlier.
|
||||||
|
|
|
||||||
|
|
@ -1967,4 +1967,29 @@ public final class EmacsService extends Service
|
||||||
else
|
else
|
||||||
requestStorageAccess30 ();
|
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");
|
"externalStorageAvailable", "()Z");
|
||||||
FIND_METHOD (request_storage_access,
|
FIND_METHOD (request_storage_access,
|
||||||
"requestStorageAccess", "()V");
|
"requestStorageAccess", "()V");
|
||||||
|
FIND_METHOD (cancel_notification,
|
||||||
|
"cancelNotification", "(Ljava/lang/String;)V");
|
||||||
#undef FIND_METHOD
|
#undef FIND_METHOD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@ struct android_emacs_service
|
||||||
jmethodID valid_authority;
|
jmethodID valid_authority;
|
||||||
jmethodID external_storage_available;
|
jmethodID external_storage_available;
|
||||||
jmethodID request_storage_access;
|
jmethodID request_storage_access;
|
||||||
|
jmethodID cancel_notification;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JNIEnv *android_java_env;
|
extern JNIEnv *android_java_env;
|
||||||
|
|
|
||||||
|
|
@ -567,15 +567,15 @@ android_locate_icon (const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display a desktop notification with the provided TITLE, BODY,
|
/* Display a desktop notification with the provided TITLE, BODY,
|
||||||
REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, ACTION_CB and CANCEL_CB.
|
REPLACES_ID, GROUP, ICON, URGENCY, ACTIONS, RESIDENT, ACTION_CB and
|
||||||
Return an identifier for the resulting notification. */
|
CANCEL_CB. Return an identifier for the resulting notification. */
|
||||||
|
|
||||||
static intmax_t
|
static intmax_t
|
||||||
android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
|
android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
|
||||||
Lisp_Object replaces_id,
|
Lisp_Object replaces_id,
|
||||||
Lisp_Object group, Lisp_Object icon,
|
Lisp_Object group, Lisp_Object icon,
|
||||||
Lisp_Object urgency, Lisp_Object actions,
|
Lisp_Object urgency, Lisp_Object actions,
|
||||||
Lisp_Object action_cb,
|
Lisp_Object resident, Lisp_Object action_cb,
|
||||||
Lisp_Object cancel_cb)
|
Lisp_Object cancel_cb)
|
||||||
{
|
{
|
||||||
static intmax_t counter;
|
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 callbacks are provided, save them into notification_table. */
|
||||||
|
|
||||||
if (!NILP (action_cb) || !NILP (cancel_cb))
|
if (!NILP (action_cb) || !NILP (cancel_cb) || !NILP (resident))
|
||||||
Fputhash (build_string (identifier), Fcons (action_cb, cancel_cb),
|
Fputhash (build_string (identifier), list3 (action_cb, cancel_cb,
|
||||||
|
resident),
|
||||||
notification_table);
|
notification_table);
|
||||||
|
|
||||||
/* Return the ID. */
|
/* Return the ID. */
|
||||||
|
|
@ -755,12 +756,12 @@ ARGS must contain keywords followed by values. Each of the following
|
||||||
keywords is understood:
|
keywords is understood:
|
||||||
|
|
||||||
:title The notification title.
|
:title The notification title.
|
||||||
:body The notification body.
|
:body The notification body.
|
||||||
:replaces-id The ID of a previous notification to supersede.
|
:replaces-id The ID of a previous notification to supersede.
|
||||||
:group The notification group, or nil.
|
:group The notification group, or nil.
|
||||||
:urgency One of the symbols `low', `normal' or `critical',
|
:urgency One of the symbols `low', `normal' or `critical',
|
||||||
defining the importance of the notification group.
|
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.
|
notification's icon.
|
||||||
:actions A list of actions of the form:
|
:actions A list of actions of the form:
|
||||||
(KEY TITLE KEY TITLE ...)
|
(KEY TITLE KEY TITLE ...)
|
||||||
|
|
@ -770,6 +771,8 @@ keywords is understood:
|
||||||
its existence is implied, and its TITLE is ignored.
|
its existence is implied, and its TITLE is ignored.
|
||||||
No more than three actions can be defined, not
|
No more than three actions can be defined, not
|
||||||
counting any action with "default" as its key.
|
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.
|
:on-action Function to call when an action is invoked.
|
||||||
The notification id and the key of the action are
|
The notification id and the key of the action are
|
||||||
provided as arguments to the function.
|
provided as arguments to the function.
|
||||||
|
|
@ -811,7 +814,7 @@ this function.
|
||||||
usage: (android-notifications-notify &rest ARGS) */)
|
usage: (android-notifications-notify &rest ARGS) */)
|
||||||
(ptrdiff_t nargs, Lisp_Object *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 icon;
|
||||||
Lisp_Object key, value, actions, action_cb, cancel_cb;
|
Lisp_Object key, value, actions, action_cb, cancel_cb;
|
||||||
ptrdiff_t i;
|
ptrdiff_t i;
|
||||||
|
|
@ -821,7 +824,7 @@ usage: (android-notifications-notify &rest ARGS) */)
|
||||||
|
|
||||||
/* Clear each variable above. */
|
/* Clear each variable above. */
|
||||||
title = body = replaces_id = group = icon = urgency = actions = Qnil;
|
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. */
|
/* If NARGS is odd, error. */
|
||||||
|
|
||||||
|
|
@ -849,6 +852,8 @@ usage: (android-notifications-notify &rest ARGS) */)
|
||||||
icon = value;
|
icon = value;
|
||||||
else if (EQ (key, QCactions))
|
else if (EQ (key, QCactions))
|
||||||
actions = value;
|
actions = value;
|
||||||
|
else if (EQ (key, QCresident))
|
||||||
|
resident = value;
|
||||||
else if (EQ (key, QCon_action))
|
else if (EQ (key, QCon_action))
|
||||||
action_cb = value;
|
action_cb = value;
|
||||||
else if (EQ (key, QCon_cancel))
|
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,
|
return make_int (android_notifications_notify_1 (title, body, replaces_id,
|
||||||
group, icon, urgency,
|
group, icon, urgency,
|
||||||
actions, action_cb,
|
actions, resident,
|
||||||
cancel_cb));
|
action_cb, cancel_cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run callbacks in response to a notification being deleted.
|
/* Run callbacks in response to a notification being deleted.
|
||||||
|
|
@ -899,7 +904,7 @@ android_notification_deleted (struct android_notification_event *event,
|
||||||
if (!NILP (item))
|
if (!NILP (item))
|
||||||
Fremhash (tag, notification_table);
|
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)
|
&& sscanf (event->tag, "%*d.%*ld.%jd", &id) > 0)
|
||||||
{
|
{
|
||||||
ie->kind = NOTIFICATION_EVENT;
|
ie->kind = NOTIFICATION_EVENT;
|
||||||
|
|
@ -919,6 +924,8 @@ android_notification_action (struct android_notification_event *event,
|
||||||
{
|
{
|
||||||
Lisp_Object item, tag;
|
Lisp_Object item, tag;
|
||||||
intmax_t id;
|
intmax_t id;
|
||||||
|
jstring tag_object;
|
||||||
|
jmethodID method;
|
||||||
|
|
||||||
tag = build_string (event->tag);
|
tag = build_string (event->tag);
|
||||||
item = Fgethash (tag, notification_table, Qnil);
|
item = Fgethash (tag, notification_table, Qnil);
|
||||||
|
|
@ -929,6 +936,29 @@ android_notification_action (struct android_notification_event *event,
|
||||||
ie->kind = NOTIFICATION_EVENT;
|
ie->kind = NOTIFICATION_EVENT;
|
||||||
ie->arg = list3 (XCAR (item), make_int (id), action);
|
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 (QCurgency, ":urgency");
|
||||||
DEFSYM (QCicon, ":icon");
|
DEFSYM (QCicon, ":icon");
|
||||||
DEFSYM (QCactions, ":actions");
|
DEFSYM (QCactions, ":actions");
|
||||||
|
DEFSYM (QCresident, ":resident");
|
||||||
DEFSYM (QCon_action, ":on-action");
|
DEFSYM (QCon_action, ":on-action");
|
||||||
DEFSYM (QCon_cancel, ":on-cancel");
|
DEFSYM (QCon_cancel, ":on-cancel");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue