termux-app/termux-shared/src/main/java/com/termux/shared/notification/NotificationUtils.java

170 lines
7.9 KiB
Java

package com.termux.shared.notification;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import androidx.annotation.Nullable;
import com.termux.shared.logger.Logger;
import com.termux.shared.settings.preferences.TermuxAppSharedPreferences;
import com.termux.shared.settings.preferences.TermuxPreferenceConstants;
import com.termux.shared.termux.TermuxConstants;
public class NotificationUtils {
/** Do not show notification */
public static final int NOTIFICATION_MODE_NONE = 0;
/** Show notification without sound, vibration or lights */
public static final int NOTIFICATION_MODE_SILENT = 1;
/** Show notification with sound */
public static final int NOTIFICATION_MODE_SOUND = 2;
/** Show notification with vibration */
public static final int NOTIFICATION_MODE_VIBRATE = 3;
/** Show notification with lights */
public static final int NOTIFICATION_MODE_LIGHTS = 4;
/** Show notification with sound and vibration */
public static final int NOTIFICATION_MODE_SOUND_AND_VIBRATE = 5;
/** Show notification with sound and lights */
public static final int NOTIFICATION_MODE_SOUND_AND_LIGHTS = 6;
/** Show notification with vibration and lights */
public static final int NOTIFICATION_MODE_VIBRATE_AND_LIGHTS = 7;
/** Show notification with sound, vibration and lights */
public static final int NOTIFICATION_MODE_ALL = 8;
private static final String LOG_TAG = "NotificationUtils";
/**
* Get the {@link NotificationManager}.
*
* @param context The {@link Context} for operations.
* @return Returns the {@link NotificationManager}.
*/
@Nullable
public static NotificationManager getNotificationManager(final Context context) {
if(context == null) return null;
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
/**
* Try to get the next unique notification id that isn't already being used by the app.
*
* Termux app and its plugin must use unique notification ids from the same pool due to usage of android:sharedUserId.
* https://commonsware.com/blog/2017/06/07/jobscheduler-job-ids-libraries.html
*
* @param context The {@link Context} for operations.
* @return Returns the notification id that should be safe to use.
*/
public synchronized static int getNextNotificationId(final Context context) {
if(context == null) return TermuxPreferenceConstants.TERMUX_APP.DEFAULT_VALUE_KEY_LAST_NOTIFICATION_ID;
TermuxAppSharedPreferences preferences = new TermuxAppSharedPreferences(context);
int lastNotificationId = preferences.getLastNotificationId();
int nextNotificationId = lastNotificationId + 1;
while(nextNotificationId == TermuxConstants.TERMUX_APP_NOTIFICATION_ID || nextNotificationId == TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_ID) {
nextNotificationId++;
}
if(nextNotificationId == Integer.MAX_VALUE || nextNotificationId < 0)
nextNotificationId = TermuxPreferenceConstants.TERMUX_APP.DEFAULT_VALUE_KEY_LAST_NOTIFICATION_ID;
preferences.setLastNotificationId(nextNotificationId);
return nextNotificationId;
}
/**
* Get {@link Notification.Builder}.
*
* @param context The {@link Context} for operations.
* @param title The title for the notification.
* @param notifiationText The second line text of the notification.
* @param notificationBigText The full text of the notification that may optionally be styled.
* @param pendingIntent The {@link PendingIntent} which should be sent when notification is clicked.
* @param notificationMode The notification mode. It must be one of {@code NotificationUtils.NOTIFICATION_MODE_*}.
* The builder returned will be {@code null} if {@link #NOTIFICATION_MODE_NONE}
* is passed. That case should ideally be handled before calling this function.
* @return Returns the {@link Notification.Builder}.
*/
@Nullable
public static Notification.Builder geNotificationBuilder(final Context context, final String channelId, final int priority, final CharSequence title, final CharSequence notifiationText, final CharSequence notificationBigText, final PendingIntent pendingIntent, final int notificationMode) {
if(context == null) return null;
Notification.Builder builder = new Notification.Builder(context);
builder.setContentTitle(title);
builder.setContentText(notifiationText);
builder.setStyle(new Notification.BigTextStyle().bigText(notificationBigText));
builder.setContentIntent(pendingIntent);
builder.setPriority(priority);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
builder.setChannelId(channelId);
builder = setNotificationDefaults(builder, notificationMode);
return builder;
}
/**
* Setup the notification channel if Android version is greater than or equal to
* {@link Build.VERSION_CODES#O}.
*
* @param context The {@link Context} for operations.
* @param channelId The id of the channel. Must be unique per package.
* @param channelName The user visible name of the channel.
* @param importance The importance of the channel. This controls how interruptive notifications
* posted to this channel are.
*/
public static void setupNotificationChannel(final Context context, final String channelId, final CharSequence channelName, final int importance) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
NotificationManager notificationManager = getNotificationManager(context);
if(notificationManager != null)
notificationManager.createNotificationChannel(channel);
}
public static Notification.Builder setNotificationDefaults(Notification.Builder builder, final int notificationMode) {
// TODO: setDefaults() is deprecated and should also implement setting notification mode via notification channel
switch (notificationMode) {
case NOTIFICATION_MODE_NONE:
Logger.logWarn(LOG_TAG, "The NOTIFICATION_MODE_NONE passed to setNotificationDefaults(), force setting builder to null.");
return null; // return null since notification is not supposed to be shown
case NOTIFICATION_MODE_SILENT:
break;
case NOTIFICATION_MODE_SOUND:
builder.setDefaults(Notification.DEFAULT_SOUND);
break;
case NOTIFICATION_MODE_VIBRATE:
builder.setDefaults(Notification.DEFAULT_VIBRATE);
break;
case NOTIFICATION_MODE_LIGHTS:
builder.setDefaults(Notification.DEFAULT_LIGHTS);
break;
case NOTIFICATION_MODE_SOUND_AND_VIBRATE:
builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
break;
case NOTIFICATION_MODE_SOUND_AND_LIGHTS:
builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS);
break;
case NOTIFICATION_MODE_VIBRATE_AND_LIGHTS:
builder.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
break;
case NOTIFICATION_MODE_ALL:
builder.setDefaults(Notification.DEFAULT_ALL);
break;
default:
Logger.logError(LOG_TAG, "Invalid notificationMode: \"" + notificationMode + "\" passed to setNotificationDefaults()");
break;
}
return builder;
}
}