diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d475c3151a9d7a4ce904130ba6d0ba5c5f1caa8d..30859edd891a332cd88abebce535f0d27c95421d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "registry.gitlab.e.foundation:5000/e/apps/docker-android-apps-cicd:latest" +image: "registry.gitlab.e.foundation/e/os/docker-android-apps-cicd:latest" stages: - test diff --git a/app/build.gradle b/app/build.gradle index c65b01d763b0d28230f03af8e2f0b82c8c54df46..018d91fdc4911fef8fe638e8d814616c33e26dfb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,7 +23,7 @@ def getTestProp(String propName) { android { - compileSdkVersion 28 + compileSdkVersion 31 defaultConfig { applicationId "foundation.e.drive" minSdkVersion 26 @@ -53,32 +53,27 @@ android { //includeAndroidResources = true } } - } dependencies { + api project(':NextcloudLib') implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.android.support:appcompat-v7:26.1.0' - - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test:rules:1.0.2' - androidTestImplementation 'androidx.annotation:annotation:1.3.0' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' api 'androidx.annotation:annotation:1.3.0' - api project(':NextcloudLib') - //start to add lib for test - 1/4/21 - //@TODO: add junit runner as lib for testImplementation + def work_version = "2.7.1" + // (Java only) + implementation "androidx.work:work-runtime:$work_version" - testImplementation 'com.android.support.test:runner:1.0.2' - testImplementation 'com.android.support.test:rules:1.0.2' + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test:rules:1.4.0' + androidTestImplementation 'androidx.annotation:annotation:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'junit:junit:4.12' + + testImplementation 'androidx.test:runner:1.4.0' + testImplementation 'androidx.test:rules:1.4.0' testImplementation 'junit:junit:4.12' - //testImplementation 'org.robolectric:robolectric:4.4' //need AndroidX - testImplementation "org.robolectric:robolectric:3.8" + testImplementation 'org.robolectric:robolectric:4.4' testImplementation('org.mockito:mockito-inline:3.4.0') - - //testImplementation Libs.AndroidX.Test.archCoreTesting //TODO: replace by not android X version - //implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' - androidTestImplementation 'junit:junit:4.12' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index be871995566a3c5de7fc4bbb8df3365b36fc9856..7337a890ac65106bb8dcaeac04f4eb87f89869c3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -61,22 +61,11 @@ http://www.gnu.org/licenses/gpl.html - - - - - - - diff --git a/app/src/main/java/foundation/e/drive/EdriveApplication.java b/app/src/main/java/foundation/e/drive/EdriveApplication.java index de7bdcf7f1a21e588e0d84f882d62c419f3d3e62..b6f6ae3533aca2c1e3698aece545df0e162d4f0c 100644 --- a/app/src/main/java/foundation/e/drive/EdriveApplication.java +++ b/app/src/main/java/foundation/e/drive/EdriveApplication.java @@ -17,7 +17,6 @@ import android.util.Log; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; -import foundation.e.drive.utils.JobUtils; /** * Class representing the eDrive application. @@ -36,7 +35,7 @@ public class EdriveApplication extends Application { SharedPreferences prefs = getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); if (prefs.getString(AccountManager.KEY_ACCOUNT_NAME, null) != null) { - scheduleScannerJob(); + Log.d(TAG, "Account already registered"); } else { Account mAccount = CommonUtils.getAccount(getString(R.string.eelo_account_type), AccountManager.get(this)); if (mAccount != null) { @@ -47,17 +46,10 @@ public class EdriveApplication extends Application { .putString(AccountManager.KEY_ACCOUNT_TYPE, accountType) .apply(); - scheduleScannerJob(); } } } - private void scheduleScannerJob() { - if (!JobUtils.isScannerJobRegistered(this)) { - JobUtils.scheduleScannerJob(this); - } - } - private void resetOperationManagerSetting() { getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE).edit() .putBoolean(AppConstants.KEY_OMS_IS_WORKING, false) diff --git a/app/src/main/java/foundation/e/drive/jobs/ScannerJob.java b/app/src/main/java/foundation/e/drive/jobs/ScannerJob.java deleted file mode 100644 index 878f554b882119cefd4795e8131d2660ddcba33a..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/jobs/ScannerJob.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © Vincent Bourgmayer (/e/ foundation). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.jobs; - -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.content.Intent; -import android.content.IntentFilter; -import android.util.Log; -import foundation.e.drive.receivers.ScreenOffReceiver; -import foundation.e.drive.services.ObserverService; -import foundation.e.drive.utils.CommonUtils; - -/** - * @author Vincent Bourgmayer - */ -public class ScannerJob extends JobService { - final private String TAG = ScannerJob.class.getSimpleName(); //Tag for log - - @Override - public boolean onStartJob(JobParameters params) { - Log.i(TAG, "onStartJob()"); - - Log.d(TAG, "RegisterReceiver: screenOffReceiver"); - IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - getApplicationContext().registerReceiver(ScreenOffReceiver.getInstance(), filter); - - Intent observerServiceIntent = new Intent(this, ObserverService.class); - this.startService(observerServiceIntent); - jobFinished(params, false); - return true; - } - - /** - * - * @param params - * @return default return... ? - */ - @Override - public boolean onStopJob(JobParameters params) { - Log.i(TAG, "onStopJob"); - boolean unregisteredReceiver = CommonUtils.unregisterScreenOff(getApplicationContext()); - Intent observerServiceIntent = new Intent(this, ObserverService.class); - this.stopService(observerServiceIntent); - return false; - } -} diff --git a/app/src/main/java/foundation/e/drive/receivers/BatteryStateReceiver.java b/app/src/main/java/foundation/e/drive/receivers/BatteryStateReceiver.java deleted file mode 100644 index 2fd661d1f98da129baffb84b77b94dfff9ecfcbc..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/receivers/BatteryStateReceiver.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © Vincent Bourgmayer (/e/ foundation). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; -import foundation.e.drive.utils.JobUtils; - -/** - * @author Vincent Bourgmayer - */ -public class BatteryStateReceiver extends BroadcastReceiver { - private final static String TAG = BatteryStateReceiver.class.getSimpleName(); - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "onReceive"); - - String intentAction = intent.getAction(); - if(intentAction == null) { - Log.e(TAG, "intent Action is null"); - } else if ( intentAction.equals(Intent.ACTION_BATTERY_OKAY) ) { - JobUtils.scheduleScannerJob(context); - }else if(intentAction.equals(Intent.ACTION_BATTERY_LOW)){ - JobUtils.stopScheduledJob(context, JobUtils.ScannerJobId); - try { - context.unregisterReceiver(ScreenOffReceiver.getInstance()); - }catch(Exception e){ - Log.e(TAG, e.toString() ); - } - } - } -} diff --git a/app/src/main/java/foundation/e/drive/receivers/ScreenOffReceiver.java b/app/src/main/java/foundation/e/drive/receivers/ScreenOffReceiver.java deleted file mode 100644 index 27d489598d6fb2b579ddd671612ac7a87c96541f..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/receivers/ScreenOffReceiver.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright © Vincent Bourgmayer (/e/ foundation). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; -import foundation.e.drive.services.ObserverService; -import foundation.e.drive.utils.CommonUtils; - -/** - * @author Vincent Bourgmayer - * This is a broadcast receiver which catch "ACTION_SCREEN_OFF" to start scanning at a moment - * where the user won't need battery or network. - */ -public class ScreenOffReceiver extends BroadcastReceiver { - private final String TAG = ScreenOffReceiver.class.getSimpleName(); - private static ScreenOffReceiver instance; - - public static ScreenOffReceiver getInstance(){ - if(instance == null) - instance = new ScreenOffReceiver(); - return instance; - } - - /** - * Private constructor - */ - private ScreenOffReceiver(){} - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "onReceive"); - String intentAction = intent.getAction(); - if(intentAction == null){ - Log.e(TAG, "intent Action is null"); - } else if ( intent.getAction().equals(Intent.ACTION_SCREEN_OFF) - && CommonUtils.haveNetworkConnexion( context ) ) { - Log.d(TAG, "onReceive: ACTION_SCREEN_OFF"); - Intent cloudIntent = new Intent(context, ObserverService.class); - context.startService(cloudIntent); - } - } -} 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 289229b2aa8a50abea151c6b047ec39aa1a4a24b..ad6822507535487a09b4e78b7ccb9c4a76c5b9c6 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -13,7 +13,6 @@ import android.accounts.AccountManager; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Build; import android.os.Environment; @@ -26,17 +25,16 @@ import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.operations.CreateInitialFolderRemoteOperation; -import foundation.e.drive.receivers.ScreenOffReceiver; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; -import foundation.e.drive.utils.JobUtils; -import foundation.e.drive.utils.ServiceExceptionHandler; + import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR; import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; @@ -44,15 +42,16 @@ import static foundation.e.drive.utils.AppConstants.MEDIA_SYNCABLE_CATEGORIES; import static foundation.e.drive.utils.AppConstants.SETTINGS_SYNCABLE_CATEGORIES; import androidx.annotation.Nullable; +import androidx.work.WorkManager; /** * @author Vincent Bourgmayer */ public class InitializerService extends Service implements OnRemoteOperationListener { - final private String TAG = InitializerService.class.getSimpleName(); - //Complex properties - private int existingRemoteFolderCounter; //@dev-only; Temporarily used to know if all remotePath exist - private List mSyncedFolders; //syncedFolders + private final String TAG = InitializerService.class.getSimpleName(); + + private int existingRemoteFolderCounter; //Temporarily used to know if all remotePath exist + private List mSyncedFolders; private OwnCloudClient mCloudClient; private Handler mHandler; private Account mAccount; @@ -63,7 +62,6 @@ public class InitializerService extends Service implements OnRemoteOperationList Log.i(TAG, "onCreate()"); super.onCreate(); this.existingRemoteFolderCounter = 0; - //JobUtils.scheduleInitializerJob(getApplicationContext()); } @Override @@ -74,10 +72,11 @@ public class InitializerService extends Service implements OnRemoteOperationList //Get account SharedPreferences prefs = this.getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE ); - if( prefs.getBoolean( AppConstants.INITIALIZATION_HAS_BEEN_DONE, false ) ) { - JobUtils.scheduleScannerJob(this); + + if (prefs.getBoolean( AppConstants.INITIALIZATION_HAS_BEEN_DONE, false ) ) { + Log.w(TAG, "Initializer has already been run"); - }else{ + } else { String accountName = prefs.getString( AccountManager.KEY_ACCOUNT_NAME, "" ); String accountType = prefs.getString( AccountManager.KEY_ACCOUNT_TYPE, "" ); @@ -86,23 +85,21 @@ public class InitializerService extends Service implements OnRemoteOperationList accountName = intent.getExtras().getString( AccountManager.KEY_ACCOUNT_NAME, "" ); accountType = intent.getExtras().getString( AccountManager.KEY_ACCOUNT_TYPE, "" ); - //If data come from intent, store them into pref because there aren't stored prefs.edit().putString( AccountManager.KEY_ACCOUNT_NAME, accountName ) .putString( AccountManager.KEY_ACCOUNT_TYPE, accountType ) .apply(); } - if(accountName.isEmpty() ) { + if (accountName.isEmpty() ) { Log.w(TAG, "Account's name not found. Neither in shared prefs nor in intent's extras"); - //JobUtils.stopScheduledJob(getApplicationContext(), JobUtils.InitializerJobId); stopSelf(); - }else{ + } else { this.mAccount = CommonUtils.getAccount( accountName, accountType, AccountManager.get(this) ); //Get OwnCloudlient if (this.mAccount != null) { this.mCloudClient = CommonUtils.getOwnCloudClient( this.mAccount, getApplicationContext()); start(); - }else { + } else { Log.w(TAG, "Got account is invalid."); stopSelf(); } @@ -123,7 +120,6 @@ public class InitializerService extends Service implements OnRemoteOperationList return; } - //Get categories of element to sync List syncCategories = new ArrayList<>(); if (CommonUtils.isMediaSyncEnabled(mAccount)) { @@ -134,7 +130,6 @@ public class InitializerService extends Service implements OnRemoteOperationList syncCategories.addAll(Arrays.asList(SETTINGS_SYNCABLE_CATEGORIES)); } - //Get SyncedFolders getInitialSyncedFolders(syncCategories); this.existingRemoteFolderCounter = 0; @@ -195,7 +190,7 @@ public class InitializerService extends Service implements OnRemoteOperationList false, true, false) ); - }catch (Exception e){ Log.e(TAG, e.toString()); } + } catch (Exception e){ Log.e(TAG, e.toString()); } break; } } @@ -212,15 +207,14 @@ public class InitializerService extends Service implements OnRemoteOperationList Log.i(TAG, "createNextRemoteFolder()"); this.restartFolderCreationCounter = 0; - if( this.mSyncedFolders == null || this.mSyncedFolders.isEmpty() ){ - //JobUtils.stopScheduledJob(getApplicationContext(), JobUtils.InitializerJobId); + if (this.mSyncedFolders == null || this.mSyncedFolders.isEmpty() ){ this.stopSelf(); } //It means that there are still folders to create - if( this.existingRemoteFolderCounter < this.mSyncedFolders.size() ){ + if (this.existingRemoteFolderCounter < this.mSyncedFolders.size() ){ - if( this.mHandler == null ) this.mHandler = new Handler(); + if (this.mHandler == null ) this.mHandler = new Handler(); CreateInitialFolderRemoteOperation createFolderOperation = new CreateInitialFolderRemoteOperation( @@ -230,11 +224,11 @@ public class InitializerService extends Service implements OnRemoteOperationList createFolderOperation.execute(this.mCloudClient, this, this.mHandler); - }else if(this.existingRemoteFolderCounter == this.mSyncedFolders.size() ){ + } else if (this.existingRemoteFolderCounter == this.mSyncedFolders.size() ){ doLastStep(); - }else{ + } else { Log.e(TAG, "this.existingRemoteFolderCounter : "+this.existingRemoteFolderCounter+" > this.mSyncedFolders.size() : "+this.mSyncedFolders.size() ); this.stopSelf(); } @@ -243,26 +237,26 @@ public class InitializerService extends Service implements OnRemoteOperationList @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { Log.i(TAG, "onRemoteOperationFinish()"); - if(operation instanceof CreateInitialFolderRemoteOperation){ + if (operation instanceof CreateInitialFolderRemoteOperation){ - if(result.isSuccess() || result.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS){ + if (result.isSuccess() || result.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS){ this.existingRemoteFolderCounter+=1; CreateNextRemoteFolder(); - }else if( result.getHttpCode() == 423 || result.getHttpCode() == 409){//file locked or conflict in result + } else if (result.getHttpCode() == 423 || result.getHttpCode() == 409){//file locked or conflict in result Log.e( TAG, result.getLogMessage() ); - if( this.restartFolderCreationCounter < 3) { + if (this.restartFolderCreationCounter < 3) { Log.w( TAG, " restart operation" ); operation.execute( this.mCloudClient, this, this.mHandler ); this.restartFolderCreationCounter+=1; - }else{ + } else { Log.e(TAG, "Remote folder's creation failed due to conflict with server"); stopSelf(); } - }else{ + } else { Log.e(TAG, result.getLogMessage()+" "+result.getHttpCode() ); stopSelf(); } @@ -275,8 +269,7 @@ public class InitializerService extends Service implements OnRemoteOperationList **/ private void doLastStep(){ Log.i(TAG, "doLastStep()"); - - Context appContext = getApplicationContext(); + final Context appContext = getApplicationContext(); appContext.getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE ) .edit() @@ -284,22 +277,16 @@ public class InitializerService extends Service implements OnRemoteOperationList .putInt( INITIALFOLDERS_NUMBER, mSyncedFolders.size() ) .apply(); + CommonUtils.registerPeriodicFullScanWorker(WorkManager.getInstance(appContext)); + //all folder have been created - //JobUtils.stopScheduledJob(appContext, JobUtils.InitializerJobId); - JobUtils.scheduleScannerJob(appContext); - Log.d(TAG, "RegisterReceiver: screenOffReceiver"); - IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - getApplicationContext().registerReceiver(ScreenOffReceiver.getInstance(), filter); //Immediatly start ObserverService to not have to wait 30 minutes. Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class); startService(observersServiceIntent); - stopSelf(); - } @Override diff --git a/app/src/main/java/foundation/e/drive/services/ObserverService.java b/app/src/main/java/foundation/e/drive/services/ObserverService.java index c90b4167adcfebb0632a9d8c751f40ff51ce44e9..a0e8c7eb89cdf6ccd888a59cfd22e449fa19b0a0 100644 --- a/app/src/main/java/foundation/e/drive/services/ObserverService.java +++ b/app/src/main/java/foundation/e/drive/services/ObserverService.java @@ -49,7 +49,6 @@ import foundation.e.drive.receivers.ForceSyncReceiver; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.utils.DavClientProvider; -import foundation.e.drive.utils.JobUtils; import foundation.e.drive.utils.ServiceExceptionHandler; import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR; @@ -95,7 +94,6 @@ public class ObserverService extends Service implements OnRemoteOperationListene // Check if account is invalid if(this.mAccount == null){ Log.w(TAG, "No account registered"); - JobUtils.stopScheduledJob(this, JobUtils.ScannerJobId); //If no account return super.onStartCommand(intent, flags, startId); } diff --git a/app/src/main/java/foundation/e/drive/services/ResetService.java b/app/src/main/java/foundation/e/drive/services/ResetService.java index dad3cb20a6b024884a57bb35bd0e62e24ee7e55a..7b7c9d4e6e2ccba4fbd980968addeafc2bf2022e 100644 --- a/app/src/main/java/foundation/e/drive/services/ResetService.java +++ b/app/src/main/java/foundation/e/drive/services/ResetService.java @@ -21,12 +21,12 @@ import java.io.File; import foundation.e.drive.database.DbHelper; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; -import foundation.e.drive.utils.JobUtils; import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE; import androidx.annotation.Nullable; +import androidx.work.WorkManager; /** * @author Vincent Bourgmayer @@ -64,9 +64,8 @@ public class ResetService extends Service { result = getApplicationContext().stopService( stopperIntent ); Log.d(TAG, "stop OperationManagerService: "+result); - //2. Stop the scheduledJob - JobUtils.stopScheduledJob(this, JobUtils.ScannerJobId); - //JobUtils.stopScheduledJob(this, JobUtils.InitializerJobId); + WorkManager.getInstance(this).cancelAllWorkByTag(AppConstants.WORK_GENERIC_TAG); + //3. delete DB result = this.deleteDatabase(DbHelper.DATABASE_NAME); Log.d(TAG, "Remove Database: "+result); @@ -86,11 +85,8 @@ public class ResetService extends Service { .apply(); } - //5. Unregister screenOffReceiver - result = CommonUtils.unregisterScreenOff(getApplicationContext()); - Log.d(TAG, "Unregistered ScreenOffReceiver: "+result); - //6. Remove Cached File + //5. Remove Cached File File[] cachedFiles = this.getApplicationContext().getExternalCacheDir().listFiles(); for(File f : cachedFiles){ f.delete(); 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 1e180424b8cb05744a5e37cb6f1d72a6f92d46a6..7506a525ee466e117113fcc3f5e778712f6ba2d7 100644 --- a/app/src/main/java/foundation/e/drive/utils/AppConstants.java +++ b/app/src/main/java/foundation/e/drive/utils/AppConstants.java @@ -40,7 +40,7 @@ public abstract class AppConstants { public final static String notificationChannelID ="3310"; public final static String notificationChannelName="eDrive channel"; - + public final static String WORK_GENERIC_TAG="eDrive"; public final static String USER_AGENT = "eos("+getBuildTime()+")-eDrive("+ BuildConfig.VERSION_NAME +")"; 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 e0f762fcb4f2d104db8baa88938f26276ddbee85..21c2099bd416c54e9c352299b650d0da08335a43 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -17,7 +17,6 @@ import android.content.ContentResolver; import android.content.Context; import android.media.MediaScannerConnection; import android.net.ConnectivityManager; -import android.net.Network; import android.net.NetworkInfo; import android.net.Uri; import android.util.Log; @@ -31,13 +30,20 @@ import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.resources.files.FileUtils; import java.io.File; +import java.util.concurrent.TimeUnit; -import foundation.e.drive.receivers.ScreenOffReceiver; + +import foundation.e.drive.work.FullScanWorker; import static foundation.e.drive.utils.AppConstants.MEDIASYNC_PROVIDER_AUTHORITY; import static foundation.e.drive.utils.AppConstants.SETTINGSYNC_PROVIDER_AUTHORITY; import androidx.annotation.NonNull; +import androidx.work.Constraints; +import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkManager; /** @@ -45,7 +51,7 @@ import androidx.annotation.NonNull; */ public abstract class CommonUtils { - final private static String TAG = CommonUtils.class.getSimpleName(); + private final static String TAG = CommonUtils.class.getSimpleName(); /** * Set ServiceUncaughtExceptionHandler to be the MainThread Exception Handler @@ -64,23 +70,6 @@ public abstract class CommonUtils { } } - /** - * Unregister from screeOffReceiver component - * - * @param context app context - * @return true if unregistration was successful or false if it encounter an exception - */ - public static boolean unregisterScreenOff(Context context) { - try { - Log.d("TAG", "unregisterReceiver(screenOffReceiver)"); - context.unregisterReceiver(ScreenOffReceiver.getInstance()); - } catch (IllegalArgumentException e) { - Log.w(TAG, "Can't unregister screenOffReceiver "); - return false; - } - return true; - } - /** * This method retrieve Account corresponding to account's name and type @@ -163,7 +152,7 @@ public abstract class CommonUtils { oc.setCredentials(new OwnCloudBasicCredentials(account.name, AccountManager.get(context).getPassword(account))); Log.d(TAG, "user agent: "+AppConstants.USER_AGENT); - if(!AppConstants.USER_AGENT.equals(OwnCloudClientManagerFactory.getUserAgent())) { + if (!AppConstants.USER_AGENT.equals(OwnCloudClientManagerFactory.getUserAgent()) ){ OwnCloudClientManagerFactory.setUserAgent(AppConstants.USER_AGENT); } @@ -293,4 +282,25 @@ public abstract class CommonUtils { + "\n File can be read?: " + f.canRead() + "\n File can be written?: " + f.canWrite(); } + + /** + * Enqueue a unique periodic worker to look for file to be synchronized (remote files + local files + * @param workManager the instance of workManager + */ + public static void registerPeriodicFullScanWorker(WorkManager workManager){ + final Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .setRequiresBatteryNotLow(true) + .build(); + + final PeriodicWorkRequest periodicFullScanRequest = + new PeriodicWorkRequest.Builder(FullScanWorker.class, + 31, TimeUnit.MINUTES, + 5, TimeUnit.MINUTES) + .setConstraints(constraints) + .addTag(AppConstants.WORK_GENERIC_TAG) + .build(); + + workManager.enqueueUniquePeriodicWork(FullScanWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, periodicFullScanRequest); + } } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/utils/JobUtils.java b/app/src/main/java/foundation/e/drive/utils/JobUtils.java deleted file mode 100644 index 790427eb103bdd02a10a0b93fe760a1a2bc4c435..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/utils/JobUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © Vincent Bourgmayer (/e/ foundation). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.utils; - -import android.app.job.JobInfo; -import android.app.job.JobScheduler; -import android.content.ComponentName; -import android.content.Context; -import android.util.Log; -import foundation.e.drive.jobs.ScannerJob; - - -/** - * @author Vincent Bourgmayer - */ - - -public abstract class JobUtils { - final private static String TAG = JobUtils.class.getSimpleName(); //Tag for log - public final static int ScannerJobId = 3310; - //public final static int InitializerJobId = 3311; - - /** - * Start the scheduledJob for observing remote's folder - * @param context app or service context - */ - public static void scheduleScannerJob(Context context){ - Log.i(TAG, "scheduleJob"); - /* I. Start periodic checkup */ - ComponentName jobService = new ComponentName( context, ScannerJob.class ); - - JobInfo job = new JobInfo.Builder(ScannerJobId, jobService ) - .setPeriodic(1860000, 30000) //31git minutes and 30 secondes - .setPersisted(true) - .setRequiredNetworkType( JobInfo.NETWORK_TYPE_ANY ) - .build(); - - JobScheduler jobScheduler = context.getSystemService( JobScheduler.class ); - - if ( jobScheduler.schedule( job ) == JobScheduler.RESULT_SUCCESS ) { - Log.d(TAG, "Scheduled job created"); - } else { - Log.e(TAG, "Scheduled job not created"); - } - } - - /** - * Try to stop the scheduledJob - * @param context - */ - public static void stopScheduledJob(Context context, int jobId){ - context.getSystemService( JobScheduler.class ).cancel(jobId); - } - - /** - * tell if the scannerJob is already registered or not - * @param context - * @return true if is registered, false either - */ - public static boolean isScannerJobRegistered(Context context){ - return (context.getSystemService( JobScheduler.class).getPendingJob(ScannerJobId) != null); - } - -} diff --git a/app/src/main/java/foundation/e/drive/work/FullScanWorker.java b/app/src/main/java/foundation/e/drive/work/FullScanWorker.java new file mode 100644 index 0000000000000000000000000000000000000000..a2424a076e77d7a945e241f706f9df2c4392a2c9 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/work/FullScanWorker.java @@ -0,0 +1,63 @@ +/* + * Copyright © Vincent Bourgmayer (/e/ foundation). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package foundation.e.drive.work; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +import foundation.e.drive.services.ObserverService; +import foundation.e.drive.utils.AppConstants; +import foundation.e.drive.utils.CommonUtils; + +/** + * As a first step, this class must replace foundation.e.drive.jobs.ScannerJob + * in order to allow to use Jetpack Work API + * + * In further development it will be a part of Workers that will replace ObserverService + * I will update this header accordingly + * + * @author Vincent Bourgmayer + */ +public class FullScanWorker extends Worker { + private final static String TAG = FullScanWorker.class.getSimpleName(); + public final static String UNIQUE_WORK_NAME = "FullScan"; + + public FullScanWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + } + + @NonNull + @Override + public Result doWork() { + Log.d(TAG, "doWork(): going to send intent to ObserverService"); + final SharedPreferences prefs = getApplicationContext().getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, + Context.MODE_PRIVATE); + final String accountName = prefs.getString(AccountManager.KEY_ACCOUNT_NAME, ""); + final String accountType = prefs.getString(AccountManager.KEY_ACCOUNT_TYPE, ""); + + final Account mAccount = CommonUtils.getAccount(accountName, accountType, AccountManager.get(this.getApplicationContext())); + + if (mAccount != null && CommonUtils.isSettingsSyncEnabled(mAccount) && CommonUtils.isMediaSyncEnabled(mAccount)) { + final Intent observerServiceIntent = new Intent(this.getApplicationContext(), ObserverService.class); + this.getApplicationContext().startService(observerServiceIntent); + } else { + Log.w(TAG, "Intent for ObserverService not send : account is null or \"settings sync\" & \"media sync\" settings are disabled"); + } + + return Result.success(); + } +} \ No newline at end of file