diff --git a/build.gradle b/build.gradle
index 0e155a0e04..d528855513 100644
--- a/build.gradle
+++ b/build.gradle
@@ -35,7 +35,6 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
-
apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'jacoco-android'
@@ -263,7 +262,6 @@ dependencies {
implementation 'com.github.tobiaskaminsky:android-job:v1.2.6.1' // 'com.github.evernote:android-job:v1.2.5'
implementation 'com.jakewharton:butterknife:10.1.0'
kapt 'com.jakewharton:butterknife-compiler:10.1.0'
-
implementation 'org.greenrobot:eventbus:3.1.1'
implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.5'
implementation 'org.lukhnos:nnio:0.2'
diff --git a/src/androidTest/java/com/owncloud/android/UploadIT.java b/src/androidTest/java/com/owncloud/android/UploadIT.java
index 9e5eb6db20..cc901f551a 100644
--- a/src/androidTest/java/com/owncloud/android/UploadIT.java
+++ b/src/androidTest/java/com/owncloud/android/UploadIT.java
@@ -4,6 +4,7 @@ import android.content.ContentResolver;
import com.evernote.android.job.JobRequest;
import com.nextcloud.client.account.CurrentAccountProvider;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.UploadsStorageManager;
@@ -48,6 +49,23 @@ public class UploadIT extends AbstractIT {
}
};
+ private PowerManagementService powerManagementServiceMock = new PowerManagementService() {
+ @Override
+ public boolean isPowerSavingEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isPowerSavingExclusionAvailable() {
+ return false;
+ }
+
+ @Override
+ public boolean isBatteryCharging() {
+ return false;
+ }
+ };
+
@Before
public void setUp() {
final ContentResolver contentResolver = targetContext.getContentResolver();
@@ -98,6 +116,7 @@ public class UploadIT extends AbstractIT {
UploadFileOperation newUpload = new UploadFileOperation(
storageManager,
connectivityServiceMock,
+ powerManagementServiceMock,
account,
null,
ocUpload,
@@ -123,6 +142,7 @@ public class UploadIT extends AbstractIT {
UploadFileOperation newUpload = new UploadFileOperation(
storageManager,
connectivityServiceMock,
+ powerManagementServiceMock,
account,
null,
ocUpload,
diff --git a/src/main/java/com/nextcloud/client/di/ComponentsModule.java b/src/main/java/com/nextcloud/client/di/ComponentsModule.java
index ab5828a415..b7ec94797f 100644
--- a/src/main/java/com/nextcloud/client/di/ComponentsModule.java
+++ b/src/main/java/com/nextcloud/client/di/ComponentsModule.java
@@ -26,6 +26,7 @@ import com.owncloud.android.authentication.DeepLinkLoginActivity;
import com.owncloud.android.files.BootupBroadcastReceiver;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.jobs.NContentObserverJob;
import com.owncloud.android.jobs.NotificationJob;
import com.owncloud.android.providers.DiskLruImageCacheFileProvider;
import com.owncloud.android.providers.DocumentsStorageProvider;
@@ -147,4 +148,5 @@ abstract class ComponentsModule {
@ContributesAndroidInjector abstract AccountManagerService accountManagerService();
@ContributesAndroidInjector abstract OperationsService operationsService();
+ @ContributesAndroidInjector abstract NContentObserverJob contentObserverJob();
}
diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java
index 7cee61103b..75d40de8bc 100644
--- a/src/main/java/com/owncloud/android/MainApp.java
+++ b/src/main/java/com/owncloud/android/MainApp.java
@@ -46,6 +46,7 @@ import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.appinfo.AppInfo;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.di.ActivityInjector;
import com.nextcloud.client.di.DaggerAppComponent;
import com.nextcloud.client.network.ConnectivityService;
@@ -106,9 +107,8 @@ import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.PREFER
/**
* Main Application of the project
- *
- * Contains methods to build the "static" strings. These strings were before constants in different
- * classes
+ *
+ * Contains methods to build the "static" strings. These strings were before constants in different classes
*/
public class MainApp extends MultiDexApplication implements
HasActivityInjector,
@@ -161,6 +161,8 @@ public class MainApp extends MultiDexApplication implements
@Inject
ConnectivityService connectivityService;
+ @Inject PowerManagementService powerManagementService;
+
private PassCodeManager passCodeManager;
@SuppressWarnings("unused")
@@ -202,7 +204,8 @@ public class MainApp extends MultiDexApplication implements
accountManager,
preferences,
uploadsStorageManager,
- connectivityService
+ connectivityService,
+ powerManagementService
)
);
@@ -235,22 +238,22 @@ public class MainApp extends MultiDexApplication implements
}
}
- initSyncOperations(uploadsStorageManager, accountManager, connectivityService);
+ initSyncOperations(uploadsStorageManager, accountManager, connectivityService, powerManagementService);
initContactsBackup(accountManager);
notificationChannels();
new JobRequest.Builder(MediaFoldersDetectionJob.TAG)
- .setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
- .setUpdateCurrent(true)
- .build()
- .schedule();
+ .setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
+ .setUpdateCurrent(true)
+ .build()
+ .schedule();
new JobRequest.Builder(MediaFoldersDetectionJob.TAG)
- .startNow()
- .setUpdateCurrent(false)
- .build()
- .schedule();
+ .startNow()
+ .setUpdateCurrent(false)
+ .build()
+ .schedule();
// register global protection with pass code
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@@ -324,7 +327,7 @@ public class MainApp extends MultiDexApplication implements
boolean set = false;
for (StoragePoint storagePoint : storagePoints) {
if (storagePoint.getStorageType() == StoragePoint.StorageType.INTERNAL &&
- storagePoint.getPrivacyType() == StoragePoint.PrivacyType.PUBLIC) {
+ storagePoint.getPrivacyType() == StoragePoint.PrivacyType.PUBLIC) {
preferences.setStoragePath(storagePoint.getPath());
preferences.removeKeysMigrationPreference();
set = true;
@@ -362,7 +365,8 @@ public class MainApp extends MultiDexApplication implements
public static void initSyncOperations(
final UploadsStorageManager uploadsStorageManager,
final UserAccountManager accountManager,
- final ConnectivityService connectivityService
+ final ConnectivityService connectivityService,
+ final PowerManagementService powerManagementService
) {
updateToAutoUpload();
cleanOldEntries();
@@ -370,7 +374,7 @@ public class MainApp extends MultiDexApplication implements
if (getAppContext() != null) {
if (PermissionUtil.checkSelfPermission(getAppContext(),
- Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
splitOutAutoUploadEntries();
} else {
AppPreferences preferences = AppPreferencesImpl.fromContext(getAppContext());
@@ -381,17 +385,30 @@ public class MainApp extends MultiDexApplication implements
initiateExistingAutoUploadEntries();
FilesSyncHelper.scheduleFilesSyncIfNeeded(mContext);
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, accountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(
+ uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
FilesSyncHelper.scheduleOfflineSyncIfNeeded();
- ReceiversHelper.registerNetworkChangeReceiver(uploadsStorageManager, accountManager, connectivityService);
+ ReceiversHelper.registerNetworkChangeReceiver(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- ReceiversHelper.registerPowerChangeReceiver(uploadsStorageManager, accountManager, connectivityService);
+ ReceiversHelper.registerPowerChangeReceiver(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- ReceiversHelper.registerPowerSaveReceiver(uploadsStorageManager, accountManager, connectivityService);
+ ReceiversHelper.registerPowerSaveReceiver(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
}
}
@@ -399,36 +416,36 @@ public class MainApp extends MultiDexApplication implements
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O && getAppContext() != null) {
Context context = getAppContext();
NotificationManager notificationManager = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_DOWNLOAD,
- R.string.notification_channel_download_name,
- R.string.notification_channel_download_description, context);
+ R.string.notification_channel_download_name,
+ R.string.notification_channel_download_description, context);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD,
- R.string.notification_channel_upload_name,
- R.string.notification_channel_upload_description, context);
+ R.string.notification_channel_upload_name,
+ R.string.notification_channel_upload_description, context);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_MEDIA,
- R.string.notification_channel_media_name,
- R.string.notification_channel_media_description, context);
+ R.string.notification_channel_media_name,
+ R.string.notification_channel_media_description, context);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_FILE_SYNC,
- R.string.notification_channel_file_sync_name,
- R.string.notification_channel_file_sync_description, context);
+ R.string.notification_channel_file_sync_name,
+ R.string.notification_channel_file_sync_description, context);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_FILE_OBSERVER,
- R.string.notification_channel_file_observer_name, R.string
- .notification_channel_file_observer_description, context);
+ R.string.notification_channel_file_observer_name, R.string
+ .notification_channel_file_observer_description, context);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_PUSH,
- R.string.notification_channel_push_name, R.string
- .notification_channel_push_description, context, NotificationManager.IMPORTANCE_DEFAULT);
+ R.string.notification_channel_push_name, R.string
+ .notification_channel_push_description, context, NotificationManager.IMPORTANCE_DEFAULT);
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_GENERAL, R.string
- .notification_channel_general_name, R.string.notification_channel_general_description,
- context, NotificationManager.IMPORTANCE_DEFAULT);
+ .notification_channel_general_name, R.string.notification_channel_general_description,
+ context, NotificationManager.IMPORTANCE_DEFAULT);
} else {
Log_OC.e(TAG, "Notification manager is null");
}
@@ -440,15 +457,15 @@ public class MainApp extends MultiDexApplication implements
String channelId, int channelName,
int channelDescription, Context context) {
createChannel(notificationManager, channelId, channelName, channelDescription, context,
- NotificationManager.IMPORTANCE_LOW);
+ NotificationManager.IMPORTANCE_LOW);
}
private static void createChannel(NotificationManager notificationManager,
String channelId, int channelName,
int channelDescription, Context context, int importance) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O
- && getAppContext() != null
- && notificationManager.getNotificationChannel(channelId) == null) {
+ && getAppContext() != null
+ && notificationManager.getNotificationChannel(channelId) == null) {
CharSequence name = context.getString(channelName);
String description = context.getString(channelDescription);
NotificationChannel channel = new NotificationChannel(channelId, name, importance);
@@ -547,29 +564,29 @@ public class MainApp extends MultiDexApplication implements
}
private static void updateToAutoUpload() {
- Context context = getAppContext();
- AppPreferences preferences = AppPreferencesImpl.fromContext(context);
- if (preferences.instantPictureUploadEnabled() || preferences.instantVideoUploadEnabled()){
- preferences.removeLegacyPreferences();
+ Context context = getAppContext();
+ AppPreferences preferences = AppPreferencesImpl.fromContext(context);
+ if (preferences.instantPictureUploadEnabled() || preferences.instantVideoUploadEnabled()) {
+ preferences.removeLegacyPreferences();
- // show info pop-up
- try {
- new AlertDialog.Builder(context, R.style.Theme_ownCloud_Dialog)
- .setTitle(R.string.drawer_synced_folders)
- .setMessage(R.string.synced_folders_new_info)
- .setPositiveButton(R.string.drawer_open, (dialog, which) -> {
- // show Auto Upload
- Intent folderSyncIntent = new Intent(context, SyncedFoldersActivity.class);
- dialog.dismiss();
- context.startActivity(folderSyncIntent);
- })
- .setNegativeButton(R.string.drawer_close, (dialog, which) -> dialog.dismiss())
- .setIcon(R.drawable.nav_synced_folders)
- .show();
- } catch (WindowManager.BadTokenException e) {
- Log_OC.i(TAG, "Error showing Auto Upload Update dialog, so skipping it: " + e.getMessage());
- }
+ // show info pop-up
+ try {
+ new AlertDialog.Builder(context, R.style.Theme_ownCloud_Dialog)
+ .setTitle(R.string.drawer_synced_folders)
+ .setMessage(R.string.synced_folders_new_info)
+ .setPositiveButton(R.string.drawer_open, (dialog, which) -> {
+ // show Auto Upload
+ Intent folderSyncIntent = new Intent(context, SyncedFoldersActivity.class);
+ dialog.dismiss();
+ context.startActivity(folderSyncIntent);
+ })
+ .setNegativeButton(R.string.drawer_close, (dialog, which) -> dialog.dismiss())
+ .setIcon(R.drawable.nav_synced_folders)
+ .show();
+ } catch (WindowManager.BadTokenException e) {
+ Log_OC.i(TAG, "Error showing Auto Upload Update dialog, so skipping it: " + e.getMessage());
}
+ }
}
private static void updateAutoUploadEntries() {
@@ -578,7 +595,7 @@ public class MainApp extends MultiDexApplication implements
AppPreferences preferences = AppPreferencesImpl.fromContext(context);
if (!preferences.isAutoUploadPathsUpdateEnabled()) {
SyncedFolderProvider syncedFolderProvider =
- new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences);
+ new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences);
syncedFolderProvider.updateAutoUploadPaths(mContext);
}
}
@@ -604,7 +621,7 @@ public class MainApp extends MultiDexApplication implements
for (SyncedFolder syncedFolder : syncedFolders) {
idsToDelete.add(syncedFolder.getId());
Log_OC.i(TAG, "Migration check for synced_folders record: "
- + syncedFolder.getId() + " - " + syncedFolder.getLocalPath());
+ + syncedFolder.getId() + " - " + syncedFolder.getLocalPath());
for (MediaFolder imageMediaFolder : imageMediaFolders) {
if (imageMediaFolder.absolutePath.equals(syncedFolder.getLocalPath())) {
@@ -612,7 +629,7 @@ public class MainApp extends MultiDexApplication implements
newSyncedFolder.setType(MediaFolderType.IMAGE);
primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
Log_OC.i(TAG, "Migrated image synced_folders record: "
- + primaryKey + " - " + newSyncedFolder.getLocalPath());
+ + primaryKey + " - " + newSyncedFolder.getLocalPath());
break;
}
}
@@ -623,7 +640,7 @@ public class MainApp extends MultiDexApplication implements
newSyncedFolder.setType(MediaFolderType.VIDEO);
primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
Log_OC.i(TAG, "Migrated video synced_folders record: "
- + primaryKey + " - " + newSyncedFolder.getLocalPath());
+ + primaryKey + " - " + newSyncedFolder.getLocalPath());
break;
}
}
@@ -643,7 +660,7 @@ public class MainApp extends MultiDexApplication implements
AppPreferences preferences = AppPreferencesImpl.fromContext(getAppContext());
if (!preferences.isAutoUploadInitialized()) {
SyncedFolderProvider syncedFolderProvider =
- new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences);
+ new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences);
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled()) {
@@ -666,7 +683,7 @@ public class MainApp extends MultiDexApplication implements
if (!preferences.isLegacyClean()) {
SyncedFolderProvider syncedFolderProvider =
- new SyncedFolderProvider(context.getContentResolver(), preferences);
+ new SyncedFolderProvider(context.getContentResolver(), preferences);
List syncedFolderList = syncedFolderProvider.getSyncedFolders();
Map, Long> syncedFolders = new HashMap<>();
@@ -686,7 +703,7 @@ public class MainApp extends MultiDexApplication implements
if (ids.size() > 0) {
int deletedCount = syncedFolderProvider.deleteSyncedFoldersNotInList(ids);
- if(deletedCount > 0) {
+ if (deletedCount > 0) {
preferences.setLegacyClean(true);
}
} else {
diff --git a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java
index d44f13fe73..42998ed986 100644
--- a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java
+++ b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.UploadsStorageManager;
@@ -49,6 +50,7 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
@Inject UserAccountManager accountManager;
@Inject UploadsStorageManager uploadsStorageManager;
@Inject ConnectivityService connectivityService;
+ @Inject PowerManagementService powerManagementService;
/**
* Receives broadcast intent reporting that the system was just boot up.
@@ -61,7 +63,10 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
AndroidInjection.inject(this, context);
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- MainApp.initSyncOperations(uploadsStorageManager, accountManager, connectivityService);
+ MainApp.initSyncOperations(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
MainApp.initContactsBackup(accountManager);
} else {
Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction());
diff --git a/src/main/java/com/owncloud/android/files/services/FileUploader.java b/src/main/java/com/owncloud/android/files/services/FileUploader.java
index 7ae1dd1ca3..a3528a8170 100644
--- a/src/main/java/com/owncloud/android/files/services/FileUploader.java
+++ b/src/main/java/com/owncloud/android/files/services/FileUploader.java
@@ -49,10 +49,10 @@ import android.util.Pair;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
-import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
@@ -74,7 +74,6 @@ import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.UploadListActivity;
import com.owncloud.android.ui.notifications.NotificationUtils;
import com.owncloud.android.utils.ErrorMessageAdapter;
-import com.owncloud.android.utils.PowerUtils;
import com.owncloud.android.utils.ThemeUtils;
import org.jetbrains.annotations.NotNull;
@@ -186,6 +185,7 @@ public class FileUploader extends Service
//since there can be only one instance of an Android service, there also just one db connection.
@Inject UploadsStorageManager mUploadsStorageManager;
@Inject ConnectivityService connectivityService;
+ @Inject PowerManagementService powerManagementService;
private IndexedForest mPendingUploads = new IndexedForest<>();
@@ -399,6 +399,7 @@ public class FileUploader extends Service
@NotNull final UploadsStorageManager uploadsStorageManager,
@NotNull final ConnectivityService connectivityService,
@NotNull final UserAccountManager accountManager,
+ @NotNull final PowerManagementService powerManagementService,
@Nullable final UploadResult uploadResult
) {
OCUpload[] failedUploads = uploadsStorageManager.getFailedUploads();
@@ -410,7 +411,7 @@ public class FileUploader extends Service
!connectivityService.isInternetWalled();
boolean gotWifi = gotNetwork && Device.getNetworkType(context).equals(JobRequest.NetworkType.UNMETERED);
boolean charging = Device.getBatteryStatus(context).isCharging();
- boolean isPowerSaving = PowerUtils.isPowerSaveMode(context);
+ boolean isPowerSaving = powerManagementService.isPowerSavingEnabled();
for ( OCUpload failedUpload: failedUploads) {
accountMatch = account == null || account.name.equals(failedUpload.getAccountName());
@@ -641,6 +642,7 @@ public class FileUploader extends Service
newUpload = new UploadFileOperation(
mUploadsStorageManager,
connectivityService,
+ powerManagementService,
account,
file,
ocUpload,
@@ -701,6 +703,7 @@ public class FileUploader extends Service
UploadFileOperation newUpload = new UploadFileOperation(
mUploadsStorageManager,
connectivityService,
+ powerManagementService,
account,
null,
upload,
@@ -986,7 +989,7 @@ public class FileUploader extends Service
cancel(mCurrentUpload.getAccount().name, mCurrentUpload.getFile().getRemotePath()
, ResultCode.DELAYED_FOR_CHARGING);
} else if (!mCurrentUpload.isIgnoringPowerSaveMode() &&
- PowerUtils.isPowerSaveMode(MainApp.getAppContext())) {
+ powerManagementService.isPowerSavingEnabled()) {
cancel(mCurrentUpload.getAccount().name, mCurrentUpload.getFile().getRemotePath()
, ResultCode.DELAYED_IN_POWER_SAVE_MODE);
}
diff --git a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java
index 1584de75ca..97b5b1716c 100644
--- a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java
+++ b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java
@@ -34,6 +34,7 @@ import android.text.TextUtils;
import com.evernote.android.job.Job;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp;
@@ -52,7 +53,6 @@ import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.MimeType;
import com.owncloud.android.utils.MimeTypeUtil;
-import com.owncloud.android.utils.PowerUtils;
import java.io.File;
import java.text.ParsePosition;
@@ -74,7 +74,7 @@ import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
*/
public class FilesSyncJob extends Job {
public static final String TAG = "FilesSyncJob";
- public static final String SKIP_CUSTOM = "skipCustom";
+ static final String SKIP_CUSTOM = "skipCustom";
public static final String OVERRIDE_POWER_SAVING = "overridePowerSaving";
private static final String WAKELOCK_TAG_SEPARATION = ":";
@@ -82,17 +82,18 @@ public class FilesSyncJob extends Job {
private AppPreferences preferences;
private UploadsStorageManager uploadsStorageManager;
private ConnectivityService connectivityService;
+ private PowerManagementService powerManagementService;
- public FilesSyncJob(
- final UserAccountManager userAccountManager,
- final AppPreferences preferences,
- final UploadsStorageManager uploadsStorageManager,
- final ConnectivityService connectivityService
- ) {
+ FilesSyncJob(final UserAccountManager userAccountManager,
+ final AppPreferences preferences,
+ final UploadsStorageManager uploadsStorageManager,
+ final ConnectivityService connectivityService,
+ final PowerManagementService powerManagementService) {
this.userAccountManager = userAccountManager;
this.preferences = preferences;
this.uploadsStorageManager = uploadsStorageManager;
this.connectivityService = connectivityService;
+ this.powerManagementService = powerManagementService;
}
@NonNull
@@ -112,8 +113,10 @@ public class FilesSyncJob extends Job {
final boolean overridePowerSaving = bundle.getBoolean(OVERRIDE_POWER_SAVING, false);
// If we are in power save mode, better to postpone upload
- if (PowerUtils.isPowerSaveMode(context) && !overridePowerSaving) {
- wakeLock.release();
+ if (powerManagementService.isPowerSavingEnabled() && !overridePowerSaving) {
+ if (wakeLock != null) {
+ wakeLock.release();
+ }
return Result.SUCCESS;
}
@@ -121,7 +124,10 @@ public class FilesSyncJob extends Job {
boolean lightVersion = resources.getBoolean(R.bool.syncedFolder_light);
final boolean skipCustom = bundle.getBoolean(SKIP_CUSTOM, false);
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, userAccountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ userAccountManager,
+ connectivityService,
+ powerManagementService);
FilesSyncHelper.insertAllDBEntries(preferences, skipCustom);
// Create all the providers we'll need
diff --git a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java
index f670b3c001..c0894a59e1 100644
--- a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java
+++ b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java
@@ -29,6 +29,7 @@ import android.content.Context;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobCreator;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.datamodel.UploadsStorageManager;
@@ -46,19 +47,22 @@ public class NCJobCreator implements JobCreator {
private final AppPreferences preferences;
private final UploadsStorageManager uploadsStorageManager;
private final ConnectivityService connectivityService;
+ private final PowerManagementService powerManagementService;
public NCJobCreator(
Context context,
UserAccountManager accountManager,
AppPreferences preferences,
UploadsStorageManager uploadsStorageManager,
- ConnectivityService connectivityServices
+ ConnectivityService connectivityServices,
+ PowerManagementService powerManagementService
) {
this.context = context;
this.accountManager = accountManager;
this.preferences = preferences;
this.uploadsStorageManager = uploadsStorageManager;
this.connectivityService = connectivityServices;
+ this.powerManagementService = powerManagementService;
}
@Override
@@ -71,9 +75,13 @@ public class NCJobCreator implements JobCreator {
case AccountRemovalJob.TAG:
return new AccountRemovalJob(uploadsStorageManager, accountManager);
case FilesSyncJob.TAG:
- return new FilesSyncJob(accountManager, preferences, uploadsStorageManager, connectivityService);
+ return new FilesSyncJob(accountManager,
+ preferences,
+ uploadsStorageManager,
+ connectivityService,
+ powerManagementService);
case OfflineSyncJob.TAG:
- return new OfflineSyncJob(accountManager, connectivityService);
+ return new OfflineSyncJob(accountManager, connectivityService, powerManagementService);
case NotificationJob.TAG:
return new NotificationJob(context, accountManager);
case MediaFoldersDetectionJob.TAG:
diff --git a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java
index cc3a59eb1d..fde69fb6e9 100644
--- a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java
+++ b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java
@@ -27,12 +27,15 @@ import android.os.Build;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
-import com.nextcloud.client.preferences.AppPreferencesImpl;
+import com.nextcloud.client.device.PowerManagementService;
+import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.utils.FilesSyncHelper;
-import com.owncloud.android.utils.PowerUtils;
+
+import javax.inject.Inject;
import androidx.annotation.RequiresApi;
+import dagger.android.AndroidInjection;
/*
Job that triggers new FilesSyncJob in case new photo or video were detected
@@ -40,6 +43,16 @@ import androidx.annotation.RequiresApi;
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class NContentObserverJob extends JobService {
+
+ @Inject PowerManagementService powerManagementService;
+ @Inject AppPreferences preferences;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ AndroidInjection.inject(this);
+ }
+
@Override
public boolean onStartJob(JobParameters params) {
@@ -65,9 +78,8 @@ public class NContentObserverJob extends JobService {
}
private void checkAndStartFileSyncJob() {
- if (!PowerUtils.isPowerSaveMode(getApplicationContext()) &&
- new SyncedFolderProvider(getContentResolver(),
- AppPreferencesImpl.fromContext(getApplicationContext())).countEnabledSyncedFolders() > 0) {
+ if (!powerManagementService.isPowerSavingEnabled() &&
+ new SyncedFolderProvider(getContentResolver(), preferences).countEnabledSyncedFolders() > 0) {
PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat();
persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true);
diff --git a/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java b/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java
index 058ff6a24b..6030fad70d 100644
--- a/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java
+++ b/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java
@@ -30,6 +30,7 @@ import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -39,7 +40,6 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.CheckEtagRemoteOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.PowerUtils;
import java.io.File;
import java.util.Set;
@@ -55,10 +55,12 @@ public class OfflineSyncJob extends Job {
private static final String WAKELOCK_TAG_SEPARATION = ":";
private final UserAccountManager userAccountManager;
private final ConnectivityService connectivityService;
+ private final PowerManagementService powerManagementService;
- public OfflineSyncJob(UserAccountManager userAccountManager, ConnectivityService connectivityService) {
+ OfflineSyncJob(UserAccountManager userAccountManager, ConnectivityService connectivityService, PowerManagementService powerManagementService) {
this.userAccountManager = userAccountManager;
this.connectivityService = connectivityService;
+ this.powerManagementService = powerManagementService;
}
@NonNull
@@ -67,7 +69,7 @@ public class OfflineSyncJob extends Job {
final Context context = getContext();
PowerManager.WakeLock wakeLock = null;
- if (!PowerUtils.isPowerSaveMode(context) &&
+ if (!powerManagementService.isPowerSavingEnabled() &&
connectivityService.getActiveNetworkType() == JobRequest.NetworkType.UNMETERED &&
!connectivityService.isInternetWalled()) {
Set jobs = JobManager.instance().getAllJobsForTag(TAG);
diff --git a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
index 639b9dfc14..1065837b54 100644
--- a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
+++ b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
@@ -32,6 +32,7 @@ import android.util.Log;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.google.gson.reflect.TypeToken;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.DecryptedFolderMetadata;
@@ -65,7 +66,6 @@ import com.owncloud.android.utils.EncryptionUtils;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.MimeType;
import com.owncloud.android.utils.MimeTypeUtil;
-import com.owncloud.android.utils.PowerUtils;
import com.owncloud.android.utils.UriUtils;
import org.apache.commons.httpclient.HttpStatus;
@@ -147,6 +147,7 @@ public class UploadFileOperation extends SyncOperation {
final private OCUpload mUpload;
final private UploadsStorageManager uploadsStorageManager;
final private ConnectivityService connectivityService;
+ final private PowerManagementService powerManagementService;
private boolean encryptedAncestor;
@@ -178,6 +179,7 @@ public class UploadFileOperation extends SyncOperation {
public UploadFileOperation(UploadsStorageManager uploadsStorageManager,
ConnectivityService connectivityService,
+ PowerManagementService powerManagementService,
Account account,
OCFile file,
OCUpload upload,
@@ -201,6 +203,7 @@ public class UploadFileOperation extends SyncOperation {
this.uploadsStorageManager = uploadsStorageManager;
this.connectivityService = connectivityService;
+ this.powerManagementService = powerManagementService;
mAccount = account;
mUpload = upload;
if (file == null) {
@@ -742,7 +745,7 @@ public class UploadFileOperation extends SyncOperation {
}
// check that device is not in power save mode
- if (!mIgnoringPowerSaveMode && PowerUtils.isPowerSaveMode(mContext)) {
+ if (!mIgnoringPowerSaveMode && powerManagementService.isPowerSavingEnabled()) {
Log_OC.d(TAG, "Upload delayed because device is in power save mode: " + getRemotePath());
remoteOperationResult = new RemoteOperationResult(ResultCode.DELAYED_IN_POWER_SAVE_MODE);
}
diff --git a/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java b/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java
index 79e40a599a..e38ce14a5a 100755
--- a/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java
@@ -45,6 +45,7 @@ import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.UploadsStorageManager;
@@ -117,6 +118,9 @@ public class UploadListActivity extends FileActivity {
@Inject
ConnectivityService connectivityService;
+ @Inject
+ PowerManagementService powerManagementService;
+
@Override
public void showFiles(boolean onDeviceOnly) {
super.showFiles(onDeviceOnly);
@@ -180,7 +184,8 @@ public class UploadListActivity extends FileActivity {
uploadListAdapter = new UploadListAdapter(this,
uploadsStorageManager,
userAccountManager,
- connectivityService);
+ connectivityService,
+ powerManagementService);
final GridLayoutManager lm = new GridLayoutManager(this, 1);
uploadListAdapter.setLayoutManager(lm);
@@ -229,6 +234,7 @@ public class UploadListActivity extends FileActivity {
uploadsStorageManager,
connectivityService,
userAccountManager,
+ powerManagementService,
null)).start();
// update UI
@@ -301,7 +307,10 @@ public class UploadListActivity extends FileActivity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FileActivity.REQUEST_CODE__UPDATE_CREDENTIALS && resultCode == RESULT_OK) {
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, userAccountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ userAccountManager,
+ connectivityService,
+ powerManagementService);
}
}
@@ -321,7 +330,10 @@ public class UploadListActivity extends FileActivity {
} else {
// already updated -> just retry!
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, userAccountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ userAccountManager,
+ connectivityService,
+ powerManagementService);
}
} else {
diff --git a/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
index 556d9575ed..409437867a 100755
--- a/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
@@ -41,6 +41,7 @@ import android.widget.TextView;
import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter;
import com.afollestad.sectionedrecyclerview.SectionedViewHolder;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
@@ -74,6 +75,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter private constructor
- }
-
- /**
- * Checks if device is in power save mode. For older devices that do not support this API, returns false.
- * @return true if it is, false otherwise.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public static boolean isPowerSaveMode(Context context) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- return powerManager != null && powerManager.isPowerSaveMode();
- }
-
- // For older versions, we just say that device is not in power save mode
- return false;
- }
-}
diff --git a/src/main/java/com/owncloud/android/utils/ReceiversHelper.java b/src/main/java/com/owncloud/android/utils/ReceiversHelper.java
index 30ed3704ea..81eb82a821 100644
--- a/src/main/java/com/owncloud/android/utils/ReceiversHelper.java
+++ b/src/main/java/com/owncloud/android/utils/ReceiversHelper.java
@@ -30,6 +30,7 @@ import android.content.IntentFilter;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.account.UserAccountManager;
+import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.network.ConnectivityService;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.UploadsStorageManager;
@@ -43,11 +44,10 @@ public final class ReceiversHelper {
// utility class -> private constructor
}
- public static void registerNetworkChangeReceiver(
- final UploadsStorageManager uploadsStorageManager,
- final UserAccountManager accountManager,
- final ConnectivityService connectivityService
- ) {
+ public static void registerNetworkChangeReceiver(final UploadsStorageManager uploadsStorageManager,
+ final UserAccountManager accountManager,
+ final ConnectivityService connectivityService,
+ final PowerManagementService powerManagementService) {
Context context = MainApp.getAppContext();
IntentFilter intentFilter = new IntentFilter();
@@ -58,7 +58,10 @@ public final class ReceiversHelper {
@Override
public void onReceive(Context context, Intent intent) {
if (!Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, accountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
}
}
};
@@ -69,7 +72,8 @@ public final class ReceiversHelper {
public static void registerPowerChangeReceiver(
final UploadsStorageManager uploadsStorageManager,
final UserAccountManager accountManager,
- final ConnectivityService connectivityService
+ final ConnectivityService connectivityService,
+ final PowerManagementService powerManagementService
) {
Context context = MainApp.getAppContext();
@@ -81,7 +85,10 @@ public final class ReceiversHelper {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, accountManager, connectivityService);
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
}
}
};
@@ -92,8 +99,9 @@ public final class ReceiversHelper {
public static void registerPowerSaveReceiver(
final UploadsStorageManager uploadsStorageManager,
final UserAccountManager accountManager,
- final ConnectivityService connectivityService
- ) {
+ final ConnectivityService connectivityService,
+ final PowerManagementService powerManagementService
+ ) {
Context context = MainApp.getAppContext();
IntentFilter intentFilter = new IntentFilter();
@@ -102,8 +110,11 @@ public final class ReceiversHelper {
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (!PowerUtils.isPowerSaveMode(context)) {
- FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, accountManager, connectivityService);
+ if (!powerManagementService.isPowerSavingEnabled()) {
+ FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager,
+ accountManager,
+ connectivityService,
+ powerManagementService);
}
}
};
diff --git a/src/test/java/com/owncloud/android/utils/PowerUtilsTest.java b/src/test/java/com/owncloud/android/utils/PowerUtilsTest.java
deleted file mode 100644
index 505766899c..0000000000
--- a/src/test/java/com/owncloud/android/utils/PowerUtilsTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Edvard Holst
- * Copyright (C) 2019 Edvard Holst
- * Copyright (C) 2019 Nextcloud GmbH
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.owncloud.android.utils;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.PowerManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.when;
-
-public class PowerUtilsTest {
-
- @Mock
- private Context mContext;
-
- @Mock
- private PowerManager mPowerManager;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- }
-
- private static void setFinalStatic(Field field, Object newValue) throws Exception {
- field.setAccessible(true);
-
- Field modifiersField = Field.class.getDeclaredField("modifiers");
- modifiersField.setAccessible(true);
- modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
-
- field.set(null, newValue);
- }
-
- @Test
- public void isPowerSaveMode_assertCorrectlyReportsTrue() throws Exception {
- setFinalStatic(Build.VERSION.class.getField("SDK_INT"), Build.VERSION_CODES.O);
- when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
- when(mPowerManager.isPowerSaveMode()).thenReturn(true);
- assertTrue("Incorrectly reported power saving mode on",
- PowerUtils.isPowerSaveMode(mContext));
- }
-
- @Test
- public void isPowerSaveMode_assertCorrectlyReportsFalse() throws Exception {
- setFinalStatic(Build.VERSION.class.getField("SDK_INT"), Build.VERSION_CODES.O);
- when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
- when(mPowerManager.isPowerSaveMode()).thenReturn(false);
- assertFalse("Incorrectly reported power saving mode off",
- PowerUtils.isPowerSaveMode(mContext));
- }
-}