Skip to content

Commit 900bb37

Browse files
authored
Merge pull request #223 from itsdrnoob/dev/2.4.0
Dev/2.4.0
2 parents 3121b94 + d7de336 commit 900bb37

File tree

1,380 files changed

+3785
-1361
lines changed

Some content is hidden

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

1,380 files changed

+3785
-1361
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@
33
All notable changes to Data Monitor will be documented in this file.
44

55

6+
## v2.4.0
7+
8+
Data Monitor v2.4.0 release <br>
9+
This release features multiple changes and improvements.
10+
11+
### What's new?
12+
- Added support for Android 14.
13+
- Introducing Smart data allocation and quota alert (Beta). Manage your data plan with a daily quota, data rollover and usage alert.
14+
- Updated plan details view. The home screen now features the number of days remaining in your data plan.
15+
- Added custom filter for app usage. Now you can take control over viewing app data usage for any specific time period.
16+
17+
### Fixes and Improvements
18+
- Fixed app usage showing incorrect total data usage at times.
19+
- Fixed notification issues on Android 14.
20+
- Improved calculations related to data plan and its validity.
21+
- Localisation fixes and improvements.
22+
- Fixed certain crashes and improved exception handling.
23+
- Added Malay and Hebrew translations.
24+
- Other minor changes and improvements.
25+
26+
627
## v2.3.2
728

829
Data Monitor v2.3.2 release <br>

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[![Version](https://shields.io/badge/version-v2.4.0-087AFF.svg)](https://github.com/itsdrnoob/DataMonitor/tree/dev/2.4.0)
22
[![Platform](https://shields.io/badge/platform-android-green.svg)](https://github.com/itsdrnoob/DataMonitor)
33
[![License](https://img.shields.io/badge/license-GPL3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
4-
[![Release](https://shields.io/badge/release-v2.3.2-blue.svg)](https://github.com/itsdrnoob/DataMonitor/releases)
4+
[![Release](https://shields.io/badge/release-v2.4.0-blue.svg)](https://github.com/itsdrnoob/DataMonitor/releases)
55
[![Chat](https://img.shields.io/badge/Telegram%20Chat-blue?logo=telegram)](https://t.me/datamonitor)
66
[![Downloads](https://img.shields.io/github/downloads/itsdrnoob/DataMonitor/total)](https://github.com/itsdrnoob/DataMonitor/releases)
77

VERSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v2.3.2
1+
v2.4.0

app/build.gradle

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ plugins {
44
}
55

66
android {
7-
compileSdkVersion 33
8-
buildToolsVersion "30.0.3"
7+
compileSdk 34
8+
// buildToolsVersion "30.0.3"
99

1010
defaultConfig {
1111
applicationId "com.drnoob.datamonitor"
1212
minSdkVersion 23
13-
targetSdkVersion 33
14-
versionCode 24
15-
versionName 'v2.3.2'
16-
resConfigs "en", "ar", "cs", "de", "es", "fr", "hi", "in", "it", "ja", "ko",
17-
"ml", "mr", "nb-rNO", "nl", "pl", "pt-rBR", "ro", "ru", "tr", "uk", "uz", "vi", "zh-rCN", "zh-rTW"
13+
targetSdkVersion 34
14+
versionCode 29
15+
versionName 'v2.4.0'
16+
resConfigs "en", "ar", "cs", "de", "es", "fr", "hi", "in", "it", "iw", "ja", "ko", "ml", "mr", "ms",
17+
"nb-rNO", "nl", "pl", "pt-rBR", "ro", "ru", "tr", "uk", "uz", "vi", "zh-rCN", "zh-rTW"
1818

1919
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2020
}
@@ -74,4 +74,6 @@ dependencies {
7474
implementation 'io.ipinfo:ipinfo-api:2.1'
7575
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
7676
implementation 'com.github.bumptech.glide:glide:4.15.1'
77+
implementation "androidx.work:work-runtime:2.8.1"
78+
implementation "androidx.work:work-runtime-ktx:2.8.1"
7779
}

app/proguard-rules.pro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@
2020
# hide the original source file name.
2121
#-renamesourcefileattribute SourceFile
2222

23-
-keep class io.ipinfo.api.** { *; }
23+
-keep class io.ipinfo.api.** { *; }
24+
-keepattributes SourceFile,LineNumberTable

app/src/main/AndroidManifest.xml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
1212
tools:ignore="ProtectedPermissions" />
1313
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
14+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
1415
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
1516
<uses-permission android:name="android.permission.VIBRATE" /> <!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" -->
1617
<!-- tools:ignore="QueryAllPackagesPermission" /> -->
@@ -91,7 +92,12 @@
9192
<service
9293
android:name=".utils.NotificationService"
9394
android:enabled="true"
94-
android:exported="true" />
95+
android:exported="true"
96+
android:foregroundServiceType="specialUse">
97+
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
98+
android:value="Service used to measure and show the data usage"/>
99+
</service>
100+
95101
<service
96102
android:name=".utils.DataUsageMonitor"
97103
android:enabled="true"
@@ -144,11 +150,19 @@
144150
<service
145151
android:name=".utils.LiveNetworkMonitor"
146152
android:enabled="true"
147-
android:exported="true" />
153+
android:exported="true"
154+
android:foregroundServiceType="specialUse">
155+
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
156+
android:value="Service used to measure and show the network connection speed"/>
157+
</service>
148158
<service
149159
android:name=".utils.CompoundNotification"
150160
android:enabled="true"
151-
android:exported="false" />
161+
android:exported="false"
162+
android:foregroundServiceType="specialUse">
163+
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
164+
android:value="Service used to measure and show the network connection speed as well as the data usage"/>
165+
</service>
152166

153167
<activity
154168
android:name=".ui.activities.MainActivity"
@@ -177,6 +191,12 @@
177191
android:enabled="true"
178192
android:exported="true" />
179193

194+
<receiver android:name=".utils.DailyQuotaAlertReceiver"
195+
android:exported="true"/>
196+
197+
<receiver android:name=".utils.DailyQuotaAlertReceiver$ResetDataQuotaAlert"
198+
android:exported="true"/>
199+
180200
<provider
181201
android:name="androidx.core.content.FileProvider"
182202
android:authorities="${applicationId}.provider"

app/src/main/java/com/drnoob/datamonitor/Common.java

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import android.content.res.Configuration;
4848
import android.content.res.Resources;
4949
import android.graphics.Typeface;
50+
import android.icu.text.MessageFormat;
5051
import android.os.Build;
5152
import android.provider.Settings;
5253
import android.text.Spannable;
@@ -56,7 +57,6 @@
5657
import android.util.Log;
5758
import android.view.View;
5859
import android.view.WindowManager;
59-
import android.widget.Toast;
6060

6161
import androidx.annotation.RequiresApi;
6262
import androidx.appcompat.app.AlertDialog;
@@ -76,6 +76,7 @@
7676
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
7777
import com.google.android.material.snackbar.Snackbar;
7878

79+
import java.text.NumberFormat;
7980
import java.text.ParseException;
8081
import java.text.SimpleDateFormat;
8182
import java.util.ArrayList;
@@ -188,7 +189,6 @@ public static List<LanguageModel> refreshAvailableLanguages() {
188189
list.add(new LanguageModel("Portuguese", "pt", "rBR"));
189190
list.add(new LanguageModel("Spanish", "es", ""));
190191
list.add(new LanguageModel("Ukrainian", "uk", ""));
191-
// list.add(new LanguageModel("Bhojpuri", "bho", ""));
192192
list.add(new LanguageModel("Hindi", "hi", ""));
193193
list.add(new LanguageModel("Indonesian", "in", ""));
194194
list.add(new LanguageModel("Korean", "ko", ""));
@@ -199,6 +199,8 @@ public static List<LanguageModel> refreshAvailableLanguages() {
199199
list.add(new LanguageModel("Czech", "cs", ""));
200200
list.add(new LanguageModel("Vietnamese", "vi", ""));
201201
list.add(new LanguageModel("Japanese", "ja", ""));
202+
list.add(new LanguageModel("Hebrew", "iw", ""));
203+
list.add(new LanguageModel("Malay", "ms", ""));
202204

203205
Collections.sort(list, new Comparator<LanguageModel>() {
204206
@Override
@@ -395,11 +397,11 @@ public static void postAlarmPermissionDeniedNotification(Context context) {
395397
postNotification(context, managerCompat, builder, OTHER_NOTIFICATION_ID);
396398
}
397399

398-
@SuppressLint("SimpleDateFormat")
399400
public static String getPlanValidity(int session, Context context) {
400401
String validity;
401402
Calendar calendar = Calendar.getInstance();
402-
String month, endDate, suffix, end;
403+
String month, ordinal, end;
404+
int endDate;
403405
if (session == SESSION_MONTHLY) {
404406
int planEnd = PreferenceManager.getDefaultSharedPreferences(context)
405407
.getInt(DATA_RESET_DATE, 1);
@@ -411,8 +413,8 @@ public static String getPlanValidity(int session, Context context) {
411413
if (today >= planEnd) {
412414
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
413415
}
414-
month = new SimpleDateFormat("MMMM").format(calendar.getTime());
415-
endDate = String.valueOf(planEnd);
416+
month = new SimpleDateFormat("MMMM", getCurrentLocale(context)).format(calendar.getTime());
417+
endDate = planEnd;
416418
}
417419
else {
418420
long planEndDateMillis;
@@ -426,30 +428,45 @@ public static String getPlanValidity(int session, Context context) {
426428
planEndDateMillis = ((Number) planEndIntValue).longValue();
427429
}
428430
calendar.setTimeInMillis(planEndDateMillis);
429-
month = new SimpleDateFormat("MMMM").format(calendar.getTime());
430-
endDate = new SimpleDateFormat("d").format(calendar.getTime());
431+
month = new SimpleDateFormat("MMMM", getCurrentLocale(context)).format(calendar.getTime());
432+
endDate = calendar.get(Calendar.DAY_OF_MONTH);
431433
}
432-
suffix = getDateSuffix(endDate);
433-
end = endDate + suffix + " " + month;
434+
ordinal = formatOrdinalNumber(endDate, context);
435+
end = ordinal + " " + month;
434436
validity = end;
435437
return validity;
436438
}
437439

438-
public static String getDateSuffix(String date) {
439-
String suffix;
440-
if (date.endsWith("1")) {
441-
suffix = "st";
442-
}
443-
else if (date.endsWith("2")) {
444-
suffix = "nd";
445-
}
446-
else if (date.endsWith("3")) {
447-
suffix = "rd";
440+
public static String formatOrdinalNumber(int number, Context context) {
441+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
442+
final String format = "{0,ordinal}";
443+
final Locale locale = getCurrentLocale(context);
444+
final MessageFormat formatter = new MessageFormat(format, locale);
445+
446+
return formatter.format(new Object[] {number});
447+
} else {
448+
String numberString = String.valueOf(number);
449+
String suffix;
450+
if (numberString.endsWith("1")) {
451+
suffix = "st";
452+
} else if (numberString.endsWith("2")) {
453+
suffix = "nd";
454+
} else if (numberString.endsWith("3")) {
455+
suffix = "rd";
456+
} else {
457+
suffix = "th";
458+
}
459+
return numberString + suffix;
448460
}
449-
else {
450-
suffix = "th";
461+
}
462+
463+
public static Locale getCurrentLocale(Context context) {
464+
final Configuration config = context.getResources().getConfiguration();
465+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
466+
return config.getLocales().get(0);
467+
} else {
468+
return config.locale;
451469
}
452-
return suffix;
453470
}
454471

455472
private static boolean isLiveNetworkServiceRunning(Context context) {
@@ -507,4 +524,18 @@ public static void postNotification(Context context, NotificationManagerCompat n
507524
}
508525
}
509526
}
527+
528+
public static String parseNumber(String number) {
529+
if (number.matches("[0-9.,]+")) {
530+
return number.replace(",", ".");
531+
}
532+
String output = "0.0";
533+
NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
534+
try {
535+
output = numberFormat.parse(number).toString();
536+
}
537+
catch (Exception ignored) {}
538+
539+
return output;
540+
}
510541
}

app/src/main/java/com/drnoob/datamonitor/core/Values.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class Values {
4848
public static final int SESSION_ALL_TIME = 0x003C;
4949
public static final int SESSION_MONTHLY = 0x00A9;
5050
public static final int SESSION_CUSTOM = 0x00AC;
51+
public static final int SESSION_CUSTOM_FILTER = 0x00AF;
5152

5253
public static final int TYPE_MOBILE_DATA = 0x0046;
5354
public static final int TYPE_WIFI = 0x0050;
@@ -77,6 +78,7 @@ public class Values {
7778
public static final int DIAGNOSTICS_HISTORY_FRAGMENT = 0x010E;
7879
public static final int DATA_PLAN_FRAGMENT = 0x0118;
7980
public static final int APP_CONTRIBUTORS_FRAGMENT = 0x0122;
81+
public static final int ADD_CUSTOM_SESSION_FRAGMENT = 0x0136;
8082

8183
public static final int BOTTOM_NAVBAR_ITEM_HOME = 0;
8284
public static final int BOTTOM_NAVBAR_ITEM_SETUP = 1;
@@ -91,6 +93,7 @@ public class Values {
9193

9294
public static final String SETUP_COMPLETED = "is_setup_complete";
9395
public static final String DATA_LIMIT = "data_limit";
96+
public static final String DATA_QUOTA = "data_quota";
9497
public static final String DATA_TYPE = "data_type";
9598
public static final String LIMIT = "limit";
9699
public static final String DATA_RESET = "data_reset";
@@ -109,6 +112,7 @@ public class Values {
109112
public static final String DATA_RESET_CUSTOM_DATE_RESTART = "custom_reset_date_restart";
110113
public static final String DATA_WARNING_TRIGGER_LEVEL = "data_warning_trigger_level";
111114
public static final String DATA_USAGE_WARNING_SHOWN = "data_usage_warning_shown";
115+
public static final String DATA_QUOTA_WARNING_SHOWN = "data_quota_warning_shown";
112116
public static final String DATA_USAGE_ALERT = "data_usage_alert";
113117
public static final String WIDGET_REFRESH_INTERVAL_SUMMARY = "widget_refresh_interval_summary";
114118
public static final String WIDGET_REFRESH_INTERVAL = "widget_refresh_interval";
@@ -185,4 +189,8 @@ public class Values {
185189
public static final String WALL_OF_THANKS_FEATURED_DONORS = "wall_of_thanks_featured_donors";
186190
public static final String WALL_OF_THANKS_ALL_DONORS = "wall_of_thanks_all_donors";
187191

192+
193+
public static final String DATA_QUOTA_SCHEDULED_RESET = "quota_scheduled_reset";
194+
public static final String DATA_QUOTA_PERFORMED_RESET = "quota_performed_reset";
195+
188196
}

app/src/main/java/com/drnoob/datamonitor/ui/activities/ContainerActivity.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import static com.drnoob.datamonitor.Common.setLanguage;
2323
import static com.drnoob.datamonitor.core.Values.ABOUT_FRAGMENT;
24+
import static com.drnoob.datamonitor.core.Values.ADD_CUSTOM_SESSION_FRAGMENT;
2425
import static com.drnoob.datamonitor.core.Values.APP_CONTRIBUTORS_FRAGMENT;
2526
import static com.drnoob.datamonitor.core.Values.APP_COUNTRY_CODE;
2627
import static com.drnoob.datamonitor.core.Values.APP_DATA_LIMIT_FRAGMENT;
@@ -66,6 +67,7 @@
6667
import com.drnoob.datamonitor.ui.fragments.AppDataLimitFragment;
6768
import com.drnoob.datamonitor.ui.fragments.AppDataUsageFragment;
6869
import com.drnoob.datamonitor.ui.fragments.ContributorsFragment;
70+
import com.drnoob.datamonitor.ui.fragments.CustomSessionFragment;
6971
import com.drnoob.datamonitor.ui.fragments.DataPlanFragment;
7072
import com.drnoob.datamonitor.ui.fragments.DiagnosticsHistoryFragment;
7173
import com.drnoob.datamonitor.ui.fragments.DiagnosticsSettingsFragment;
@@ -237,6 +239,12 @@ navigation bar icons being a light color (white). This limits visibility in ligh
237239
fragment = new AppContributorsFragment();
238240
title = getString(R.string.app_contributors);
239241
break;
242+
243+
case ADD_CUSTOM_SESSION_FRAGMENT:
244+
fragment = new CustomSessionFragment();
245+
title = getString(R.string.add_custom_session);
246+
getSupportActionBar().hide();
247+
break;
240248
}
241249

242250
getSupportFragmentManager().beginTransaction().replace(R.id.container_host_fragment, fragment).commit();

app/src/main/java/com/drnoob/datamonitor/ui/activities/MainActivity.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import static com.drnoob.datamonitor.Common.isUsageAccessGranted;
2525
import static com.drnoob.datamonitor.Common.refreshService;
2626
import static com.drnoob.datamonitor.Common.setLanguage;
27-
import static com.drnoob.datamonitor.Common.showAlarmPermissionDeniedDialog;
2827
import static com.drnoob.datamonitor.core.Values.ALARM_PERMISSION_DENIED;
2928
import static com.drnoob.datamonitor.core.Values.APP_COUNTRY_CODE;
3029
import static com.drnoob.datamonitor.core.Values.APP_DATA_USAGE_WARNING_CHANNEL_ID;
@@ -66,8 +65,6 @@
6665
import static com.drnoob.datamonitor.utils.NetworkStatsHelper.getTetheringDataUsage;
6766

6867
import android.Manifest;
69-
import android.animation.Animator;
70-
import android.animation.AnimatorListenerAdapter;
7168
import android.app.Activity;
7269
import android.app.AlarmManager;
7370
import android.app.NotificationChannel;
@@ -94,14 +91,11 @@
9491
import android.view.MenuItem;
9592
import android.view.View;
9693
import android.widget.RemoteViews;
97-
import android.widget.Toast;
9894

9995
import androidx.annotation.NonNull;
10096
import androidx.annotation.RequiresApi;
10197
import androidx.appcompat.app.AppCompatActivity;
10298
import androidx.appcompat.app.AppCompatDelegate;
103-
import androidx.constraintlayout.widget.ConstraintLayout;
104-
import androidx.core.app.NotificationCompat;
10599
import androidx.navigation.NavController;
106100
import androidx.navigation.NavDestination;
107101
import androidx.navigation.fragment.NavHostFragment;

0 commit comments

Comments
 (0)