Skip to content

Commit 072bb08

Browse files
committed
refactored
1 parent 1af7b06 commit 072bb08

File tree

9 files changed

+107
-84
lines changed

9 files changed

+107
-84
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Flutter plugin for notification read & reply.
44

5-
<img src="https://i.imgur.com/462Y6wf.gif" title="Flutter_Shortcuts"/>
5+
<img src="https://i.imgur.com/kz6uoXm.png" title="Flutter_Shortcuts"/>
66

77
![GitHub](https://img.shields.io/github/license/DevsOnFlutter/reflex?style=plastic) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/DevsOnFlutter/reflex?style=plastic) ![GitHub top language](https://img.shields.io/github/languages/top/DevsOnFlutter/reflex?style=plastic) ![GitHub language count](https://img.shields.io/github/languages/count/DevsOnFlutter/reflex?style=plastic) ![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/DevsOnFlutter/reflex?style=plastic) ![GitHub issues](https://img.shields.io/github/issues/DevsOnFlutter/reflex?style=plastic) ![GitHub Repo stars](https://img.shields.io/github/stars/DevsOnFlutter/reflex?style=social) ![GitHub forks](https://img.shields.io/github/forks/DevsOnFlutter/reflex?style=social)
88

android/src/main/java/com/devsonflutter/reflex/EventCallHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.devsonflutter.reflex.notification.NotificationListener;
2121
import com.devsonflutter.reflex.notification.NotificationReceiver;
2222
import com.devsonflutter.reflex.notification.NotificationUtils;
23-
import com.devsonflutter.reflex.notification.autoReply.AutoReply;
2423
import com.devsonflutter.reflex.permission.NotificationPermission;
2524

2625
import java.util.List;

android/src/main/java/com/devsonflutter/reflex/MethodCallHandler.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/*
2+
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
4+
All rights reserved.
5+
6+
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file
7+
for more details.
8+
9+
*/
10+
111
package com.devsonflutter.reflex;
212

313
import android.util.Log;

android/src/main/java/com/devsonflutter/reflex/notification/NotificationListener.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,18 @@
1919
import android.service.notification.StatusBarNotification;
2020
import androidx.annotation.RequiresApi;
2121

22-
import com.devsonflutter.reflex.EventCallHandler;
2322
import com.devsonflutter.reflex.ReflexPlugin;
2423
import com.devsonflutter.reflex.notification.autoReply.AutoReply;
2524

26-
import java.util.HashMap;
27-
import java.util.List;
2825
import java.util.Map;
2926

30-
import io.flutter.Log;
31-
import io.flutter.plugin.common.EventChannel;
32-
3327
/* Notification Listener */
3428
@RequiresApi(api = VERSION_CODES.JELLY_BEAN_MR2)
3529
@SuppressLint("OverrideAbstract")
3630
public class NotificationListener extends NotificationListenerService {
3731

3832
private static final String TAG = ReflexPlugin.getPluginTag();
33+
private final Map<String, Object> autoReply = ReflexPlugin.autoReply;
3934

4035
@RequiresApi(api = VERSION_CODES.N)
4136
@Override
@@ -73,15 +68,11 @@ public void onNotificationPosted(StatusBarNotification notification) {
7368
sendBroadcast(intent);
7469

7570
// Sending AutoReply
76-
Map<String, Object> autoReply = ReflexPlugin.autoReply;
77-
if(autoReply != null) {
78-
List<String> autoReplyPackageNameList = (List<String>) autoReply.get("packageNameList");
71+
if(NotificationUtils.canReply(notification))
72+
{
7973
String message = (String) autoReply.get("message");
80-
assert autoReplyPackageNameList != null;
81-
if(autoReplyPackageNameList.contains(packageName)) {
82-
// Reply to notification
83-
new AutoReply(ReflexPlugin.context).sendReply(notification, packageName, title, message);
84-
}
74+
// Reply to notification
75+
new AutoReply(ReflexPlugin.context).sendReply(notification, packageName, title, message);
8576
}
8677
}
8778

android/src/main/java/com/devsonflutter/reflex/notification/NotificationReceiver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
3-
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
44
All rights reserved.
55
66
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file

android/src/main/java/com/devsonflutter/reflex/notification/NotificationUtils.java

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/*
2+
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
4+
All rights reserved.
5+
6+
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file
7+
for more details.
8+
9+
*/
10+
111
package com.devsonflutter.reflex.notification;
212

313
import android.app.Notification;
@@ -11,12 +21,14 @@
1121
import androidx.core.app.NotificationCompat;
1222
import androidx.core.app.RemoteInput;
1323

24+
import com.devsonflutter.reflex.ReflexPlugin;
1425
import com.devsonflutter.reflex.notification.model.App;
1526
import com.devsonflutter.reflex.notification.model.NotificationWear;
1627

1728
import java.util.ArrayList;
1829
import java.util.HashSet;
1930
import java.util.List;
31+
import java.util.Map;
2032
import java.util.Set;
2133
import java.util.UUID;
2234

@@ -27,8 +39,11 @@ public class NotificationUtils {
2739
public static String NOTIFICATION_PACKAGE_NAME = "notification_package_name";
2840
public static String NOTIFICATION_MESSAGE = "notification_message";
2941
public static String NOTIFICATION_TITLE = "notification_title";
30-
public static Set<App> SUPPORTED_APPS = new HashSet<App>();
3142

43+
private static final Map<String, Object> autoReply = ReflexPlugin.autoReply;
44+
45+
private static final List<String> listeningPackageNameList = ReflexPlugin.packageNameList;
46+
private static final List<String> listeningExceptionPackageNameList = ReflexPlugin.packageNameExceptionList;
3247

3348
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
3449
public static NotificationWear extractWearNotification(StatusBarNotification sbn){
@@ -61,16 +76,16 @@ public static NotificationWear extractWearNotification(StatusBarNotification sbn
6176
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
6277
public static boolean isNewNotification(StatusBarNotification sbn) {
6378
return sbn.getNotification().when == 0 ||
64-
(System.currentTimeMillis() - sbn.getNotification().when) < MAX_OLD_NOTIFICATION_CAN_BE_REPLIED_TIME_MS;
79+
(System.currentTimeMillis() - sbn.getNotification().when)
80+
< MAX_OLD_NOTIFICATION_CAN_BE_REPLIED_TIME_MS;
6581
}
6682

6783
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
6884
public static String getTitle(StatusBarNotification sbn) {
6985
String title;
7086
if (sbn.getNotification().extras.getBoolean("android.isGroupConversation")) {
7187
title = sbn.getNotification().extras.getString("android.hiddenConversationTitle");
72-
//Just to avoid null cases, if by any chance hiddenConversationTitle comes null for group message
73-
// then extract group name from title
88+
// Checking if title is null
7489
if (title == null) {
7590
title = sbn.getNotification().extras.getString("android.title");
7691
int index = title.indexOf(':');
@@ -79,7 +94,7 @@ public static String getTitle(StatusBarNotification sbn) {
7994
}
8095
}
8196

82-
//To eliminate the case where group title has number of messages count in it
97+
// Eliminate message count in groups
8398
Parcelable[] b = (Parcelable[]) sbn.getNotification().extras.get("android.messages");
8499
if (b != null && b.length > 1) {
85100
int startIndex = title.lastIndexOf('(');
@@ -97,4 +112,43 @@ public static String getTitle(StatusBarNotification sbn) {
97112
public static String getTitleRaw(StatusBarNotification sbn) {
98113
return sbn.getNotification().extras.getString("android.title");
99114
}
115+
116+
@RequiresApi(api = Build.VERSION_CODES.N)
117+
static boolean canReply(StatusBarNotification notification) {
118+
String notificationPackageName = notification.getPackageName();
119+
120+
boolean isServiceEnabled = false;
121+
List<String> autoReplyPackageNameList = null;
122+
123+
if(autoReply != null) {
124+
isServiceEnabled = true;
125+
autoReplyPackageNameList = (List<String>) autoReply.get("packageNameList");
126+
}
127+
128+
// If AutoReply object coming from flutter side is null, AutoReply feature is disabled
129+
if (!isServiceEnabled) return false;
130+
131+
return isSupportedPackage(notificationPackageName,autoReplyPackageNameList) &&
132+
checkListeningAndReplyPackages(notificationPackageName,autoReplyPackageNameList) &&
133+
NotificationUtils.isNewNotification(notification);
134+
}
135+
136+
private static boolean checkListeningAndReplyPackages(String notificationPackageName,
137+
List<String> replyPackageNameList) {
138+
// TODO: check Listening and Replying PackageNames also debugPrint if necessary
139+
// Use listeningPackageNameList & listeningExceptionPackageNameList
140+
return true;
141+
}
142+
143+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
144+
private static boolean isSupportedPackage(String notificationPackageName, List<String> packageList) {
145+
// If packageNameList coming from flutter is null,
146+
// then AutoReply is enabled for all packageNames
147+
if(packageList == null) {
148+
return true;
149+
}
150+
151+
// Check notification's package name contained in AutoReply's PackageNameList
152+
return packageList.contains(notificationPackageName);
153+
}
100154
}
Lines changed: 11 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
package com.devsonflutter.reflex.notification.autoReply;
1+
/*
2+
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
4+
All rights reserved.
25
3-
import static java.lang.Double.max;
6+
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file
7+
for more details.
8+
9+
*/
10+
11+
package com.devsonflutter.reflex.notification.autoReply;
412

513
import android.app.PendingIntent;
614
import android.content.Context;
715
import android.content.Intent;
816
import android.os.Build;
917
import android.os.Bundle;
1018
import android.service.notification.StatusBarNotification;
11-
import android.text.SpannableString;
1219
import android.util.Log;
1320

1421
import androidx.annotation.RequiresApi;
@@ -33,15 +40,9 @@ public AutoReply(Context context) {
3340

3441
private static final String TAG = ReflexPlugin.getPluginTag();
3542

43+
3644
@RequiresApi(api = Build.VERSION_CODES.N)
3745
public void sendReply(StatusBarNotification sbn, String packageName, CharSequence title,String message){
38-
if (canReply(sbn)) {
39-
reply(sbn,packageName, title, message);
40-
}
41-
}
42-
43-
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
44-
private void reply(StatusBarNotification sbn, String packageName, CharSequence title,String message) {
4546
NotificationWear notificationWear = NotificationUtils.extractWearNotification(sbn);
4647

4748
if (notificationWear.getRemoteInputs().isEmpty()) {
@@ -83,56 +84,4 @@ private void reply(StatusBarNotification sbn, String packageName, CharSequence t
8384
e.printStackTrace();
8485
}
8586
}
86-
87-
88-
89-
@RequiresApi(api = Build.VERSION_CODES.N)
90-
private boolean canReply(StatusBarNotification sbn) {
91-
return isServiceEnabled() &&
92-
isSupportedPackage(sbn) &&
93-
NotificationUtils.isNewNotification(sbn) &&
94-
isGroupMessageAndReplyAllowed(sbn) &&
95-
canSendReplyNow(sbn);
96-
}
97-
98-
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
99-
private boolean isGroupMessageAndReplyAllowed(StatusBarNotification sbn) {
100-
String rawTitle = NotificationUtils.getTitleRaw(sbn);
101-
//android.text returning SpannableString
102-
SpannableString rawText = SpannableString.valueOf("" + sbn.getNotification().extras.get("android.text"));
103-
// Detect possible group image message by checking for colon and text starts with camera icon #181
104-
boolean isPossiblyAnImageGrpMsg = ((rawTitle != null) && (": ".contains(rawTitle) || "@ ".contains(rawTitle)))
105-
&& ((rawText != null) && rawText.toString().contains("\uD83D\uDCF7"));
106-
if (!sbn.getNotification().extras.getBoolean("android.isGroupConversation")) {
107-
return !isPossiblyAnImageGrpMsg;
108-
}
109-
// Input from Flutter Side
110-
return true;
111-
}
112-
113-
private boolean isSupportedPackage(StatusBarNotification sbn) {
114-
// TODO: true if sbn's package name is equal to PackageName in AutoReply
115-
return true;
116-
}
117-
118-
private boolean isServiceEnabled() {
119-
// TODO: true if AutoReply object coming from Flutter is not null, else false
120-
return true;
121-
}
122-
123-
124-
@RequiresApi(api = Build.VERSION_CODES.N)
125-
private boolean canSendReplyNow(StatusBarNotification sbn) {
126-
// Do not reply to consecutive notifications from same person/group that arrive in below time
127-
// This helps to prevent infinite loops when users on both end uses Watomatic or similar app
128-
int DELAY_BETWEEN_REPLY_IN_MILLISECONDS = 10 * 1000;
129-
130-
String title = NotificationUtils.getTitle(sbn);
131-
String selfDisplayName = sbn.getNotification().extras.getString("android.selfDisplayName");
132-
if (title != null && title.equalsIgnoreCase(selfDisplayName)) { //to protect double reply in case where if notification is not dismissed and existing notification is updated with our reply
133-
return false;
134-
}
135-
long timeDelay = 1000;
136-
return (System.currentTimeMillis() - 1000 >= max(timeDelay, DELAY_BETWEEN_REPLY_IN_MILLISECONDS));
137-
}
13887
}

android/src/main/java/com/devsonflutter/reflex/notification/model/App.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/*
2+
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
4+
All rights reserved.
5+
6+
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file
7+
for more details.
8+
9+
*/
10+
111
package com.devsonflutter.reflex.notification.model;
212

313
public class App {

android/src/main/java/com/devsonflutter/reflex/notification/model/NotificationWear.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/*
2+
3+
Copyright (c) 2022 DevsOnFlutter (Devs On Flutter)
4+
All rights reserved.
5+
6+
The plugin is governed by the BSD-3-clause License. Please see the LICENSE file
7+
for more details.
8+
9+
*/
10+
111
package com.devsonflutter.reflex.notification.model;
212

313
import android.app.PendingIntent;

0 commit comments

Comments
 (0)