From 4f714dc08137d36d0d1e886814008f2abe5712c0 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 20 Aug 2023 20:23:56 +0800 Subject: Support desktop notifications on Android * doc/emacs/android.texi (Android Environment): Correct list of permissions granted by default. * doc/lispref/os.texi (Desktop Notifications): Document the new function `android-notifications-notify' and its limitations. * java/AndroidManifest.xml.in: Request notification permissions. * java/org/gnu/emacs/EmacsDesktopNotification.java: New file. * java/res/layout/sdk8_notifications_view.xml: New file holding substitute notification widget definitions for Android versions prior to 3.0. * java/res/values/strings.xml: Remove inadvertently introduced tag attribute. * lisp/org/org-clock.el (haiku-notifications-notify): Correct file name in function declaration. (android-notifications-notify): New declaration. (org-show-notification): Use `android-notifications-notify'. * src/androidselect.c (android_init_emacs_desktop_notification) (android_notifications_notify_1, Fandroid_notifications_notify): New functions. (init_androidselect, syms_of_androidselect): Initialize new class and define new subr. --- java/AndroidManifest.xml.in | 5 + java/org/gnu/emacs/EmacsDesktopNotification.java | 152 +++++++++++++++++++++++ java/res/layout/sdk8_notifications_view.xml | 31 +++++ java/res/values/strings.xml | 2 +- 4 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 java/org/gnu/emacs/EmacsDesktopNotification.java create mode 100644 java/res/layout/sdk8_notifications_view.xml (limited to 'java') diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in index 895e7f88c57..b9cda401c9d 100644 --- a/java/AndroidManifest.xml.in +++ b/java/AndroidManifest.xml.in @@ -66,6 +66,11 @@ along with GNU Emacs. If not, see . --> + + + + diff --git a/java/org/gnu/emacs/EmacsDesktopNotification.java b/java/org/gnu/emacs/EmacsDesktopNotification.java new file mode 100644 index 00000000000..8f55ffe8145 --- /dev/null +++ b/java/org/gnu/emacs/EmacsDesktopNotification.java @@ -0,0 +1,152 @@ +/* Communication module for Android terminals. -*- c-file-style: "GNU" -*- + +Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +package org.gnu.emacs; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.NotificationChannel; + +import android.content.Context; + +import android.os.Build; + +import android.widget.RemoteViews; + + + +/* Structure designating a single desktop notification. + + New versions of Android also organize notifications into individual + ``channels'', which are used to implement groups. Unlike on other + systems, notification importance is set for each group, not for + each individual notification. */ + + + +public final class EmacsDesktopNotification +{ + /* The content of this desktop notification. */ + public final String content; + + /* The title of this desktop notification. */ + public final String title; + + /* The notification group. */ + public final String group; + + /* String identifying this notification for future replacement. + Typically a string resembling ``XXXX.NNNN.YYYY'', where XXXX is + the system boot time, NNNN is the PID of this Emacs instance, and + YYYY is the counter value returned by the notifications display + function. */ + public final String tag; + + /* The importance of this notification's group. */ + public final int importance; + + public + EmacsDesktopNotification (String title, String content, + String group, String tag, int importance) + { + this.content = content; + this.title = title; + this.group = group; + this.tag = tag; + this.importance = importance; + } + + + + /* Functions for displaying desktop notifications. */ + + /* Internal helper for `display' executed on the main thread. */ + + @SuppressWarnings ("deprecation") /* Notification.Builder (Context). */ + private void + display1 (Context context) + { + NotificationManager manager; + NotificationChannel channel; + Notification notification; + Object tem; + RemoteViews contentView; + + tem = context.getSystemService (Context.NOTIFICATION_SERVICE); + manager = (NotificationManager) tem; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + { + /* Create the notification channel for this group. If a group + already exists with the same name, its linked attributes + (such as its importance) will be overridden. */ + channel = new NotificationChannel (group, group, importance); + manager.createNotificationChannel (channel); + + /* Create a notification object and display it. */ + notification = (new Notification.Builder (context, group) + .setContentTitle (title) + .setContentText (content) + .setSmallIcon (R.drawable.emacs) + .build ()); + } + else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + notification = (new Notification.Builder (context) + .setContentTitle (title) + .setContentText (content) + .setSmallIcon (R.drawable.emacs) + .build ()); + else + { + notification = new Notification (); + notification.icon = R.drawable.emacs; + + /* This remote widget tree is defined in + java/res/layout/sdk8_notifications_view.xml. */ + notification.contentView + = contentView + = new RemoteViews ("org.gnu.emacs", + R.layout.sdk8_notifications_view); + contentView.setTextViewText (R.id.sdk8_notifications_title, + title); + contentView.setTextViewText (R.id.sdk8_notifications_content, + content); + } + + manager.notify (tag, 2, notification); + } + + /* Display this desktop notification. + + Create a notification channel named GROUP or update its + importance if such a channel is already defined. */ + + public void + display () + { + EmacsService.SERVICE.runOnUiThread (new Runnable () { + @Override + public void + run () + { + display1 (EmacsService.SERVICE); + } + }); + } +}; diff --git a/java/res/layout/sdk8_notifications_view.xml b/java/res/layout/sdk8_notifications_view.xml new file mode 100644 index 00000000000..2daa5beea86 --- /dev/null +++ b/java/res/layout/sdk8_notifications_view.xml @@ -0,0 +1,31 @@ + + + + + + diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 8a11cb007ee..0bf1ef0ac9b 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -17,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . --> - + Restart Emacs with -Q -- cgit v1.2.1