diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java @@ -31,6 +31,7 @@ public class AppDatabase { static final private HashSet disabledByDefault = new HashSet<>(); + static { disabledByDefault.add("com.android.messaging"); //We already have sms notifications in the telephony plugin disabledByDefault.add("com.google.android.googlequicksearchbox"); //Google Now notifications re-spawn every few minutes @@ -64,7 +65,7 @@ @Override public void onUpgrade(SQLiteDatabase db, int i, int i2) { - db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE); onCreate(db); } @@ -80,23 +81,23 @@ } public void setEnabled(String packageName, boolean isEnabled) { - String[] columns = new String []{KEY_IS_ENABLED}; - Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null); + String[] columns = new String[]{KEY_IS_ENABLED}; + Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null); ContentValues cv = new ContentValues(); - cv.put(KEY_IS_ENABLED, isEnabled?"true":"false"); + cv.put(KEY_IS_ENABLED, isEnabled ? "true" : "false"); if (res.getCount() > 0) { - ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName}); + ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?", new String[]{packageName}); } else { cv.put(KEY_PACKAGE_NAME, packageName); ourDatabase.insert(DATABASE_TABLE, null, cv); } res.close(); } public boolean isEnabled(String packageName) { - String[] columns = new String []{KEY_IS_ENABLED}; - Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null); + String[] columns = new String[]{KEY_IS_ENABLED}; + Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null); boolean result; if (res.getCount() > 0) { res.moveToFirst(); diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java @@ -80,10 +80,10 @@ LayoutInflater inflater = getLayoutInflater(); view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true); } - CheckedTextView checkedTextView = (CheckedTextView)view; + CheckedTextView checkedTextView = (CheckedTextView) view; checkedTextView.setText(apps[position].name); checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null); - checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density)); + checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density)); return view; } @@ -151,7 +151,7 @@ } }); - for (int i = 0 ; i < apps.length; i++) { + for (int i = 0; i < apps.length; i++) { listView.setItemChecked(i, apps[i].isEnabled); } @@ -176,7 +176,7 @@ Resources res = getResources(); //Convert to display pixels - maxSize = (int)(maxSize*res.getDisplayMetrics().density); + maxSize = (int) (maxSize * res.getDisplayMetrics().density); Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationReceiver.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationReceiver.java --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationReceiver.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationReceiver.java @@ -34,37 +34,36 @@ public interface NotificationListener { void onNotificationPosted(StatusBarNotification statusBarNotification); + void onNotificationRemoved(StatusBarNotification statusBarNotification); } private final ArrayList listeners = new ArrayList<>(); public void addListener(NotificationListener listener) { listeners.add(listener); } + public void removeListener(NotificationListener listener) { listeners.remove(listener); } @Override public void onNotificationPosted(StatusBarNotification statusBarNotification) { //Log.e("NotificationReceiver.onNotificationPosted","listeners: " + listeners.size()); - for(NotificationListener listener : listeners) { + for (NotificationListener listener : listeners) { listener.onNotificationPosted(statusBarNotification); } } @Override public void onNotificationRemoved(StatusBarNotification statusBarNotification) { - for(NotificationListener listener : listeners) { + for (NotificationListener listener : listeners) { listener.onNotificationRemoved(statusBarNotification); } } - - - //To use the service from the outer (name)space public interface InstanceCallback { diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java @@ -35,7 +35,6 @@ import android.service.notification.StatusBarNotification; import android.util.Log; - import org.kde.kdeconnect.Helpers.AppsHelper; import org.kde.kdeconnect.NetworkPackage; import org.kde.kdeconnect.Plugins.Plugin; @@ -46,10 +45,8 @@ import java.io.ByteArrayOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) @@ -61,7 +58,7 @@ private boolean sendIcons = true; - + private Map pendingIntents; @@ -98,7 +95,7 @@ @Override public boolean onCreate() { pendingIntents = new HashMap(); - + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { if (hasPermission()) { NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { @@ -167,7 +164,7 @@ } appDatabase.open(); - if (!appDatabase.isEnabled(statusBarNotification.getPackageName())){ + if (!appDatabase.isEnabled(statusBarNotification.getPackageName())) { return; // we dont want notification from this app } @@ -178,7 +175,6 @@ String appName = AppsHelper.appNameLookup(context, packageName); - if ("com.facebook.orca".equals(packageName) && (statusBarNotification.getId() == 10012) && "Messenger".equals(appName) && @@ -188,16 +184,14 @@ } if ("com.android.systemui".equals(packageName) && - "low_battery".equals(statusBarNotification.getTag())) - { + "low_battery".equals(statusBarNotification.getTag())) { //HACK: Android low battery notification are posted again every few seconds. Ignore them, as we already have a battery indicator. return; } NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION); - if (packageName.equals("org.kde.kdeconnect_tp")) - { + if (packageName.equals("org.kde.kdeconnect_tp")) { //Make our own notifications silent :) np.set("silent", true); np.set("requestAnswer", true); //For compatibility with old desktop versions of KDE Connect that don't support "silent" @@ -219,20 +213,20 @@ np.set("payloadHash", getChecksum(bitmapData)); } - } catch(Exception e){ + } catch (Exception e) { e.printStackTrace(); Log.e("NotificationsPlugin", "Error retrieving icon"); } } - + RepliableNotification rn = extractRepliableNotification(statusBarNotification); - if(rn.pendingIntent != null) { + if (rn.pendingIntent != null) { np.set("requestReplyId", rn.id); pendingIntents.put(rn.id, rn); } np.set("id", key); - np.set("appName", appName == null? packageName : appName); + np.set("appName", appName == null ? packageName : appName); np.set("isClearable", statusBarNotification.isClearable()); np.set("ticker", getTickerText(notification)); np.set("title", getNotificationTitle(notification)); @@ -246,14 +240,14 @@ device.sendPackage(np); } - void replyToNotification(String id, String message){ - if(pendingIntents.isEmpty() || !pendingIntents.containsKey(id)){ + void replyToNotification(String id, String message) { + if (pendingIntents.isEmpty() || !pendingIntents.containsKey(id)) { Log.e("NotificationsPlugin", "No such notification"); return; } RepliableNotification repliableNotification = pendingIntents.get(id); - if(repliableNotification == null) { + if (repliableNotification == null) { Log.e("NotificationsPlugin", "No such notification"); return; } @@ -263,14 +257,14 @@ localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundle localBundle = new Bundle(); int i = 0; - for(RemoteInput remoteIn : repliableNotification.remoteInputs){ + for (RemoteInput remoteIn : repliableNotification.remoteInputs) { getDetailsOfNotification(remoteIn); remoteInputs[i] = remoteIn; localBundle.putCharSequence(remoteInputs[i].getResultKey(), message); i++; } RemoteInput.addResultsToIntent(remoteInputs, localIntent, localBundle); - + try { repliableNotification.pendingIntent.send(context, 0, localIntent); } catch (PendingIntent.CanceledException e) { @@ -284,26 +278,26 @@ String resultKey = remoteInput.getResultKey(); String label = remoteInput.getLabel().toString(); Boolean canFreeForm = remoteInput.getAllowFreeFormInput(); - if(remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) { + if (remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) { String[] possibleChoices = new String[remoteInput.getChoices().length]; - for(int i = 0; i < remoteInput.getChoices().length; i++){ + for (int i = 0; i < remoteInput.getChoices().length; i++) { possibleChoices[i] = remoteInput.getChoices()[i].toString(); } } } - + private String getNotificationTitle(Notification notification) { final String TITLE_KEY = "android.title"; final String TEXT_KEY = "android.text"; String title = ""; - if(notification != null) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (notification != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { try { Bundle extras = notification.extras; title = extras.getCharSequence(TITLE_KEY).toString(); - } catch(Exception e) { - Log.w("NotificationPlugin","problem parsing notification extras for " + notification.tickerText); + } catch (Exception e) { + Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText); e.printStackTrace(); } } @@ -313,17 +307,17 @@ return title; } - + private RepliableNotification extractRepliableNotification(StatusBarNotification statusBarNotification) { RepliableNotification repliableNotification = new RepliableNotification(); - - if(statusBarNotification != null) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + + if (statusBarNotification != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { try { Boolean reply = false; - + //works for WhatsApp, but not for Telegram - if(statusBarNotification.getNotification().actions!=null) { + if (statusBarNotification.getNotification().actions != null) { for (Notification.Action act : statusBarNotification.getNotification().actions) { if (act != null && act.getRemoteInputs() != null) { repliableNotification.remoteInputs.addAll(Arrays.asList(act.getRemoteInputs())); @@ -337,28 +331,28 @@ repliableNotification.tag = statusBarNotification.getTag();//TODO find how to pass Tag with sending PendingIntent, might fix Hangout problem } - } catch(Exception e) { - Log.w("NotificationPlugin","problem extracting notification wear for " + statusBarNotification.getNotification().tickerText); + } catch (Exception e) { + Log.w("NotificationPlugin", "problem extracting notification wear for " + statusBarNotification.getNotification().tickerText); e.printStackTrace(); } } } - + return repliableNotification; } private String getNotificationText(Notification notification) { final String TEXT_KEY = "android.text"; String text = ""; - if(notification != null) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (notification != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { try { Bundle extras = notification.extras; Object extraTextExtra = extras.get(TEXT_KEY); if (extraTextExtra != null) text = extraTextExtra.toString(); - } catch(Exception e) { - Log.w("NotificationPlugin","problem parsing notification extras for " + notification.tickerText); + } catch (Exception e) { + Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText); e.printStackTrace(); } } @@ -380,8 +374,8 @@ final String TEXT_KEY = "android.text"; String ticker = ""; - if(notification != null) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (notification != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { try { Bundle extras = notification.extras; String extraTitle = extras.getCharSequence(TITLE_KEY).toString(); @@ -396,14 +390,14 @@ } else if (extraText != null) { ticker = extraText; } - } catch(Exception e) { - Log.w("NotificationPlugin","problem parsing notification extras for " + notification.tickerText); + } catch (Exception e) { + Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText); e.printStackTrace(); } } if (ticker.isEmpty()) { - ticker = (notification.tickerText != null)? notification.tickerText.toString() : ""; + ticker = (notification.tickerText != null) ? notification.tickerText.toString() : ""; } } @@ -435,17 +429,17 @@ try { //If service just started, this call will throw an exception because the answer is not ready yet sendCurrentNotifications(service); - } catch(Exception e) { - Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying in 100ms..."); + } catch (Exception e) { + Log.e("onPackageReceived", "Error when answering 'request': Service failed to start. Retrying in 100ms..."); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(100); - Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying..."); + Log.e("onPackageReceived", "Error when answering 'request': Service failed to start. Retrying..."); sendCurrentNotifications(service); } catch (Exception e) { - Log.e("onPackageReceived","Error when answering 'request': Service failed to start twice!"); + Log.e("onPackageReceived", "Error when answering 'request': Service failed to start twice!"); e.printStackTrace(); } } @@ -466,9 +460,9 @@ }); } else if (np.has("requestReplyId") && np.has("message")) { - + replyToNotification(np.getString("requestReplyId"), np.getString("message")); - + } return true; @@ -500,7 +494,7 @@ deviceActivity.startActivityForResult(intent, MaterialActivity.RESULT_NEEDS_RELOAD); } }) - .setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() { + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //Do nothing @@ -512,7 +506,7 @@ @Override public String[] getSupportedPackageTypes() { - return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST,PACKAGE_TYPE_NOTIFICATION_REPLY}; + return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST, PACKAGE_TYPE_NOTIFICATION_REPLY}; } @Override @@ -527,7 +521,7 @@ } else { int first = compatKey.indexOf(':'); if (first == -1) { - Log.e("cancelNotificationCompa","Not formated like a notification key: "+ compatKey); + Log.e("cancelNotificationCompa", "Not formated like a notification key: " + compatKey); return; } int last = compatKey.lastIndexOf(':'); @@ -563,23 +557,23 @@ return result; } - public String getChecksum(byte[] data){ + public String getChecksum(byte[] data) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(data); return bytesToHex(md.digest()); } catch (NoSuchAlgorithmException e) { - Log.e("KDEConenct", "Error while generating checksum", e); + Log.e("KDEConenct", "Error while generating checksum", e); } return null; } public static String bytesToHex(byte[] bytes) { char[] hexArray = "0123456789ABCDEF".toCharArray(); char[] hexChars = new char[bytes.length * 2]; - for ( int j = 0; j < bytes.length; j++ ) { + for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/RepliableNotification.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/RepliableNotification.java --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/RepliableNotification.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/RepliableNotification.java @@ -1,5 +1,5 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin; - + import android.app.Notification; import android.app.PendingIntent; import android.os.Bundle;