Loading app/src/main/AndroidManifest.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -12,7 +12,7 @@ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- for Android 30+ --> tools:ignore="ScopedStorage" /> <!-- for Android 30+ --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- needed for PersistedJob --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> Loading app/src/main/java/foundation/e/drive/account/AccountUtils.kt +10 −2 Original line number Original line Diff line number Diff line /* /* * Copyright MURENA SAS 2022-2023 * Copyright MURENA SAS 2022-2024 * This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or Loading @@ -20,8 +20,8 @@ import android.accounts.Account import android.accounts.AccountManager import android.accounts.AccountManager import android.content.Context import android.content.Context import foundation.e.drive.R import foundation.e.drive.R import foundation.e.drive.utils.AppConstants.SHARED_PREFERENCE_NAME import foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS import foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS import foundation.e.drive.utils.AppConstants.SHARED_PREFERENCE_NAME object AccountUtils { object AccountUtils { Loading Loading @@ -68,4 +68,12 @@ object AccountUtils { return accountManager.getAccountsByType(accountType) return accountManager.getAccountsByType(accountType) .firstOrNull { account -> account.name == accountName } .firstOrNull { account -> account.name == accountName } } } @JvmStatic fun isAccountAvailable(context: Context): Boolean { val accountManager = AccountManager.get(context.applicationContext) val accountList = accountManager.getAccountsByType(context.getString(R.string.eelo_account_type)) return accountList.isNotEmpty() } } } app/src/main/java/foundation/e/drive/account/receivers/AccountAddedReceiver.kt +6 −41 Original line number Original line Diff line number Diff line /* /* * Copyright © MURENA SAS 2023. * Copyright © MURENA SAS 2023-2024. * All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * which accompanies this distribution, and is available at Loading @@ -14,11 +14,8 @@ import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences import foundation.e.drive.R import foundation.e.drive.R import foundation.e.drive.account.AccountUtils import foundation.e.drive.account.AccountUtils import foundation.e.drive.models.SyncedFolder import foundation.e.drive.utils.AppConstants import foundation.e.drive.utils.AppConstants import foundation.e.drive.utils.DavClientProvider import foundation.e.drive.utils.DavClientProvider import foundation.e.drive.utils.RootSyncedFolderProvider import foundation.e.drive.work.WorkRequestFactory.* import foundation.e.drive.work.WorkLauncher import foundation.e.drive.work.WorkLauncher import timber.log.Timber import timber.log.Timber Loading Loading @@ -47,10 +44,10 @@ class AccountAddedReceiver() : BroadcastReceiver() { .putString(AccountManager.KEY_ACCOUNT_NAME, accountName) .putString(AccountManager.KEY_ACCOUNT_NAME, accountName) .apply() .apply() if (registerSetupWorkers(context)) { val workLauncher = WorkLauncher.getInstance(context) if (workLauncher.enqueueSetupWorkers(context)) { DavClientProvider.getInstance().cleanUp() DavClientProvider.getInstance().cleanUp() workLauncher.enqueuePeriodicUserInfoFetching() WorkLauncher.getInstance(context).enqueuePeriodicUserInfoFetching() } } } } Loading @@ -67,7 +64,7 @@ class AccountAddedReceiver() : BroadcastReceiver() { prefs: SharedPreferences, prefs: SharedPreferences, context: Context context: Context ): Boolean { ): Boolean { if (AccountUtils.isSetupAlreadyDone(prefs)) { if (isSetupAlreadyDone(prefs)) { return false return false } } Loading Loading @@ -98,36 +95,4 @@ class AccountAddedReceiver() : BroadcastReceiver() { private fun isExistingAccount(accountName: String, context: Context): Boolean { private fun isExistingAccount(accountName: String, context: Context): Boolean { return AccountUtils.getAccount(accountName, context) != null return AccountUtils.getAccount(accountName, context) != null } } private fun registerSetupWorkers(context: Context): Boolean { val rootFolderSetupWorkers = generateRootFolderSetupWorkers(context) ?: return false val getUserInfoRequest = getOneTimeWorkRequest(WorkType.ONE_TIME_USER_INFO, null) val finishSetupRequest = getOneTimeWorkRequest(WorkType.ONE_TIME_FINISH_SETUP, null) val workManager = WorkManager.getInstance(context) workManager.beginWith(getUserInfoRequest) .then(rootFolderSetupWorkers) .then(finishSetupRequest) .enqueue() return true } private fun generateRootFolderSetupWorkers(context: Context): MutableList<OneTimeWorkRequest>? { val rootSyncedFolderList: List<SyncedFolder> = RootSyncedFolderProvider.getSyncedFolderRoots(context) if (rootSyncedFolderList.isEmpty()) { return null } val workRequests: MutableList<OneTimeWorkRequest> = ArrayList() for (folder in rootSyncedFolderList) { val rootFolderSetupWorkRequest = getOneTimeWorkRequest( WorkType.ONE_TIME_ROOT_FOLDER_SETUP, folder ) workRequests.add(rootFolderSetupWorkRequest) } return workRequests } } } app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java +50 −40 Original line number Original line Diff line number Diff line /* /* * Copyright © MURENA SAS 2022-2023. * Copyright © MURENA SAS 2022-2024. * All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * which accompanies this distribution, and is available at Loading @@ -24,6 +24,7 @@ import foundation.e.drive.synchronization.SyncProxy; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.work.WorkLauncher; import foundation.e.drive.work.WorkLauncher; import foundation.e.drive.account.AccountUtils; import timber.log.Timber; import timber.log.Timber; /** /** Loading @@ -38,21 +39,36 @@ public class BootCompletedReceiver extends BroadcastReceiver { private static final int VERSION_CODE_FOR_UPDATE_1 = 1002000; private static final int VERSION_CODE_FOR_UPDATE_1 = 1002000; private static final int VERSION_CODE_FOR_UPDATE_2 = 1003017; private static final int VERSION_CODE_FOR_UPDATE_2 = 1003017; @Override @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { public void onReceive(@NonNull Context context, @NonNull Intent intent) { final String action = intent.getAction(); final String action = intent.getAction(); Timber.v("onReceive(...)"); Timber.v("onReceive(...)"); if (!Intent.ACTION_BOOT_COMPLETED.equals(action) || !AccountUtils.isAccountAvailable(context)) { return; } final SharedPreferences prefs = context.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); final SharedPreferences prefs = context.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); final WorkLauncher workLauncher = WorkLauncher.getInstance(context); if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { migrateSetupCompletedPrefsKey(prefs); final String currentDateProp = CommonUtils.getProp(DATE_SYSTEM_PROPERTY); if (!isSetupCompleted(prefs)){ workLauncher.enqueueSetupWorkers(context); return; } if (isOsUpdated(prefs, currentDateProp)) { // App is persistent so can only be updated (by replacement) on OS update /* * App was persistent so can only be updated (by replacement) on OS update * note: still needs the below check and call when migrating for persistent eDrive to not persistent eDrive. * But on "not persistent eDrive" update "to not persistent eDrive" update+1, this won't be required again */ final String currentDateProp = CommonUtils.getProp(DATE_SYSTEM_PROPERTY); if (isOsUpdated(prefs, currentDateProp)) { handleOsUpdate(context); handleOsUpdate(context); } } changeSetupCompletedPreferenceKey(prefs); if (!isSetupCompleted(prefs)) return; final int lastSavedVersionCode = prefs.getInt(PREF_VERSION_CODE, VERSION_CODE_FOR_UPDATE_1); final int lastSavedVersionCode = prefs.getInt(PREF_VERSION_CODE, VERSION_CODE_FOR_UPDATE_1); if (isEdriveUpdated(lastSavedVersionCode)) { if (isEdriveUpdated(lastSavedVersionCode)) { Loading @@ -60,20 +76,13 @@ public class BootCompletedReceiver extends BroadcastReceiver { prefs.edit().putInt(PREF_VERSION_CODE, BuildConfig.VERSION_CODE).apply(); prefs.edit().putInt(PREF_VERSION_CODE, BuildConfig.VERSION_CODE).apply(); } } if (isAccountPresent) { WorkerUtils.INSTANCE.registerSetupWorkers(context.getApplicationContext()); } SyncProxy.INSTANCE.startListeningFiles((Application) context.getApplicationContext()); SyncProxy.INSTANCE.startListeningFiles((Application) context.getApplicationContext()); } } private void forceDBUpdate(@NonNull Context context) { workLauncher.enqueuePeriodicFullScan(); final DbHelper dbHelper = new DbHelper(context); workLauncher.enqueuePeriodicUserInfoFetching(); dbHelper.getWritableDatabase().close(); } } private void changeSetupCompletedPreferenceKey(@NonNull SharedPreferences prefs) { private void migrateSetupCompletedPrefsKey(@NonNull SharedPreferences prefs) { if (prefs.getBoolean(OLD_SETUP_COMPLETED_PREF_KEY, false)) { if (prefs.getBoolean(OLD_SETUP_COMPLETED_PREF_KEY, false)) { Timber.i("Update setup complete preferences"); Timber.i("Update setup complete preferences"); prefs prefs Loading @@ -81,16 +90,7 @@ public class BootCompletedReceiver extends BroadcastReceiver { .remove(OLD_SETUP_COMPLETED_PREF_KEY) .remove(OLD_SETUP_COMPLETED_PREF_KEY) .putBoolean(AppConstants.SETUP_COMPLETED, true) .putBoolean(AppConstants.SETUP_COMPLETED, true) .apply(); .apply(); } } } /** * Force reinitialization, upgrade of DB in case of OS update * @param context Context used to start InitializationService */ private void handleOsUpdate(@NonNull Context context) { forceDBUpdate(context); } } /** @noinspection SpellCheckingInspection*/ /** @noinspection SpellCheckingInspection*/ Loading @@ -99,10 +99,6 @@ public class BootCompletedReceiver extends BroadcastReceiver { return BuildConfig.VERSION_CODE > oldVersionCode; return BuildConfig.VERSION_CODE > oldVersionCode; } } private boolean isSetupCompleted(@NonNull SharedPreferences prefs) { return prefs.getBoolean(AppConstants.SETUP_COMPLETED, false); } private void onEdriveUpdate(int oldVersionCode, @NonNull Context context) { private void onEdriveUpdate(int oldVersionCode, @NonNull Context context) { if (oldVersionCode <= VERSION_CODE_FOR_UPDATE_1) { if (oldVersionCode <= VERSION_CODE_FOR_UPDATE_1) { try { try { Loading @@ -117,8 +113,9 @@ public class BootCompletedReceiver extends BroadcastReceiver { final WorkManager workManager= WorkManager.getInstance(context); final WorkManager workManager= WorkManager.getInstance(context); workManager.cancelAllWork(); workManager.cancelAllWork(); WorkLauncher.getInstance(context).enqueuePeriodicFullScan(); final WorkLauncher workLauncher = WorkLauncher.getInstance(context); WorkLauncher.getInstance(context).enqueuePeriodicUserInfoFetching(); workLauncher.enqueuePeriodicFullScan(); workLauncher.enqueuePeriodicUserInfoFetching(); } } } } Loading @@ -126,4 +123,17 @@ public class BootCompletedReceiver extends BroadcastReceiver { final String lastKnownDateProp = prefs.getString(DATE_SYSTEM_PROPERTY, ""); final String lastKnownDateProp = prefs.getString(DATE_SYSTEM_PROPERTY, ""); return !currentDateProp.equals(lastKnownDateProp); return !currentDateProp.equals(lastKnownDateProp); } } /** * Force reinitialization, upgrade of DB in case of OS update * @param context Context used to start InitializationService */ private void handleOsUpdate(@NonNull Context context) { final DbHelper dbHelper = new DbHelper(context); dbHelper.getWritableDatabase().close(); //force DB update } private boolean isSetupCompleted(@NonNull SharedPreferences prefs) { return prefs.getBoolean(AppConstants.SETUP_COMPLETED, false); } } } app/src/main/java/foundation/e/drive/synchronization/tasks/UploadFileOperation.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -285,7 +285,7 @@ public class UploadFileOperation extends RemoteOperation { @VisibleForTesting() @VisibleForTesting() @NonNull @NonNull public RemoteOperationResult uploadChunkedFile(@NonNull final File file, @NonNull final OwnCloudClient client) { public RemoteOperationResult uploadChunkedFile(@NonNull final File file, @NonNull final OwnCloudClient client) { final long timeStamp = file.lastModified() / 1000; final long timeStamp = formatTimestampToMatchCloud(file.lastModified()); final String mimeType = getMimeType(file); final String mimeType = getMimeType(file); final ChunkedFileUploadRemoteOperation uploadOperation = new ChunkedFileUploadRemoteOperation(syncedState.getLocalPath(), final ChunkedFileUploadRemoteOperation uploadOperation = new ChunkedFileUploadRemoteOperation(syncedState.getLocalPath(), syncedState.getRemotePath(), syncedState.getRemotePath(), Loading Loading @@ -342,7 +342,7 @@ public class UploadFileOperation extends RemoteOperation { @VisibleForTesting() @VisibleForTesting() @NonNull @NonNull public RemoteOperationResult<String> uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client, boolean checkEtag) { public RemoteOperationResult<String> uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client, boolean checkEtag) { final long timeStamp = file.lastModified() / 1000; final long timeStamp = formatTimestampToMatchCloud(file.lastModified()); final String eTag = checkEtag ? syncedState.getLastEtag() : null; final String eTag = checkEtag ? syncedState.getLastEtag() : null; final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), Loading Loading @@ -380,7 +380,7 @@ public class UploadFileOperation extends RemoteOperation { * @return String timestamp in second * @return String timestamp in second */ */ @VisibleForTesting() @VisibleForTesting() public @NonNull String formatTimestampToMatchCloud(long timestamp) { public long formatTimestampToMatchCloud(long timestamp) { return String.valueOf(timestamp/1000); return timestamp / 1000; } } } } No newline at end of file Loading
app/src/main/AndroidManifest.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -12,7 +12,7 @@ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- for Android 30+ --> tools:ignore="ScopedStorage" /> <!-- for Android 30+ --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- needed for PersistedJob --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> Loading
app/src/main/java/foundation/e/drive/account/AccountUtils.kt +10 −2 Original line number Original line Diff line number Diff line /* /* * Copyright MURENA SAS 2022-2023 * Copyright MURENA SAS 2022-2024 * This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or Loading @@ -20,8 +20,8 @@ import android.accounts.Account import android.accounts.AccountManager import android.accounts.AccountManager import android.content.Context import android.content.Context import foundation.e.drive.R import foundation.e.drive.R import foundation.e.drive.utils.AppConstants.SHARED_PREFERENCE_NAME import foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS import foundation.e.drive.utils.AppConstants.ACCOUNT_DATA_GROUPS import foundation.e.drive.utils.AppConstants.SHARED_PREFERENCE_NAME object AccountUtils { object AccountUtils { Loading Loading @@ -68,4 +68,12 @@ object AccountUtils { return accountManager.getAccountsByType(accountType) return accountManager.getAccountsByType(accountType) .firstOrNull { account -> account.name == accountName } .firstOrNull { account -> account.name == accountName } } } @JvmStatic fun isAccountAvailable(context: Context): Boolean { val accountManager = AccountManager.get(context.applicationContext) val accountList = accountManager.getAccountsByType(context.getString(R.string.eelo_account_type)) return accountList.isNotEmpty() } } }
app/src/main/java/foundation/e/drive/account/receivers/AccountAddedReceiver.kt +6 −41 Original line number Original line Diff line number Diff line /* /* * Copyright © MURENA SAS 2023. * Copyright © MURENA SAS 2023-2024. * All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * which accompanies this distribution, and is available at Loading @@ -14,11 +14,8 @@ import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences import foundation.e.drive.R import foundation.e.drive.R import foundation.e.drive.account.AccountUtils import foundation.e.drive.account.AccountUtils import foundation.e.drive.models.SyncedFolder import foundation.e.drive.utils.AppConstants import foundation.e.drive.utils.AppConstants import foundation.e.drive.utils.DavClientProvider import foundation.e.drive.utils.DavClientProvider import foundation.e.drive.utils.RootSyncedFolderProvider import foundation.e.drive.work.WorkRequestFactory.* import foundation.e.drive.work.WorkLauncher import foundation.e.drive.work.WorkLauncher import timber.log.Timber import timber.log.Timber Loading Loading @@ -47,10 +44,10 @@ class AccountAddedReceiver() : BroadcastReceiver() { .putString(AccountManager.KEY_ACCOUNT_NAME, accountName) .putString(AccountManager.KEY_ACCOUNT_NAME, accountName) .apply() .apply() if (registerSetupWorkers(context)) { val workLauncher = WorkLauncher.getInstance(context) if (workLauncher.enqueueSetupWorkers(context)) { DavClientProvider.getInstance().cleanUp() DavClientProvider.getInstance().cleanUp() workLauncher.enqueuePeriodicUserInfoFetching() WorkLauncher.getInstance(context).enqueuePeriodicUserInfoFetching() } } } } Loading @@ -67,7 +64,7 @@ class AccountAddedReceiver() : BroadcastReceiver() { prefs: SharedPreferences, prefs: SharedPreferences, context: Context context: Context ): Boolean { ): Boolean { if (AccountUtils.isSetupAlreadyDone(prefs)) { if (isSetupAlreadyDone(prefs)) { return false return false } } Loading Loading @@ -98,36 +95,4 @@ class AccountAddedReceiver() : BroadcastReceiver() { private fun isExistingAccount(accountName: String, context: Context): Boolean { private fun isExistingAccount(accountName: String, context: Context): Boolean { return AccountUtils.getAccount(accountName, context) != null return AccountUtils.getAccount(accountName, context) != null } } private fun registerSetupWorkers(context: Context): Boolean { val rootFolderSetupWorkers = generateRootFolderSetupWorkers(context) ?: return false val getUserInfoRequest = getOneTimeWorkRequest(WorkType.ONE_TIME_USER_INFO, null) val finishSetupRequest = getOneTimeWorkRequest(WorkType.ONE_TIME_FINISH_SETUP, null) val workManager = WorkManager.getInstance(context) workManager.beginWith(getUserInfoRequest) .then(rootFolderSetupWorkers) .then(finishSetupRequest) .enqueue() return true } private fun generateRootFolderSetupWorkers(context: Context): MutableList<OneTimeWorkRequest>? { val rootSyncedFolderList: List<SyncedFolder> = RootSyncedFolderProvider.getSyncedFolderRoots(context) if (rootSyncedFolderList.isEmpty()) { return null } val workRequests: MutableList<OneTimeWorkRequest> = ArrayList() for (folder in rootSyncedFolderList) { val rootFolderSetupWorkRequest = getOneTimeWorkRequest( WorkType.ONE_TIME_ROOT_FOLDER_SETUP, folder ) workRequests.add(rootFolderSetupWorkRequest) } return workRequests } } }
app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java +50 −40 Original line number Original line Diff line number Diff line /* /* * Copyright © MURENA SAS 2022-2023. * Copyright © MURENA SAS 2022-2024. * All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * which accompanies this distribution, and is available at Loading @@ -24,6 +24,7 @@ import foundation.e.drive.synchronization.SyncProxy; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.work.WorkLauncher; import foundation.e.drive.work.WorkLauncher; import foundation.e.drive.account.AccountUtils; import timber.log.Timber; import timber.log.Timber; /** /** Loading @@ -38,21 +39,36 @@ public class BootCompletedReceiver extends BroadcastReceiver { private static final int VERSION_CODE_FOR_UPDATE_1 = 1002000; private static final int VERSION_CODE_FOR_UPDATE_1 = 1002000; private static final int VERSION_CODE_FOR_UPDATE_2 = 1003017; private static final int VERSION_CODE_FOR_UPDATE_2 = 1003017; @Override @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { public void onReceive(@NonNull Context context, @NonNull Intent intent) { final String action = intent.getAction(); final String action = intent.getAction(); Timber.v("onReceive(...)"); Timber.v("onReceive(...)"); if (!Intent.ACTION_BOOT_COMPLETED.equals(action) || !AccountUtils.isAccountAvailable(context)) { return; } final SharedPreferences prefs = context.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); final SharedPreferences prefs = context.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); final WorkLauncher workLauncher = WorkLauncher.getInstance(context); if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { migrateSetupCompletedPrefsKey(prefs); final String currentDateProp = CommonUtils.getProp(DATE_SYSTEM_PROPERTY); if (!isSetupCompleted(prefs)){ workLauncher.enqueueSetupWorkers(context); return; } if (isOsUpdated(prefs, currentDateProp)) { // App is persistent so can only be updated (by replacement) on OS update /* * App was persistent so can only be updated (by replacement) on OS update * note: still needs the below check and call when migrating for persistent eDrive to not persistent eDrive. * But on "not persistent eDrive" update "to not persistent eDrive" update+1, this won't be required again */ final String currentDateProp = CommonUtils.getProp(DATE_SYSTEM_PROPERTY); if (isOsUpdated(prefs, currentDateProp)) { handleOsUpdate(context); handleOsUpdate(context); } } changeSetupCompletedPreferenceKey(prefs); if (!isSetupCompleted(prefs)) return; final int lastSavedVersionCode = prefs.getInt(PREF_VERSION_CODE, VERSION_CODE_FOR_UPDATE_1); final int lastSavedVersionCode = prefs.getInt(PREF_VERSION_CODE, VERSION_CODE_FOR_UPDATE_1); if (isEdriveUpdated(lastSavedVersionCode)) { if (isEdriveUpdated(lastSavedVersionCode)) { Loading @@ -60,20 +76,13 @@ public class BootCompletedReceiver extends BroadcastReceiver { prefs.edit().putInt(PREF_VERSION_CODE, BuildConfig.VERSION_CODE).apply(); prefs.edit().putInt(PREF_VERSION_CODE, BuildConfig.VERSION_CODE).apply(); } } if (isAccountPresent) { WorkerUtils.INSTANCE.registerSetupWorkers(context.getApplicationContext()); } SyncProxy.INSTANCE.startListeningFiles((Application) context.getApplicationContext()); SyncProxy.INSTANCE.startListeningFiles((Application) context.getApplicationContext()); } } private void forceDBUpdate(@NonNull Context context) { workLauncher.enqueuePeriodicFullScan(); final DbHelper dbHelper = new DbHelper(context); workLauncher.enqueuePeriodicUserInfoFetching(); dbHelper.getWritableDatabase().close(); } } private void changeSetupCompletedPreferenceKey(@NonNull SharedPreferences prefs) { private void migrateSetupCompletedPrefsKey(@NonNull SharedPreferences prefs) { if (prefs.getBoolean(OLD_SETUP_COMPLETED_PREF_KEY, false)) { if (prefs.getBoolean(OLD_SETUP_COMPLETED_PREF_KEY, false)) { Timber.i("Update setup complete preferences"); Timber.i("Update setup complete preferences"); prefs prefs Loading @@ -81,16 +90,7 @@ public class BootCompletedReceiver extends BroadcastReceiver { .remove(OLD_SETUP_COMPLETED_PREF_KEY) .remove(OLD_SETUP_COMPLETED_PREF_KEY) .putBoolean(AppConstants.SETUP_COMPLETED, true) .putBoolean(AppConstants.SETUP_COMPLETED, true) .apply(); .apply(); } } } /** * Force reinitialization, upgrade of DB in case of OS update * @param context Context used to start InitializationService */ private void handleOsUpdate(@NonNull Context context) { forceDBUpdate(context); } } /** @noinspection SpellCheckingInspection*/ /** @noinspection SpellCheckingInspection*/ Loading @@ -99,10 +99,6 @@ public class BootCompletedReceiver extends BroadcastReceiver { return BuildConfig.VERSION_CODE > oldVersionCode; return BuildConfig.VERSION_CODE > oldVersionCode; } } private boolean isSetupCompleted(@NonNull SharedPreferences prefs) { return prefs.getBoolean(AppConstants.SETUP_COMPLETED, false); } private void onEdriveUpdate(int oldVersionCode, @NonNull Context context) { private void onEdriveUpdate(int oldVersionCode, @NonNull Context context) { if (oldVersionCode <= VERSION_CODE_FOR_UPDATE_1) { if (oldVersionCode <= VERSION_CODE_FOR_UPDATE_1) { try { try { Loading @@ -117,8 +113,9 @@ public class BootCompletedReceiver extends BroadcastReceiver { final WorkManager workManager= WorkManager.getInstance(context); final WorkManager workManager= WorkManager.getInstance(context); workManager.cancelAllWork(); workManager.cancelAllWork(); WorkLauncher.getInstance(context).enqueuePeriodicFullScan(); final WorkLauncher workLauncher = WorkLauncher.getInstance(context); WorkLauncher.getInstance(context).enqueuePeriodicUserInfoFetching(); workLauncher.enqueuePeriodicFullScan(); workLauncher.enqueuePeriodicUserInfoFetching(); } } } } Loading @@ -126,4 +123,17 @@ public class BootCompletedReceiver extends BroadcastReceiver { final String lastKnownDateProp = prefs.getString(DATE_SYSTEM_PROPERTY, ""); final String lastKnownDateProp = prefs.getString(DATE_SYSTEM_PROPERTY, ""); return !currentDateProp.equals(lastKnownDateProp); return !currentDateProp.equals(lastKnownDateProp); } } /** * Force reinitialization, upgrade of DB in case of OS update * @param context Context used to start InitializationService */ private void handleOsUpdate(@NonNull Context context) { final DbHelper dbHelper = new DbHelper(context); dbHelper.getWritableDatabase().close(); //force DB update } private boolean isSetupCompleted(@NonNull SharedPreferences prefs) { return prefs.getBoolean(AppConstants.SETUP_COMPLETED, false); } } }
app/src/main/java/foundation/e/drive/synchronization/tasks/UploadFileOperation.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -285,7 +285,7 @@ public class UploadFileOperation extends RemoteOperation { @VisibleForTesting() @VisibleForTesting() @NonNull @NonNull public RemoteOperationResult uploadChunkedFile(@NonNull final File file, @NonNull final OwnCloudClient client) { public RemoteOperationResult uploadChunkedFile(@NonNull final File file, @NonNull final OwnCloudClient client) { final long timeStamp = file.lastModified() / 1000; final long timeStamp = formatTimestampToMatchCloud(file.lastModified()); final String mimeType = getMimeType(file); final String mimeType = getMimeType(file); final ChunkedFileUploadRemoteOperation uploadOperation = new ChunkedFileUploadRemoteOperation(syncedState.getLocalPath(), final ChunkedFileUploadRemoteOperation uploadOperation = new ChunkedFileUploadRemoteOperation(syncedState.getLocalPath(), syncedState.getRemotePath(), syncedState.getRemotePath(), Loading Loading @@ -342,7 +342,7 @@ public class UploadFileOperation extends RemoteOperation { @VisibleForTesting() @VisibleForTesting() @NonNull @NonNull public RemoteOperationResult<String> uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client, boolean checkEtag) { public RemoteOperationResult<String> uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client, boolean checkEtag) { final long timeStamp = file.lastModified() / 1000; final long timeStamp = formatTimestampToMatchCloud(file.lastModified()); final String eTag = checkEtag ? syncedState.getLastEtag() : null; final String eTag = checkEtag ? syncedState.getLastEtag() : null; final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), Loading Loading @@ -380,7 +380,7 @@ public class UploadFileOperation extends RemoteOperation { * @return String timestamp in second * @return String timestamp in second */ */ @VisibleForTesting() @VisibleForTesting() public @NonNull String formatTimestampToMatchCloud(long timestamp) { public long formatTimestampToMatchCloud(long timestamp) { return String.valueOf(timestamp/1000); return timestamp / 1000; } } } } No newline at end of file