From b5b60f9fb1428910c9108dff8a7eb84d0a0276ec Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Mon, 3 Jul 2023 18:23:13 +0200 Subject: [PATCH 1/9] implement base for ScreenOnReceiver --- app/src/main/AndroidManifest.xml | 8 ++++ .../e/drive/receivers/ScreenOnReceiver.kt | 44 +++++++++++++++++ .../e/drive/receivers/ScreenOnReceiverTest.kt | 47 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt create mode 100644 app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ec966a21..6f4937e1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -95,6 +95,14 @@ android:name=".services.ObserverService" android:enabled="true" /> + + + + + = MIN_DELAY_BETWEEN_USERINFO_CHECK + } +} \ No newline at end of file diff --git a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt new file mode 100644 index 00000000..bff6282b --- /dev/null +++ b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt @@ -0,0 +1,47 @@ +package foundation.e.drive.receivers + +import org.junit.Assert +import org.junit.Test + +internal class ScreenOnReceiverTest { + + val currentTimeStamp = System.currentTimeMillis() + companion object { + val instanceUnderTest = ScreenOnReceiver() + } + + @Test + fun `isEnoughElapsedTimeForUserInfoCheck with 0 as previous check time`() { + val previousTimestamp = 0L + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + } + + @Test + fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp earlier than min delay`() { + val previousTimestamp = currentTimeStamp-1 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + Assert.assertFalse("isEnoughTimeElapsed should return false but returned: $result", result) + } + + @Test + fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp equal to min delay`() { + val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_DELAY_BETWEEN_USERINFO_CHECK + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + } + + @Test + fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp older than min delay`() { + val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_DELAY_BETWEEN_USERINFO_CHECK - 1 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + } + + @Test + fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp bigger than current timestamp`() { + val previousTimestamp = currentTimeStamp + 10000 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + Assert.assertFalse("isEnoughTimeElapsed should return true but returned: $result", result) + } +} \ No newline at end of file -- GitLab From b1ffd02d455d497ce291f2dc844c7dc6799dec50 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 11:40:18 +0200 Subject: [PATCH 2/9] refactor WorkRequestFactory & CommonUtils remove useless code, fix warning, add method to trigger a oneTime work request for fetching userInfo --- .../e/drive/utils/AppConstants.java | 3 - .../foundation/e/drive/utils/CommonUtils.java | 37 ++++------- .../e/drive/work/FirstStartWorker.java | 3 +- .../e/drive/work/WorkRequestFactory.java | 64 ++++--------------- 4 files changed, 25 insertions(+), 82 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/utils/AppConstants.java b/app/src/main/java/foundation/e/drive/utils/AppConstants.java index 1c9da75a..6946bd53 100644 --- a/app/src/main/java/foundation/e/drive/utils/AppConstants.java +++ b/app/src/main/java/foundation/e/drive/utils/AppConstants.java @@ -9,10 +9,8 @@ package foundation.e.drive.utils; -import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR; import android.os.Build; -import android.os.Environment; import java.text.SimpleDateFormat; import java.util.Locale; @@ -43,7 +41,6 @@ public abstract class AppConstants { public static final String ACCOUNT_DATA_EMAIL = "email"; public static final String ACCOUNT_USER_ID_KEY = "USERID"; public static final String[] MEDIA_SYNCABLE_CATEGORIES = new String[]{"Images", "Movies", "Music", "Ringtones", "Documents", "Podcasts"}; - public static final String[] SETTINGS_SYNCABLE_CATEGORIES = new String[]{"Rom settings"}; public static final String notificationChannelID = "foundation.e.drive"; public static final String WORK_GENERIC_TAG = "eDrive"; diff --git a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java index 1ffb3a1e..16556cb2 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -40,7 +40,6 @@ import java.util.List; import foundation.e.drive.R; import foundation.e.drive.models.SyncedFolder; -import foundation.e.drive.work.AccountUserInfoWorker; import foundation.e.drive.work.WorkRequestFactory; import timber.log.Timber; @@ -50,9 +49,7 @@ import static foundation.e.drive.utils.AppConstants.SETTINGSYNC_PROVIDER_AUTHORI import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.OneTimeWorkRequest; -import androidx.work.PeriodicWorkRequest; import androidx.work.WorkManager; @@ -123,7 +120,7 @@ public abstract class CommonUtils { * * @param account Account used for synchronisation * @param syncedFileStateIsMedia true if the concerned syncedFileState is a media's type element, false if it is a settings's type element - * @return + * @return true if sync is allowed in given condition */ public static boolean isThisSyncAllowed(@NonNull Account account, boolean syncedFileStateIsMedia) { return (syncedFileStateIsMedia && isMediaSyncEnabled(account)) @@ -153,14 +150,14 @@ public abstract class CommonUtils { /** * Read accountManager settings * - * @param account + * @param account Concerned account * @return true if usage of metered connection is allowed */ public static boolean isMeteredNetworkAllowed(@NonNull Account account) { return ContentResolver.getSyncAutomatically(account, METERED_NETWORK_ALLOWED_AUTHORITY); } - /** methods relative to file **/ + /* methods relative to file */ /** * Return name of a file from its access path @@ -188,14 +185,11 @@ public abstract class CommonUtils { final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); final NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork()); - if (capabilities != null + return capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) && (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - || meteredNetworkAllowed)) { - return true; - } - return false; + || meteredNetworkAllowed); } @@ -229,13 +223,8 @@ public abstract class CommonUtils { MediaScannerConnection.scanFile(context, filePathArray, mimeType, - new MediaScannerConnection.OnScanCompletedListener() { - @Override - public void onScanCompleted(String path, Uri uri) { - Timber.tag("MediaScannerConnection") - .v("file %s was scanned with success: %s ", path, uri); - } - }); + (path, uri) -> Timber.tag("MediaScannerConnection") + .v("file %s was scanned with success: %s ", path, uri)); } /** @@ -258,7 +247,7 @@ public abstract class CommonUtils { /** * Formatter class is not used since bytes passed by server are in SI unit aka 1kb = 1024byte - * https://stackoverflow.com/questions/3758606/how-can-i-convert-byte-size-into-a-human-readable-format-in-java/3758880#3758880 + * ... * * @param bytes file/data size in bytes * @return String in human readable format @@ -342,11 +331,11 @@ public abstract class CommonUtils { /** * Job for Widget & notification about quota * - * @param workManager + * @param workManager WorkManager */ - public static void registerPeriodicUserInfoChecking(@NonNull WorkManager workManager) { - final PeriodicWorkRequest workRequest = WorkRequestFactory.getPeriodicWorkRequest(WorkRequestFactory.WorkType.PERIODIC_USER_INFO); - workManager.enqueueUniquePeriodicWork(AccountUserInfoWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, workRequest); + public static void TriggerUserInfoFetching(@NonNull WorkManager workManager) { + final OneTimeWorkRequest getUserInfoRequest = WorkRequestFactory.getOneTimeWorkRequest(WorkRequestFactory.WorkType.ONE_TIME_USER_INFO, null); + workManager.enqueue(getUserInfoRequest); } /** @@ -368,4 +357,4 @@ public abstract class CommonUtils { } return value == null ? "" : value; } -} +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java b/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java index 7cdbf4f1..80f0b3d4 100644 --- a/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java +++ b/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java @@ -10,7 +10,6 @@ package foundation.e.drive.work; import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; import static foundation.e.drive.work.WorkRequestFactory.WorkType.ONE_TIME_APP_LIST; -import static foundation.e.drive.work.WorkRequestFactory.WorkType.PERIODIC_SCAN; import android.content.Context; import android.content.Intent; @@ -73,6 +72,6 @@ public class FirstStartWorker extends Worker { workManager.enqueueUniquePeriodicWork(PeriodicWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, - WorkRequestFactory.getPeriodicWorkRequest(PERIODIC_SCAN)); + WorkRequestFactory.createPeriodicScanWorkRequest()); } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java index 6331f302..6208226e 100644 --- a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java +++ b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java @@ -36,8 +36,6 @@ import foundation.e.drive.utils.AppConstants; public class WorkRequestFactory { public enum WorkType { - PERIODIC_USER_INFO, - PERIODIC_SCAN, ONE_TIME_FULL_SCAN, ONE_TIME_APP_LIST, ONE_TIME_USER_INFO, @@ -46,58 +44,21 @@ public class WorkRequestFactory { } /** - * Build an instance of PeriodicWorkRequest depending of the work type specified - * @param type WorkType. Should be FULL_SCAN or PERIODIC_USER_INFO or PERIODIC_APP_LIST - * If not, it will throw an InvalidParameterException - * @return Periodic WorkRequest - */ - @NonNull - public static PeriodicWorkRequest getPeriodicWorkRequest(@NonNull WorkType type) { - switch (type) { - case PERIODIC_SCAN: - return createPeriodicScanWorkRequest(); - case PERIODIC_USER_INFO: - return createPeriodicGetUserInfoWorkRequest(); - default: - throw new InvalidParameterException("Unsupported Work Type: " + type); - } - } - - /** - * Create a PeridocWorkRequest instance for + * Create a PeriodicWorkRequest instance for * a Full scan with constraints on network (should * be unmetered) and battery (shouldn't be low) * @return instance of PeriodicWorkRequest */ - private static PeriodicWorkRequest createPeriodicScanWorkRequest() { + public static PeriodicWorkRequest createPeriodicScanWorkRequest() { final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints(); - final PeriodicWorkRequest workRequest = - new PeriodicWorkRequest.Builder(PeriodicWorker.class, - 26, TimeUnit.MINUTES, 5, TimeUnit.MINUTES) - .setConstraints(constraints) - .addTag(AppConstants.WORK_GENERIC_TAG) - .build(); - return workRequest; - } - - /** - * Create a periodic work request to get userInfo - * @return instance of PeriodicWorkRequest - */ - private static PeriodicWorkRequest createPeriodicGetUserInfoWorkRequest() { - final Constraints constraints = new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) + return new PeriodicWorkRequest.Builder(PeriodicWorker.class, + 26, TimeUnit.MINUTES, 5, TimeUnit.MINUTES) + .setConstraints(constraints) + .addTag(AppConstants.WORK_GENERIC_TAG) .build(); - - final PeriodicWorkRequest workRequest = - new PeriodicWorkRequest.Builder(AccountUserInfoWorker.class, - 30, TimeUnit.MINUTES) - .addTag(AppConstants.WORK_GENERIC_TAG) - .setConstraints(constraints) - .build(); - return workRequest; } + /** * Build an instance of OneTimeWorkRequest depending of the work type specified. * @param type Should be ONE_TIME_USER_INFO, or FIRST_START, or CREATE_REMOTE_DIR @@ -163,7 +124,7 @@ public class WorkRequestFactory { final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(AccountUserInfoWorker.class); - return builder.setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES) + return builder.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.MINUTES) .addTag(AppConstants.WORK_GENERIC_TAG) .addTag(AppConstants.WORK_INITIALIZATION_TAG) .setConstraints(constraints) @@ -179,7 +140,7 @@ public class WorkRequestFactory { private static OneTimeWorkRequest createOneTimeCreateRemoteFolderWorkRequest(@NonNull SyncedFolder syncedFolder) { final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints(); - final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder( + return new OneTimeWorkRequest.Builder( CreateRemoteFolderWorker.class) .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES) .setInputData(createDataFromSyncedFolder(syncedFolder)) @@ -187,7 +148,6 @@ public class WorkRequestFactory { .addTag(AppConstants.WORK_INITIALIZATION_TAG) .setConstraints(constraints) .build(); - return workRequest; } /** @@ -196,12 +156,11 @@ public class WorkRequestFactory { * @return Instance of OneTimeWorkRequest */ private static OneTimeWorkRequest createOneTimeFirstStartWorkRequest() { - final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(FirstStartWorker.class) + return new OneTimeWorkRequest.Builder(FirstStartWorker.class) .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES) .addTag(AppConstants.WORK_GENERIC_TAG) .addTag(AppConstants.WORK_INITIALIZATION_TAG) .build(); - return workRequest; } /** @@ -210,11 +169,10 @@ public class WorkRequestFactory { * @return instance of Constraints */ private static Constraints createUnmeteredNetworkAndHighBatteryConstraints() { - final Constraints constraint = new Constraints.Builder() + return new Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresBatteryNotLow(true) .build(); - return constraint; } /** -- GitLab From c5c6e51764b94029a51dc8d08db704990cc9877d Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 11:41:49 +0200 Subject: [PATCH 3/9] remove registering worker for periodic user info fetching from InitializerService and refactor UnitTest for ScreenOnReceivers --- .../java/foundation/e/drive/services/InitializerService.java | 1 - .../java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/services/InitializerService.java b/app/src/main/java/foundation/e/drive/services/InitializerService.java index 74927399..1824c9ce 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -109,7 +109,6 @@ public class InitializerService extends Service { */ private void start() { Timber.d("start()"); - CommonUtils.registerPeriodicUserInfoChecking(WorkManager.getInstance(this)); final List syncedFolders = RootSyncedFolderProvider.INSTANCE.getSyncedFolderRoots(getApplicationContext()); CommonUtils.registerInitializationWorkers(syncedFolders, WorkManager.getInstance(getApplicationContext()) ); diff --git a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt index bff6282b..27044644 100644 --- a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt +++ b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt @@ -26,14 +26,14 @@ internal class ScreenOnReceiverTest { @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp equal to min delay`() { - val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_DELAY_BETWEEN_USERINFO_CHECK + val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) } @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp older than min delay`() { - val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_DELAY_BETWEEN_USERINFO_CHECK - 1 + val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - 1 val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) } -- GitLab From 18e4cdfd9ad522dfc6391d14f7cb0fe13f53f9b2 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 11:42:52 +0200 Subject: [PATCH 4/9] clean ScreenOnReceivers code --- .../e/drive/receivers/ScreenOnReceiver.kt | 21 +++++++++++-------- .../e/drive/utils/AppConstants.java | 1 + ...foWorker.java => FetchUserInfoWorker.java} | 0 3 files changed, 13 insertions(+), 9 deletions(-) rename app/src/main/java/foundation/e/drive/work/{AccountUserInfoWorker.java => FetchUserInfoWorker.java} (100%) diff --git a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt index dbee3755..babb3410 100644 --- a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt +++ b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt @@ -12,21 +12,24 @@ import android.content.Context import android.content.Intent import android.content.Intent.ACTION_SCREEN_ON import androidx.annotation.VisibleForTesting +import androidx.work.WorkManager import foundation.e.drive.utils.AppConstants +import foundation.e.drive.utils.AppConstants.USER_INFO_LAST_FETCH_KEY +import foundation.e.drive.utils.CommonUtils class ScreenOnReceiver() : BroadcastReceiver() { companion object { - const val USER_INFO_LAST_CHECK_KEY = "userInfoLastCheck" - const val MIN_DELAY_BETWEEN_USERINFO_CHECK: Long = 1800000 + const val MIN_BACKOFF_FOR_FETCHING_USERINFO: Long = 1800000 } override fun onReceive(ctx: Context?, intent: Intent?) { - if (intent?.action.equals(ACTION_SCREEN_ON)) { - val preferences = ctx?.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE) - val previousCheckTimestamp = preferences?.getLong(USER_INFO_LAST_CHECK_KEY, 0L) ?: 0L - if (isEnoughElapsedTimeForUserInfoCheck(previousCheckTimestamp, System.currentTimeMillis())) { - //todo trigger userInfo check - //todo may be not here, but don't forget to register timestamp value after call + if (intent?.action.equals(ACTION_SCREEN_ON) && ctx != null) { + val preferences = ctx.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE) + val previousTimestamp = preferences?.getLong(USER_INFO_LAST_FETCH_KEY, 0L) ?: 0L + + if (isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, System.currentTimeMillis())) { + val workManager = WorkManager.getInstance(ctx) + CommonUtils.TriggerUserInfoFetching(workManager) } } } @@ -39,6 +42,6 @@ class ScreenOnReceiver() : BroadcastReceiver() { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun isEnoughElapsedTimeForUserInfoCheck(previousCheckTimestamp: Long, currentTimeStamp: Long): Boolean { val elapsedTime = currentTimeStamp - previousCheckTimestamp - return elapsedTime >= MIN_DELAY_BETWEEN_USERINFO_CHECK + return elapsedTime >= MIN_BACKOFF_FOR_FETCHING_USERINFO } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/utils/AppConstants.java b/app/src/main/java/foundation/e/drive/utils/AppConstants.java index 6946bd53..28214695 100644 --- a/app/src/main/java/foundation/e/drive/utils/AppConstants.java +++ b/app/src/main/java/foundation/e/drive/utils/AppConstants.java @@ -36,6 +36,7 @@ public abstract class AppConstants { public static final String ACCOUNT_DATA_USED_QUOTA_KEY = "used_quota"; public static final String ACCOUNT_DATA_TOTAL_QUOTA_KEY = "total_quota"; public static final String ACCOUNT_DATA_RELATIVE_QUOTA_KEY = "relative_quota"; + public static final String USER_INFO_LAST_FETCH_KEY = "userInfoLastCheck"; public static final String ACCOUNT_DATA_GROUPS = "group"; public static final String ACCOUNT_DATA_ALIAS_KEY = "alias"; public static final String ACCOUNT_DATA_EMAIL = "email"; diff --git a/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java b/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java similarity index 100% rename from app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java rename to app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java -- GitLab From 3ebb2a2da87f5e90a7d6283b8b311887d9a40111 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 12:03:31 +0200 Subject: [PATCH 5/9] rename AccountUserInfoWorker into FetchUserInfoWorker and implement method to store current timestamp when worker succeed --- .../e/drive/work/FetchUserInfoWorker.java | 37 ++++++++++++------- .../e/drive/work/WorkRequestFactory.java | 2 +- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java b/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java index 39b308c1..32028452 100644 --- a/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java +++ b/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java @@ -15,6 +15,7 @@ import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_RELATIVE_QUOTA_ import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_TOTAL_QUOTA_KEY; import static foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_USED_QUOTA_KEY; import static foundation.e.drive.utils.AppConstants.ACCOUNT_USER_ID_KEY; +import static foundation.e.drive.utils.AppConstants.USER_INFO_LAST_FETCH_KEY; import android.accounts.Account; import android.accounts.AccountManager; @@ -51,18 +52,17 @@ import timber.log.Timber; * @author vincent Bourgmayer * @author TheScarastic */ -public class AccountUserInfoWorker extends Worker { - public static final String UNIQUE_WORK_NAME = "AccountUserInfoWorker"; +public class FetchUserInfoWorker extends Worker { private final AccountManager accountManager; private final GetUserInfoRemoteOperation GetUserInfoRemoteOperation = new GetUserInfoRemoteOperation(); - private final Context mContext; + private final Context context; private Account account; - public AccountUserInfoWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + public FetchUserInfoWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); - Timber.tag(AccountUserInfoWorker.class.getSimpleName()); - mContext = context; + Timber.tag(FetchUserInfoWorker.class.getSimpleName()); + this.context = context; accountManager = AccountManager.get(context); } @@ -71,21 +71,22 @@ public class AccountUserInfoWorker extends Worker { public Result doWork() { try { - account = CommonUtils.getAccount(mContext.getString(R.string.eelo_account_type), accountManager); + account = CommonUtils.getAccount(context.getString(R.string.eelo_account_type), accountManager); if (account == null) { return Result.failure(); } - final NextcloudClient client = DavClientProvider.getInstance().getNcClientInstance(account, mContext); + final NextcloudClient client = DavClientProvider.getInstance().getNcClientInstance(account, context); if (client != null) { if (fetchUserInfo(client) && fetchAliases()) { - Glide.with(mContext) + Glide.with(context) .load(client.getBaseUri() + AccountsActivity.NON_OFFICIAL_AVATAR_PATH + client.getUserId() + "/" + 300) .diskCacheStrategy(DiskCacheStrategy.ALL) .preload(); - ViewUtils.updateWidgetView(mContext); + ViewUtils.updateWidgetView(context); + saveLastExecutionTimestamp(context); return Result.success(); } else { return Result.retry(); @@ -109,7 +110,7 @@ public class AccountUserInfoWorker extends Worker { if (userId != null) { client.setUserId(userId); - AccountManager.get(mContext).setUserData(account, ACCOUNT_USER_ID_KEY, userId); + AccountManager.get(context).setUserData(account, ACCOUNT_USER_ID_KEY, userId); Timber.v("UserId %s saved for account", userId); } } @@ -166,7 +167,7 @@ public class AccountUserInfoWorker extends Worker { final String LAST_NOTIFICATION_TIMESTAMP_KEY = "last_notification_timestamp"; final long MILLI_SECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; - SharedPreferences sharedPreferences = context.getSharedPreferences( + final SharedPreferences sharedPreferences = context.getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE ); @@ -205,7 +206,7 @@ public class AccountUserInfoWorker extends Worker { } private boolean fetchAliases() { - final OwnCloudClient ocClient = DavClientProvider.getInstance().getClientInstance(account, mContext); + final OwnCloudClient ocClient = DavClientProvider.getInstance().getClientInstance(account, context); final String userId = accountManager.getUserData(account, ACCOUNT_USER_ID_KEY); if (userId == null || userId.isEmpty()) { @@ -213,6 +214,7 @@ public class AccountUserInfoWorker extends Worker { } final GetAliasOperation getAliasOperation = new GetAliasOperation(userId); + @SuppressWarnings("deprecation") final RemoteOperationResult> ocsResult = getAliasOperation.execute(ocClient); String aliases = ""; @@ -226,4 +228,11 @@ public class AccountUserInfoWorker extends Worker { Timber.d("fetchAliases(): success"); return true; } -} + + private void saveLastExecutionTimestamp(final Context context) { + context.getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE) + .edit() + .putLong(USER_INFO_LAST_FETCH_KEY, System.currentTimeMillis()) + .apply(); + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java index 6208226e..b46a71ad 100644 --- a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java +++ b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java @@ -122,7 +122,7 @@ public class WorkRequestFactory { private static OneTimeWorkRequest createOneTimeGetUserInfoWorkRequest() { final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints(); - final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(AccountUserInfoWorker.class); + final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(FetchUserInfoWorker.class); return builder.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.MINUTES) .addTag(AppConstants.WORK_GENERIC_TAG) -- GitLab From ff7192a27c1b963169ff9f1ea555a00c49aedf2c Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 14:41:33 +0200 Subject: [PATCH 6/9] fix failing build on gitlab --- .../main/java/foundation/e/drive/work/WorkRequestFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java index b46a71ad..abee51af 100644 --- a/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java +++ b/app/src/main/java/foundation/e/drive/work/WorkRequestFactory.java @@ -49,6 +49,7 @@ public class WorkRequestFactory { * be unmetered) and battery (shouldn't be low) * @return instance of PeriodicWorkRequest */ + @NonNull public static PeriodicWorkRequest createPeriodicScanWorkRequest() { final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints(); -- GitLab From 63633761c3ec4596ddb284ec345d3db1b5c8710e Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 15:58:49 +0200 Subject: [PATCH 7/9] re-add user info fetching after account registration --- .../java/foundation/e/drive/work/FirstStartWorker.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java b/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java index 80f0b3d4..6c8daf47 100644 --- a/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java +++ b/app/src/main/java/foundation/e/drive/work/FirstStartWorker.java @@ -10,6 +10,7 @@ package foundation.e.drive.work; import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; import static foundation.e.drive.work.WorkRequestFactory.WorkType.ONE_TIME_APP_LIST; +import static foundation.e.drive.work.WorkRequestFactory.WorkType.ONE_TIME_USER_INFO; import android.content.Context; import android.content.Intent; @@ -51,7 +52,7 @@ public class FirstStartWorker extends Worker { .putInt(INITIALFOLDERS_NUMBER, 9) .apply(); - registerPeriodicWork(appContext); + registerWorker(appContext); getApplicationContext().startService(new Intent(getApplicationContext(), foundation.e.drive.services.SynchronizationService.class)); getApplicationContext().startService(new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class)); @@ -67,9 +68,11 @@ public class FirstStartWorker extends Worker { workManager.enqueue(WorkRequestFactory.getOneTimeWorkRequest(ONE_TIME_APP_LIST, null)); } - private void registerPeriodicWork(@NonNull final Context context) { + private void registerWorker(@NonNull final Context context) { final WorkManager workManager = WorkManager.getInstance(context); + workManager.enqueue(WorkRequestFactory.getOneTimeWorkRequest(ONE_TIME_USER_INFO, null)); + workManager.enqueueUniquePeriodicWork(PeriodicWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, WorkRequestFactory.createPeriodicScanWorkRequest()); -- GitLab From ae467effa3b59a16409d49a72c61a23cd37e84ce Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 16:12:02 +0200 Subject: [PATCH 8/9] rename variable about timestamp --- .../e/drive/receivers/ScreenOnReceiver.kt | 12 +++++----- .../e/drive/work/FetchUserInfoWorker.java | 10 ++++----- .../e/drive/receivers/ScreenOnReceiverTest.kt | 22 +++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt index babb3410..94a1290c 100644 --- a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt +++ b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt @@ -25,9 +25,9 @@ class ScreenOnReceiver() : BroadcastReceiver() { override fun onReceive(ctx: Context?, intent: Intent?) { if (intent?.action.equals(ACTION_SCREEN_ON) && ctx != null) { val preferences = ctx.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE) - val previousTimestamp = preferences?.getLong(USER_INFO_LAST_FETCH_KEY, 0L) ?: 0L + val previousTimeInMs = preferences?.getLong(USER_INFO_LAST_FETCH_KEY, 0L) ?: 0L - if (isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, System.currentTimeMillis())) { + if (isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, System.currentTimeMillis())) { val workManager = WorkManager.getInstance(ctx) CommonUtils.TriggerUserInfoFetching(workManager) } @@ -36,12 +36,12 @@ class ScreenOnReceiver() : BroadcastReceiver() { /** * Check if enough time has elapsed - * @param previousCheckTimestamp: previous userInfo check timestamp - * @param currentTimeStamp: current time stamp + * @param previousCheckTimeInMs: previous userInfo check timestamp + * @param currentTimeInMs: current time stamp */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun isEnoughElapsedTimeForUserInfoCheck(previousCheckTimestamp: Long, currentTimeStamp: Long): Boolean { - val elapsedTime = currentTimeStamp - previousCheckTimestamp + fun isEnoughElapsedTimeForUserInfoCheck(previousCheckTimeInMs: Long, currentTimeInMs: Long): Boolean { + val elapsedTime = currentTimeInMs - previousCheckTimeInMs return elapsedTime >= MIN_BACKOFF_FOR_FETCHING_USERINFO } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java b/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java index 32028452..8df8d3bd 100644 --- a/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java +++ b/app/src/main/java/foundation/e/drive/work/FetchUserInfoWorker.java @@ -172,14 +172,14 @@ public class FetchUserInfoWorker extends Worker { Context.MODE_PRIVATE ); - long previousTimestamp = sharedPreferences.getLong(LAST_NOTIFICATION_TIMESTAMP_KEY, 0); - long currentTimeStamp = System.currentTimeMillis(); + long previousTimeInMs = sharedPreferences.getLong(LAST_NOTIFICATION_TIMESTAMP_KEY, 0); + long currentTimeInMs = System.currentTimeMillis(); - if (previousTimestamp == 0 || - currentTimeStamp - previousTimestamp > MILLI_SECONDS_IN_A_DAY) { + if (previousTimeInMs == 0 || + currentTimeInMs - previousTimeInMs > MILLI_SECONDS_IN_A_DAY) { sharedPreferences .edit() - .putLong(LAST_NOTIFICATION_TIMESTAMP_KEY, currentTimeStamp) + .putLong(LAST_NOTIFICATION_TIMESTAMP_KEY, currentTimeInMs) .apply(); return true; } diff --git a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt index 27044644..96c1ca4a 100644 --- a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt +++ b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt @@ -5,43 +5,43 @@ import org.junit.Test internal class ScreenOnReceiverTest { - val currentTimeStamp = System.currentTimeMillis() + private val currentTimeInMs = System.currentTimeMillis() companion object { val instanceUnderTest = ScreenOnReceiver() } @Test fun `isEnoughElapsedTimeForUserInfoCheck with 0 as previous check time`() { - val previousTimestamp = 0L - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + val previousTimeInMs = 0L + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) } @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp earlier than min delay`() { - val previousTimestamp = currentTimeStamp-1 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + val previousTimeInMs = currentTimeInMs-1 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) Assert.assertFalse("isEnoughTimeElapsed should return false but returned: $result", result) } @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp equal to min delay`() { - val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + val previousTimeInMs = currentTimeInMs - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) } @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp older than min delay`() { - val previousTimestamp = currentTimeStamp - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - 1 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + val previousTimeInMs = currentTimeInMs - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - 1 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) } @Test fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp bigger than current timestamp`() { - val previousTimestamp = currentTimeStamp + 10000 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimestamp, currentTimeStamp) + val previousTimeInMs = currentTimeInMs + 10000 + val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) Assert.assertFalse("isEnoughTimeElapsed should return true but returned: $result", result) } } \ No newline at end of file -- GitLab From 5a5389ce243c49a39c3209d3d75a420f60e6e8d9 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 4 Jul 2023 17:37:49 +0200 Subject: [PATCH 9/9] rename isEnoughTimeElapsedToFetchUserInfo into canFetchUserInfo --- .../e/drive/receivers/ScreenOnReceiver.kt | 5 ++-- .../e/drive/receivers/ScreenOnReceiverTest.kt | 30 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt index 94a1290c..e1044f2b 100644 --- a/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt +++ b/app/src/main/java/foundation/e/drive/receivers/ScreenOnReceiver.kt @@ -26,8 +26,7 @@ class ScreenOnReceiver() : BroadcastReceiver() { if (intent?.action.equals(ACTION_SCREEN_ON) && ctx != null) { val preferences = ctx.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE) val previousTimeInMs = preferences?.getLong(USER_INFO_LAST_FETCH_KEY, 0L) ?: 0L - - if (isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, System.currentTimeMillis())) { + if (canFetchUserInfo(previousTimeInMs, System.currentTimeMillis())) { val workManager = WorkManager.getInstance(ctx) CommonUtils.TriggerUserInfoFetching(workManager) } @@ -40,7 +39,7 @@ class ScreenOnReceiver() : BroadcastReceiver() { * @param currentTimeInMs: current time stamp */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun isEnoughElapsedTimeForUserInfoCheck(previousCheckTimeInMs: Long, currentTimeInMs: Long): Boolean { + fun canFetchUserInfo(previousCheckTimeInMs: Long, currentTimeInMs: Long): Boolean { val elapsedTime = currentTimeInMs - previousCheckTimeInMs return elapsedTime >= MIN_BACKOFF_FOR_FETCHING_USERINFO } diff --git a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt index 96c1ca4a..119edeac 100644 --- a/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt +++ b/app/src/test/java/foundation/e/drive/receivers/ScreenOnReceiverTest.kt @@ -11,37 +11,37 @@ internal class ScreenOnReceiverTest { } @Test - fun `isEnoughElapsedTimeForUserInfoCheck with 0 as previous check time`() { + fun `canFetchUserInfo with 0 as previous check time`() { val previousTimeInMs = 0L - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) - Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + val result = instanceUnderTest.canFetchUserInfo(previousTimeInMs, currentTimeInMs) + Assert.assertTrue("canFetchUserInfo should return true but returned: $result", result) } @Test - fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp earlier than min delay`() { + fun `canFetchUserInfo with previous timeStamp earlier than min delay`() { val previousTimeInMs = currentTimeInMs-1 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) - Assert.assertFalse("isEnoughTimeElapsed should return false but returned: $result", result) + val result = instanceUnderTest.canFetchUserInfo(previousTimeInMs, currentTimeInMs) + Assert.assertFalse("canFetchUserInfo should return false but returned: $result", result) } @Test - fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp equal to min delay`() { + fun `canFetchUserInfo with previous timeStamp equal to min delay`() { val previousTimeInMs = currentTimeInMs - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) - Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + val result = instanceUnderTest.canFetchUserInfo(previousTimeInMs, currentTimeInMs) + Assert.assertTrue("canFetchUserInfo should return true but returned: $result", result) } @Test - fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp older than min delay`() { + fun `canFetchUserInfo with previous timeStamp older than min delay`() { val previousTimeInMs = currentTimeInMs - ScreenOnReceiver.MIN_BACKOFF_FOR_FETCHING_USERINFO - 1 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) - Assert.assertTrue("isEnoughTimeElapsed should return true but returned: $result", result) + val result = instanceUnderTest.canFetchUserInfo(previousTimeInMs, currentTimeInMs) + Assert.assertTrue("canFetchUserInfo should return true but returned: $result", result) } @Test - fun `isEnoughElapsedTimeForUserInfoCheck with previous timeStamp bigger than current timestamp`() { + fun `canFetchUserInfo with previous timeStamp bigger than current timestamp`() { val previousTimeInMs = currentTimeInMs + 10000 - val result = instanceUnderTest.isEnoughElapsedTimeForUserInfoCheck(previousTimeInMs, currentTimeInMs) - Assert.assertFalse("isEnoughTimeElapsed should return true but returned: $result", result) + val result = instanceUnderTest.canFetchUserInfo(previousTimeInMs, currentTimeInMs) + Assert.assertFalse("canFetchUserInfo should return true but returned: $result", result) } } \ No newline at end of file -- GitLab