From d607e4c0cad2dd9b38da869f80d2e60e48164876 Mon Sep 17 00:00:00 2001 From: Mihai-Cristian Condrea Date: Thu, 18 Sep 2025 19:15:04 +0300 Subject: [PATCH] Remove app usage notification components --- .../AppUpdateNotificationsManager.java | 83 ------------------- .../AppUsageNotificationsManager.java | 54 ------------ .../AppUsageNotificationReceiver.java | 31 ------- .../workers/AppUsageNotificationWorker.java | 81 ------------------ .../java/ui/screens/main/MainActivity.java | 13 --- .../AppUsageNotificationReceiverTest.java | 42 ---------- 6 files changed, 304 deletions(-) delete mode 100644 app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUpdateNotificationsManager.java delete mode 100644 app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManager.java delete mode 100644 app/src/main/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiver.java delete mode 100644 app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorker.java delete mode 100644 app/src/test/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiverTest.java diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUpdateNotificationsManager.java b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUpdateNotificationsManager.java deleted file mode 100644 index 0d366eb4..00000000 --- a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUpdateNotificationsManager.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.d4rk.androidtutorials.java.notifications.managers; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; - -import androidx.annotation.RequiresApi; -import androidx.core.app.NotificationCompat; - -import com.d4rk.androidtutorials.java.R; -import com.google.android.gms.tasks.Task; -import com.google.android.play.core.appupdate.AppUpdateInfo; -import com.google.android.play.core.appupdate.AppUpdateManager; -import com.google.android.play.core.appupdate.AppUpdateManagerFactory; -import com.google.android.play.core.install.model.AppUpdateType; -import com.google.android.play.core.install.model.UpdateAvailability; - -/** - * Utility class for managing app update notifications. - * - *

This class provides functionality to check for available app updates and send update - * notifications with a deep link to the Play Store for user interaction. - */ -public class AppUpdateNotificationsManager { - - private final Context context; - private final String updateChannelId = "update_channel"; - private final int updateNotificationId = 0; - - public AppUpdateNotificationsManager(Context context) { - this.context = context; - } - - /** - * Checks for available app updates and sends a notification if a flexible update is available. - * - *

This method utilizes the AppUpdateManager to retrieve app update information. - * If a flexible update is available, a notification is displayed to the user, prompting them - * to update the app via the Play Store. The notification includes a deep link to the app's - * Play Store listing. - */ - @RequiresApi(api = Build.VERSION_CODES.O) - public void checkAndSendUpdateNotification() { - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context); - Task appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); - appUpdateInfoTask.addOnSuccessListener( - appUpdateInfo -> { - if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && - appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { - NotificationChannel updateChannel = new NotificationChannel( - updateChannelId, - context.getString(R.string.update_notifications), - NotificationManager.IMPORTANCE_HIGH - ); - notificationManager.createNotificationChannel(updateChannel); - NotificationCompat.Builder updateBuilder = new NotificationCompat.Builder(context, updateChannelId) - .setSmallIcon(R.drawable.ic_notification_update) - .setContentTitle(context.getString(R.string.notification_update_title)) - .setContentText(context.getString(R.string.summary_notification_update)) - .setAutoCancel(true) - .setContentIntent( - PendingIntent.getActivity( - context, - 0, - new Intent( - Intent.ACTION_VIEW, - Uri.parse("market://details?id=" + context.getPackageName()) - ), - PendingIntent.FLAG_IMMUTABLE - ) - ); - notificationManager.notify(updateNotificationId, updateBuilder.build()); - } - } - ); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManager.java b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManager.java deleted file mode 100644 index 7367e05d..00000000 --- a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManager.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.d4rk.androidtutorials.java.notifications.managers; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -import com.d4rk.androidtutorials.java.notifications.receivers.AppUsageNotificationReceiver; - -import java.util.concurrent.TimeUnit; - -/** - * Utility class for managing app usage notifications. - *

- * This class provides functionality to schedule periodic checks for app usage notifications - * using {@link android.app.AlarmManager}. - */ -public class AppUsageNotificationsManager { - - private final AlarmManager alarmManager; - private final PendingIntent notificationIntent; - - /** - * Constructor for AppUsageNotificationsManager. - * - * @param context The application context used for scheduling app usage checks. - */ - public AppUsageNotificationsManager(Context context) { - this.alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - this.notificationIntent = PendingIntent.getBroadcast( - context, - 0, - new Intent(context, AppUsageNotificationReceiver.class), - PendingIntent.FLAG_IMMUTABLE - ); - } - - /** - * Schedules a periodic check for app usage notifications. - *

- * This method schedules a repeating task using {@link android.app.AlarmManager} to perform app - * usage checks every 3 days. It sets a repeating alarm that triggers an instance of the - * {@link AppUsageNotificationReceiver} to handle the app usage check. - */ - public void scheduleAppUsageCheck() { - long triggerTime = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(3); - alarmManager.setRepeating( - AlarmManager.RTC_WAKEUP, - triggerTime, - TimeUnit.DAYS.toMillis(3), - notificationIntent - ); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiver.java b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiver.java deleted file mode 100644 index dd062760..00000000 --- a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiver.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.d4rk.androidtutorials.java.notifications.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkManager; - -import com.d4rk.androidtutorials.java.notifications.workers.AppUsageNotificationWorker; - -/** - * A {@link BroadcastReceiver} that enqueues a {@link AppUsageNotificationWorker} - * when it receives a broadcast. - */ -public class AppUsageNotificationReceiver extends BroadcastReceiver { - - /** - * Receives the broadcast and enqueues the {@link AppUsageNotificationWorker}. - * - * @param context The context of the application. - * @param intent The intent that triggered the receiver. - */ - @Override - public void onReceive(Context context, Intent intent) { - OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder( - AppUsageNotificationWorker.class) - .build(); - WorkManager.getInstance(context).enqueue(workRequest); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorker.java b/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorker.java deleted file mode 100644 index bf840797..00000000 --- a/app/src/main/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorker.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.d4rk.androidtutorials.java.notifications.workers; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; - -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; -import androidx.core.app.NotificationCompat; -import androidx.preference.PreferenceManager; -import androidx.work.Worker; -import androidx.work.WorkerParameters; - -import com.d4rk.androidtutorials.java.R; - -/** - * A {@link Worker} that checks the last time the app was used and displays a notification - * if it exceeds a certain threshold. - */ -public class AppUsageNotificationWorker extends Worker { - - private final SharedPreferences sharedPreferences; - - /** - * Constructor for {@link AppUsageNotificationWorker}. - * - * @param context The context of the application. - * @param workerParams The parameters of the worker. - */ - public AppUsageNotificationWorker(@NonNull Context context, - @NonNull WorkerParameters workerParams) { - super(context, workerParams); - this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - } - - /** - * Performs the work of the worker, which involves checking the last used timestamp - * and displaying a notification if necessary. - * - * @return The {@link Result} of the work. - */ - @RequiresApi(api = Build.VERSION_CODES.O) - @NonNull - @Override - public Result doWork() { - long currentTimestamp = System.currentTimeMillis(); - long notificationThreshold = 3 * 24 * 60 * 60 * 1000; - long lastUsedTimestamp = sharedPreferences.getLong("lastUsed", 0); - - if (currentTimestamp - lastUsedTimestamp > notificationThreshold) { - NotificationManager notificationManager = - (NotificationManager) getApplicationContext().getSystemService( - Context.NOTIFICATION_SERVICE); - String appUsageChannelId = "app_usage_channel"; - NotificationChannel appUsageChannel = new NotificationChannel( - appUsageChannelId, - getApplicationContext().getString(R.string.app_usage_notifications), - NotificationManager.IMPORTANCE_HIGH - ); - notificationManager.createNotificationChannel(appUsageChannel); - NotificationCompat.Builder notificationBuilder = - new NotificationCompat.Builder(getApplicationContext(), - appUsageChannelId) - .setSmallIcon(R.drawable.ic_notification_important) - .setContentTitle(getApplicationContext().getString( - R.string.notification_last_time_used_title)) - .setContentText(getApplicationContext().getString( - R.string.summary_notification_last_time_used)) - .setAutoCancel(true); - int appUsageNotificationId = 0; - notificationManager.notify(appUsageNotificationId, - notificationBuilder.build()); - } - - sharedPreferences.edit().putLong("lastUsed", currentTimestamp).apply(); - - return Result.success(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java index 147b1dfe..a1cce574 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java @@ -35,8 +35,6 @@ import com.d4rk.androidtutorials.java.R; import com.d4rk.androidtutorials.java.ads.AdUtils; import com.d4rk.androidtutorials.java.databinding.ActivityMainBinding; -import com.d4rk.androidtutorials.java.notifications.managers.AppUpdateNotificationsManager; -import com.d4rk.androidtutorials.java.notifications.managers.AppUsageNotificationsManager; import com.d4rk.androidtutorials.java.startup.StartupInitializer; import com.d4rk.androidtutorials.java.ui.components.navigation.BottomSheetMenuFragment; import com.d4rk.androidtutorials.java.ui.screens.startup.StartupActivity; @@ -87,7 +85,6 @@ public void onResume(@NonNull LifecycleOwner owner) { private NavController navController; private int currentNavIndex; private AppUpdateManager appUpdateManager; - private AppUpdateNotificationsManager appUpdateNotificationsManager; private InstallStateUpdatedListener installStateUpdatedListener; private long backPressedTime; @@ -149,7 +146,6 @@ protected void onCreate(Bundle savedInstanceState) { } this.appUpdateManager = mainViewModel.getAppUpdateManager(); - setupUpdateNotifications(); registerInstallStateListener(); getLifecycle().addObserver(lifecycleObserver); @@ -319,11 +315,6 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) { @Override protected void onResume() { super.onResume(); - AppUsageNotificationsManager appUsageNotificationsManager = new AppUsageNotificationsManager(this); - appUsageNotificationsManager.scheduleAppUsageCheck(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - appUpdateNotificationsManager.checkAndSendUpdateNotification(); - } checkForFlexibleOrImmediateUpdate(); } @@ -380,10 +371,6 @@ private void startImmediateUpdate(AppUpdateInfo appUpdateInfo) { } } - private void setupUpdateNotifications() { - appUpdateNotificationsManager = new AppUpdateNotificationsManager(this); - } - private void registerInstallStateListener() { installStateUpdatedListener = state -> { if (state.installStatus() == InstallStatus.DOWNLOADED) { diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiverTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiverTest.java deleted file mode 100644 index 69775c11..00000000 --- a/app/src/test/java/com/d4rk/androidtutorials/java/notifications/receivers/AppUsageNotificationReceiverTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.d4rk.androidtutorials.java.notifications.receivers; - -import android.content.Context; -import android.content.Intent; - -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkManager; - -import com.d4rk.androidtutorials.java.notifications.workers.AppUsageNotificationWorker; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.MockedStatic; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.verify; - -public class AppUsageNotificationReceiverTest { - - @Test - public void onReceive_enqueuesOneTimeWorkRequestForAppUsageNotificationWorker() { - Context context = mock(Context.class); - Intent intent = mock(Intent.class); - WorkManager workManager = mock(WorkManager.class); - - try (MockedStatic mockedWorkManager = mockStatic(WorkManager.class)) { - mockedWorkManager.when(() -> WorkManager.getInstance(context)).thenReturn(workManager); - - AppUsageNotificationReceiver receiver = new AppUsageNotificationReceiver(); - receiver.onReceive(context, intent); - - ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(OneTimeWorkRequest.class); - verify(workManager).enqueue(requestCaptor.capture()); - - OneTimeWorkRequest request = requestCaptor.getValue(); - assertEquals(AppUsageNotificationWorker.class.getName(), - request.getWorkSpec().workerClassName); - } - } -}