Skip to content

Commit 124eb7e

Browse files
authored
Merge pull request #24 from akaMrNagar/dev
Feat: Notification grouping and minor improvements.
2 parents d018e86 + 9c5cee9 commit 124eb7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+629
-298
lines changed

android/app/build.gradle

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,36 @@ android {
4545
}
4646

4747

48+
signingConfigs {
49+
release {
50+
if (System.getenv("KEYSTORE_FILE") != null) {
51+
storeFile file(System.getenv("KEYSTORE_FILE"))
52+
storePassword System.getenv("STORE_PASSWORD")
53+
keyAlias System.getenv("KEY_ALIAS")
54+
keyPassword System.getenv("KEY_PASSWORD")
55+
}
56+
}
57+
}
58+
4859
buildTypes {
4960
release {
5061
ndk {
5162
debugSymbolLevel 'full'
5263
}
53-
if (System.getenv("KEYSTORE_FILE") != null) {
54-
signingConfigs {
55-
register("release") {
56-
storeFile file(System.getenv("KEYSTORE_FILE"))
57-
storePassword System.getenv("STORE_PASSWORD")
58-
keyAlias System.getenv("KEY_ALIAS")
59-
keyPassword System.getenv("KEY_PASSWORD")
60-
}
61-
}
62-
signingConfig = signingConfigs.release
63-
} else {
64-
signingConfig = signingConfigs.debug
65-
}
64+
resValue "string", "app_name", "Mindful"
65+
signingConfig = signingConfigs.release
6666
}
6767

6868
debug {
6969
applicationIdSuffix ".debug"
70-
signingConfig signingConfigs.debug
70+
resValue "string", "app_name", "Mindful Debug"
71+
signingConfig = signingConfigs.release ?: signingConfigs.debug
7172
}
7273

7374
profile {
7475
applicationIdSuffix ".profile"
75-
signingConfig signingConfigs.debug
76+
resValue "string", "app_name", "Mindful Profile"
77+
signingConfig = signingConfigs.release ?: signingConfigs.debug
7678
}
7779
}
7880
buildFeatures {

android/app/src/main/java/com/mindful/android/MainActivity.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
121121
Intent currentIntent = getIntent();
122122
Map<String, Object> intentData = new HashMap<>();
123123
intentData.put("route", currentIntent.getStringExtra(INTENT_EXTRA_INITIAL_ROUTE));
124-
intentData.put("targetedPackage", currentIntent.getStringExtra(INTENT_EXTRA_PACKAGE_NAME));
125-
intentData.put("isSelfRestart", currentIntent.getBooleanExtra(INTENT_EXTRA_IS_SELF_RESTART, false));
124+
intentData.put("extraPackageName", currentIntent.getStringExtra(INTENT_EXTRA_PACKAGE_NAME));
125+
intentData.put("extraIsSelfStart", currentIntent.getBooleanExtra(INTENT_EXTRA_IS_SELF_RESTART, false));
126126

127127
// Update intent data on flutter side
128128
mMethodChannel.invokeMethod("updateIntentData", intentData);
@@ -160,7 +160,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
160160
break;
161161
}
162162
case "getUpComingNotifications": {
163-
result.success(SharedPrefsHelper.getUpComingNotificationsArrayString(this));
163+
result.success(SharedPrefsHelper.getSerializedNotificationsJson(this));
164164
break;
165165
}
166166
case "getShortsScreenTimeMs": {

android/app/src/main/java/com/mindful/android/helpers/SharedPrefsHelper.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
import org.json.JSONArray;
3232
import org.json.JSONObject;
3333

34+
import java.util.ArrayList;
3435
import java.util.Calendar;
3536
import java.util.HashMap;
3637
import java.util.HashSet;
38+
import java.util.LinkedHashMap;
39+
import java.util.Map;
3740

3841
/**
3942
* Helper class to manage SharedPreferences operations.
@@ -352,6 +355,23 @@ public static HashSet<Integer> getSetNotificationBatchSchedules(@NonNull Context
352355
}
353356
}
354357

358+
/**
359+
* Fetches the hashset of notification batched apps if jsonBatchedApps is null else store it's json.
360+
*
361+
* @param context The application context.
362+
* @param jsonBatchedApps The JSON string of notification batched apps.
363+
*/
364+
@NonNull
365+
public static HashSet<String> getSetNotificationBatchedApps(@NonNull Context context, @Nullable String jsonBatchedApps) {
366+
checkAndInitializeNotificationBatchPrefs(context);
367+
if (jsonBatchedApps == null) {
368+
return JsonDeserializer.jsonStrToStringHashSet(mNotificationBatchPrefs.getString(PREF_KEY_BATCHED_APPS, ""));
369+
} else {
370+
mNotificationBatchPrefs.edit().putString(PREF_KEY_BATCHED_APPS, jsonBatchedApps).apply();
371+
return JsonDeserializer.jsonStrToStringHashSet(jsonBatchedApps);
372+
}
373+
}
374+
355375
/**
356376
* Creates and Inserts a new notification into SharedPreferences based on the passed object.
357377
*
@@ -361,7 +381,7 @@ public static HashSet<Integer> getSetNotificationBatchSchedules(@NonNull Context
361381
public static void insertNotificationToPrefs(@NonNull Context context, @NonNull UpcomingNotification notification) {
362382
checkAndInitializeNotificationBatchPrefs(context);
363383

364-
// Create new notification object
384+
// Create new json object
365385
JSONObject currentNotification = new JSONObject(notification.toMap());
366386

367387
// Get existing notifications
@@ -379,7 +399,6 @@ public static void insertNotificationToPrefs(@NonNull Context context, @NonNull
379399
notificationsArray.remove(i);
380400
}
381401
}
382-
383402
} catch (Exception e1) {
384403
notificationsArray = new JSONArray();
385404
}
@@ -397,26 +416,9 @@ public static void insertNotificationToPrefs(@NonNull Context context, @NonNull
397416
* @return A JSON string representing the stored notifications array.
398417
*/
399418
@NonNull
400-
public static String getUpComingNotificationsArrayString(@NonNull Context context) {
419+
public static String getSerializedNotificationsJson(@NonNull Context context) {
401420
checkAndInitializeNotificationBatchPrefs(context);
402421
return mNotificationBatchPrefs.getString(PREF_KEY_UPCOMING_NOTIFICATIONS, "[]");
403422
}
404423

405-
/**
406-
* Fetches the hashset of notification batched apps if jsonBatchedApps is null else store it's json.
407-
*
408-
* @param context The application context.
409-
* @param jsonBatchedApps The JSON string of notification batched apps.
410-
*/
411-
@NonNull
412-
public static HashSet<String> getSetNotificationBatchedApps(@NonNull Context context, @Nullable String jsonBatchedApps) {
413-
checkAndInitializeNotificationBatchPrefs(context);
414-
if (jsonBatchedApps == null) {
415-
return JsonDeserializer.jsonStrToStringHashSet(mNotificationBatchPrefs.getString(PREF_KEY_BATCHED_APPS, ""));
416-
} else {
417-
mNotificationBatchPrefs.edit().putString(PREF_KEY_BATCHED_APPS, jsonBatchedApps).apply();
418-
return JsonDeserializer.jsonStrToStringHashSet(jsonBatchedApps);
419-
}
420-
}
421-
422424
}

android/app/src/main/java/com/mindful/android/models/UpcomingNotification.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ public class UpcomingNotification {
1919
public final String contentText;
2020
public final long timeStamp;
2121

22-
// Constructor that initializes the object using StatusBarNotification
22+
/**
23+
* Constructor that initializes the object using StatusBarNotification
24+
*
25+
* @param sbn Status Bar Notification object
26+
*/
2327
public UpcomingNotification(@NonNull StatusBarNotification sbn) {
2428
Bundle extras = sbn.getNotification().extras;
2529
this.packageName = sbn.getPackageName();
26-
this.titleText = extras.getString(Notification.EXTRA_TITLE, "Null").trim();
27-
this.contentText = extras.getString(Notification.EXTRA_TEXT, "Null").trim();
2830
this.timeStamp = sbn.getPostTime();
31+
this.titleText = extras.getCharSequence(Notification.EXTRA_TITLE, "").toString().trim();
32+
this.contentText = extras.getCharSequence(Notification.EXTRA_TEXT, "").toString().trim();
2933
}
3034

3135
/**

android/app/src/main/java/com/mindful/android/receivers/alarm/NotificationBatchReceiver.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.mindful.android.R;
2525
import com.mindful.android.helpers.AlarmTasksSchedulingHelper;
2626
import com.mindful.android.helpers.SharedPrefsHelper;
27-
import com.mindful.android.utils.AppConstants;
2827
import com.mindful.android.utils.Utils;
2928

3029
import org.json.JSONArray;
@@ -56,7 +55,7 @@ public NotificationBatchWorker(@NonNull Context context, @NonNull WorkerParamete
5655
public Result doWork() {
5756
try {
5857
// Return if no available notifications
59-
String jsonStr = SharedPrefsHelper.getUpComingNotificationsArrayString(mContext);
58+
String jsonStr = SharedPrefsHelper.getSerializedNotificationsJson(mContext);
6059
int notificationsCount = new JSONArray(jsonStr).length();
6160
if (notificationsCount == 0) return Result.success();
6261

android/app/src/main/java/com/mindful/android/services/MindfulAccessibilityService.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@ public class MindfulAccessibilityService extends AccessibilityService implements
8787
* These are used to retrieve/extract url from the browsers.
8888
*/
8989
private final HashSet<String> mUrlBarNodeIds = new HashSet<>(Set.of(
90-
":id/url_bar",
91-
":id/mozac_browser_toolbar_url_view",
90+
":id/url_bar", // Chrome
91+
":id/mozac_browser_toolbar_url_view", // Firefox
9292
":id/url",
9393
":id/search",
9494
":id/url_field",
9595
":id/location_bar_edit_text",
9696
":id/addressbarEdit",
97-
":id/bro_omnibar_address_title_text"
97+
":id/bro_omnibar_address_title_text",
98+
":id/cbn_tv_title" // Quetta Browser
9899
));
99100

100101
// Fixed thread pool for parallel event processing

android/app/src/main/java/com/mindful/android/services/MindfulNotificationListenerService.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,39 +21,41 @@
2121
import android.service.notification.StatusBarNotification;
2222
import android.util.Log;
2323

24-
import androidx.annotation.NonNull;
25-
import androidx.annotation.Nullable;
2624

2725
import com.mindful.android.generics.ServiceBinder;
2826
import com.mindful.android.helpers.SharedPrefsHelper;
2927
import com.mindful.android.models.UpcomingNotification;
3028
import com.mindful.android.utils.Utils;
3129

32-
import org.jetbrains.annotations.Contract;
33-
34-
import java.util.ArrayList;
3530
import java.util.HashSet;
36-
import java.util.Map;
31+
import java.util.Set;
3732

3833

3934
public class MindfulNotificationListenerService extends NotificationListenerService {
4035
private final String TAG = "Mindful.MindfulNotificationService";
4136
private final ServiceBinder<MindfulNotificationListenerService> mBinder = new ServiceBinder<>(MindfulNotificationListenerService.this);
37+
private final Set<String> mSocialMediaPackages = Set.of("com.whatsapp", "com.instagram.android", "com.snapchat.android");
38+
4239
private HashSet<String> mDistractingApps = new HashSet<>(0);
4340
private boolean mIsListenerActive = false;
4441

4542
@Override
4643
public void onListenerConnected() {
4744
super.onListenerConnected();
4845
mDistractingApps = SharedPrefsHelper.getSetNotificationBatchedApps(this, null);
46+
47+
//
48+
SharedPrefsHelper.insertCrashLogToPrefs(this, new Throwable("MindfulNotificationListenerService is CONNECTED by system"));
4949
mIsListenerActive = true;
5050
}
5151

5252
@Override
5353
public void onListenerDisconnected() {
5454
super.onListenerDisconnected();
55-
mIsListenerActive = false;
5655

56+
//
57+
SharedPrefsHelper.insertCrashLogToPrefs(this, new Throwable("MindfulNotificationListenerService is DIS-CONNECTED by system"));
58+
mIsListenerActive = false;
5759
}
5860

5961
@Override
@@ -62,45 +64,51 @@ public void onNotificationPosted(StatusBarNotification sbn) {
6264
if (!mIsListenerActive) return;
6365
String packageName = sbn.getPackageName();
6466
try {
65-
6667
// Return if the posting app is not marked as distracting
6768
if (!mDistractingApps.contains(packageName) || !sbn.isClearable()) return;
6869

70+
6971
// Dismiss notification
7072
cancelNotification(sbn.getKey());
7173
Log.d(TAG, "onNotificationPosted: Notification dismissed");
7274

73-
// Check if we need to store it or not
74-
if (shouldStoreNotification(packageName, sbn.getTag())) {
75-
UpcomingNotification notification = new UpcomingNotification(sbn);
76-
SharedPrefsHelper.insertNotificationToPrefs(this, notification);
77-
Log.d(TAG, "onNotificationPosted: Notification stored from package: " + packageName);
75+
// Return if it is from social media but does not have tag
76+
if (sbn.getTag() == null && mSocialMediaPackages.contains(packageName)) return;
77+
78+
// Check if we can store it or not
79+
UpcomingNotification notification = new UpcomingNotification(sbn);
80+
if (notification.titleText.isEmpty() || notification.contentText.isEmpty()) {
81+
Log.d(TAG, "onNotificationPosted: Notification is not valid, so skipping it from storing.");
82+
SharedPrefsHelper.insertCrashLogToPrefs(
83+
this,
84+
new Exception("Invalid notification from " + packageName + " with title: " + notification.titleText + " and content: " + notification.contentText)
85+
);
86+
return;
7887
}
7988

89+
SharedPrefsHelper.insertNotificationToPrefs(this, notification);
90+
Log.d(TAG, "onNotificationPosted: Notification stored from package: " + packageName);
8091
} catch (Exception e) {
8192
SharedPrefsHelper.insertCrashLogToPrefs(this, e);
8293
Log.e(TAG, "onNotificationPosted: Something went wrong for package: " + packageName, e);
8394
}
8495
}
8596

8697

87-
@Contract(pure = true)
88-
private boolean shouldStoreNotification(@NonNull String packageName, @Nullable String tag) {
89-
// For whatsapp
90-
if (packageName.equals("com.whatsapp") && tag == null) return false;
91-
return true;
92-
}
93-
94-
9598
public void updateDistractingApps(HashSet<String> distractingApps) {
9699
mDistractingApps = distractingApps;
97100
Log.d(TAG, "updateDistractingApps: Distracting apps updated successfully");
98101
}
99102

100-
101103
@Override
102104
public IBinder onBind(Intent intent) {
103105
String action = Utils.getActionFromIntent(intent);
104106
return action.equals(ACTION_BIND_TO_MINDFUL) ? mBinder : super.onBind(intent);
105107
}
108+
109+
@Override
110+
public void onDestroy() {
111+
super.onDestroy();
112+
SharedPrefsHelper.insertCrashLogToPrefs(this, new Throwable("MindfulNotificationListenerService is DESTROYED"));
113+
}
106114
}

android/app/src/main/java/com/mindful/android/utils/AppConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public class AppConstants {
1616
public static final String FLUTTER_METHOD_CHANNEL = "com.mindful.android.methodchannel";
1717

1818
// Extra intent data
19-
public static final String INTENT_EXTRA_IS_SELF_RESTART = "com.mindful.android.isSelfRestart";
2019
public static final String INTENT_EXTRA_INITIAL_ROUTE = "com.mindful.android.initialRoute";
20+
public static final String INTENT_EXTRA_IS_SELF_RESTART = "com.mindful.android.isSelfRestart";
2121
public static final String INTENT_EXTRA_PACKAGE_NAME = "com.mindful.android.launchedAppPackageName";
2222
public static final String INTENT_EXTRA_DIALOG_INFO = "com.mindful.android.dialogInformation";
2323
public static final String INTENT_EXTRA_MAX_PROGRESS = "com.mindful.android.maxProgress";

android/app/src/main/res/values-ja/strings.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
~ */
1111
-->
1212
<resources>
13-
<string name="app_name" comment="app_name app values">Mindful</string>
1413
<string name="accessibility_description">Mindful アプリは、ユーザー補助を使用して、ウェブサイトやアプリのショート動画をブロックします。ブロックリストに登録されたURLやコンテンツへのアクセスを制限することで、集中力を維持するのに役立ちます。 \n\n⚠️注意:Mindful はプライバシーを最優先に考えています。100%安全でオフラインで動作します。個人データの収集や保存は一切行いません。 </string>
1514
<string name="admin_description">Mindful は、ユーザーのデータを収集、保存、または送信することはありません。無料でオープンソースのソフトウェア(FOSS)なので、ソースコードを自由に確認・変更できます。管理者権限は、アプリの正常な動作に必要なシステム操作にのみ使用され、プライバシーは完全に保護されます。</string>
1615
<string name="toast_enable_notification">通知を許可する</string>

android/app/src/main/res/values/strings.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
<resources>
1414
<!-- app values -->
15-
<string name="app_name" translatable="false">Mindful</string>
1615
<string name="accessibility_description">The Mindful app uses accessibility services to block
1716
websites and short-form content on apps. It checks URLs and content against your blocklist
1817
and prevents access to help you stay focused. \n\n⚠️Note: Your privacy is our priority.

0 commit comments

Comments
 (0)