File indexing completed on 2024-12-22 04:41:40
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 package org.kde.kdeconnect.Plugins.ReceiveNotificationsPlugin; 0008 0009 import android.Manifest; 0010 import android.app.Notification; 0011 import android.app.NotificationManager; 0012 import android.app.PendingIntent; 0013 import android.content.Intent; 0014 import android.graphics.Bitmap; 0015 import android.graphics.BitmapFactory; 0016 import android.os.Build; 0017 import android.util.Log; 0018 0019 import androidx.annotation.NonNull; 0020 import androidx.core.app.NotificationCompat; 0021 import androidx.core.content.ContextCompat; 0022 0023 import org.apache.commons.lang3.ArrayUtils; 0024 import org.kde.kdeconnect.Helpers.NotificationHelper; 0025 import org.kde.kdeconnect.NetworkPacket; 0026 import org.kde.kdeconnect.Plugins.Plugin; 0027 import org.kde.kdeconnect.Plugins.PluginFactory; 0028 import org.kde.kdeconnect.UserInterface.MainActivity; 0029 import org.kde.kdeconnect_tp.R; 0030 0031 import java.io.InputStream; 0032 0033 @PluginFactory.LoadablePlugin 0034 public class ReceiveNotificationsPlugin extends Plugin { 0035 0036 private final static String PACKET_TYPE_NOTIFICATION = "kdeconnect.notification"; 0037 private final static String PACKET_TYPE_NOTIFICATION_REQUEST = "kdeconnect.notification.request"; 0038 0039 @Override 0040 public @NonNull String getDisplayName() { 0041 return context.getResources().getString(R.string.pref_plugin_receive_notifications); 0042 } 0043 0044 @Override 0045 public @NonNull String getDescription() { 0046 return context.getResources().getString(R.string.pref_plugin_receive_notifications_desc); 0047 } 0048 0049 @Override 0050 public boolean isEnabledByDefault() { 0051 return false; 0052 } 0053 0054 @Override 0055 public boolean onCreate() { 0056 // request all existing notifications 0057 NetworkPacket np = new NetworkPacket(PACKET_TYPE_NOTIFICATION_REQUEST); 0058 np.set("request", true); 0059 device.sendPacket(np); 0060 return true; 0061 } 0062 0063 @Override 0064 public boolean onPacketReceived(final NetworkPacket np) { 0065 0066 if (!np.has("ticker") || !np.has("appName") || !np.has("id")) { 0067 Log.e("NotificationsPlugin", "Received notification packet lacks properties"); 0068 return true; 0069 } 0070 0071 if (np.getBoolean("silent", false)) { 0072 return true; 0073 } 0074 0075 PendingIntent resultPendingIntent = PendingIntent.getActivity( 0076 context, 0077 0, 0078 new Intent(context, MainActivity.class), 0079 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE 0080 ); 0081 0082 Bitmap largeIcon = null; 0083 if (np.hasPayload()) { 0084 int width = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width); 0085 int height = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height); 0086 final InputStream input = np.getPayload().getInputStream(); 0087 largeIcon = BitmapFactory.decodeStream(input); 0088 np.getPayload().close(); 0089 0090 if (largeIcon != null) { 0091 //Log.i("NotificationsPlugin", "hasPayload: size=" + largeIcon.getWidth() + "/" + largeIcon.getHeight() + " opti=" + width + "/" + height); 0092 if (largeIcon.getWidth() > width || largeIcon.getHeight() > height) { 0093 // older API levels don't scale notification icons automatically, therefore: 0094 largeIcon = Bitmap.createScaledBitmap(largeIcon, width, height, false); 0095 } 0096 } 0097 } 0098 0099 NotificationManager notificationManager = ContextCompat.getSystemService(context, NotificationManager.class); 0100 0101 Notification noti = new NotificationCompat.Builder(context, NotificationHelper.Channels.RECEIVENOTIFICATION) 0102 .setContentTitle(np.getString("appName")) 0103 .setContentText(np.getString("ticker")) 0104 .setContentIntent(resultPendingIntent) 0105 .setTicker(np.getString("ticker")) 0106 .setSmallIcon(R.drawable.ic_notification) 0107 .setLargeIcon(largeIcon) 0108 .setAutoCancel(true) 0109 .setLocalOnly(true) // to avoid bouncing the notification back to other kdeconnect nodes 0110 .setDefaults(Notification.DEFAULT_ALL) 0111 .setStyle(new NotificationCompat.BigTextStyle().bigText(np.getString("ticker"))) 0112 .build(); 0113 0114 NotificationHelper.notifyCompat(notificationManager, "kdeconnectId:" + np.getString("id", "0"), np.getInt("id", 0), noti); 0115 0116 return true; 0117 } 0118 0119 @Override 0120 public @NonNull String[] getSupportedPacketTypes() { 0121 return new String[]{PACKET_TYPE_NOTIFICATION}; 0122 } 0123 0124 @Override 0125 public @NonNull String[] getOutgoingPacketTypes() { 0126 return new String[]{PACKET_TYPE_NOTIFICATION_REQUEST}; 0127 } 0128 0129 @NonNull 0130 @Override 0131 protected String[] getRequiredPermissions() { 0132 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 0133 return new String[]{Manifest.permission.POST_NOTIFICATIONS}; 0134 } else { 0135 return ArrayUtils.EMPTY_STRING_ARRAY; 0136 } 0137 } 0138 0139 @Override 0140 protected int getPermissionExplanation() { 0141 return R.string.receive_notifications_permission_explanation; 0142 } 0143 }