mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 15:15:51 +03:00
Check if app is excluded from battery optimization (#3589)
Check if app is excluded from battery optimization
This commit is contained in:
commit
9a023c6496
11 changed files with 109 additions and 13 deletions
|
@ -1 +1 @@
|
|||
413
|
||||
412
|
|
@ -2,8 +2,11 @@
|
|||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* @author Tobias Kaminsky
|
||||
*
|
||||
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2019 Tobias Kaminsky
|
||||
* 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
|
||||
|
@ -23,6 +26,7 @@ package com.nextcloud.client.device
|
|||
|
||||
import android.content.Context
|
||||
import android.os.PowerManager
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
|
@ -30,12 +34,13 @@ import dagger.Provides
|
|||
class DeviceModule {
|
||||
|
||||
@Provides
|
||||
fun powerManagementService(context: Context): PowerManagementService {
|
||||
fun powerManagementService(context: Context, preferences: AppPreferences): PowerManagementService {
|
||||
val platformPowerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
return PowerManagementServiceImpl(
|
||||
context = context,
|
||||
powerManager = platformPowerManager,
|
||||
deviceInfo = DeviceInfo()
|
||||
deviceInfo = DeviceInfo(),
|
||||
preferences = preferences
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,13 @@ import android.content.IntentFilter
|
|||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.nextcloud.client.preferences.AppPreferencesImpl
|
||||
|
||||
internal class PowerManagementServiceImpl(
|
||||
private val context: Context,
|
||||
private val powerManager: PowerManager,
|
||||
private val preferences: AppPreferences,
|
||||
private val deviceInfo: DeviceInfo = DeviceInfo()
|
||||
) : PowerManagementService {
|
||||
|
||||
|
@ -41,10 +44,22 @@ internal class PowerManagementServiceImpl(
|
|||
* break application experience.
|
||||
*/
|
||||
val OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS = setOf("samsung", "huawei", "xiaomi")
|
||||
|
||||
@JvmStatic
|
||||
fun fromContext(context: Context): PowerManagementServiceImpl {
|
||||
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
val preferences = AppPreferencesImpl.fromContext(context)
|
||||
|
||||
return PowerManagementServiceImpl(context, powerManager, preferences, DeviceInfo())
|
||||
}
|
||||
}
|
||||
|
||||
override val isPowerSavingEnabled: Boolean
|
||||
get() {
|
||||
if (preferences.isPowerCheckDisabled) {
|
||||
return false
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return powerManager.isPowerSaveMode
|
||||
|
|
|
@ -29,6 +29,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.UsersAndGroupsSearchProvider;
|
||||
|
@ -154,4 +155,6 @@ abstract class ComponentsModule {
|
|||
|
||||
@ContributesAndroidInjector abstract AccountManagerService accountManagerService();
|
||||
@ContributesAndroidInjector abstract OperationsService operationsService();
|
||||
|
||||
@ContributesAndroidInjector abstract NContentObserverJob nContentObserverJob();
|
||||
}
|
||||
|
|
|
@ -296,4 +296,8 @@ public interface AppPreferences {
|
|||
void setPhotoSearchTimestamp(long timestamp);
|
||||
|
||||
long getPhotoSearchTimestamp();
|
||||
|
||||
boolean isPowerCheckDisabled();
|
||||
|
||||
void setPowerCheckDisabled(boolean value);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ public final class AppPreferencesImpl implements AppPreferences {
|
|||
private static final String PREF__SELECTED_ACCOUNT_NAME = "select_oc_account";
|
||||
private static final String PREF__MIGRATED_USER_ID = "migrated_user_id";
|
||||
private static final String PREF__PHOTO_SEARCH_TIMESTAMP = "photo_search_timestamp";
|
||||
private static final String PREF__POWER_CHECK_DISABLED = "power_check_disabled";
|
||||
|
||||
private final Context context;
|
||||
private final SharedPreferences preferences;
|
||||
|
@ -534,4 +535,14 @@ public final class AppPreferencesImpl implements AppPreferences {
|
|||
|
||||
return preferenceName + "_" + folderIdString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowerCheckDisabled() {
|
||||
return preferences.getBoolean(PREF__POWER_CHECK_DISABLED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPowerCheckDisabled(boolean value) {
|
||||
preferences.edit().putBoolean(PREF__POWER_CHECK_DISABLED, value).apply();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import dagger.android.AndroidInjection;
|
|||
|
||||
|
||||
/**
|
||||
* App-registered receiver catching the broadcast intent reporting that the system was
|
||||
* App-registered receiver catching the broadcast intent reporting that the system was
|
||||
* just boot up.
|
||||
*/
|
||||
public class BootupBroadcastReceiver extends BroadcastReceiver {
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.view.View;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nextcloud.client.device.PowerManagementService;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.nextcloud.client.preferences.AppPreferences;
|
||||
import com.owncloud.android.BuildConfig;
|
||||
|
@ -96,7 +97,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
|
|||
SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener, Injectable {
|
||||
|
||||
private static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"};
|
||||
private static final List<String> SPECIAL_MANUFACTURER = Arrays.asList("Samsung", "Huawei", "Xiaomi");
|
||||
public static final String EXTRA_SHOW_SIDEBAR = "SHOW_SIDEBAR";
|
||||
private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG";
|
||||
private static final String TAG = SyncedFoldersActivity.class.getSimpleName();
|
||||
|
@ -112,6 +112,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
|
|||
private String path;
|
||||
private int type;
|
||||
@Inject AppPreferences preferences;
|
||||
@Inject PowerManagementService powerManagementService;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -175,9 +176,42 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
|
|||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.synced_folders_menu, menu);
|
||||
|
||||
if (powerManagementService.isPowerSavingExclusionAvailable()) {
|
||||
MenuItem item = menu.findItem(R.id.action_disable_power_save_check);
|
||||
item.setVisible(true);
|
||||
|
||||
item.setChecked(preferences.isPowerCheckDisabled());
|
||||
|
||||
item.setOnMenuItemClickListener(this::onDisablePowerSaveCheckClicked);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onDisablePowerSaveCheckClicked(MenuItem powerCheck) {
|
||||
if (!powerCheck.isChecked()) {
|
||||
showPowerCheckDialog();
|
||||
}
|
||||
|
||||
preferences.setPowerCheckDisabled(!powerCheck.isChecked());
|
||||
powerCheck.setChecked(!powerCheck.isChecked());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showPowerCheckDialog() {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(this)
|
||||
.setView(findViewById(R.id.root_layout))
|
||||
.setPositiveButton(R.string.common_ok, (dialog, which) -> dialog.dismiss())
|
||||
.setTitle(ThemeUtils.getColoredTitle(getResources().getString(R.string.autoupload_disable_power_save_check),
|
||||
ThemeUtils.primaryAccentColor(this)))
|
||||
.setMessage(getString(R.string.power_save_check_dialog_message))
|
||||
.show();
|
||||
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ThemeUtils.primaryAccentColor(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up the UI elements and loads all media/synced folders.
|
||||
*/
|
||||
|
@ -691,10 +725,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
|
|||
}
|
||||
|
||||
private void showBatteryOptimizationInfo() {
|
||||
|
||||
boolean isSpecialManufacturer = SPECIAL_MANUFACTURER.contains(Build.MANUFACTURER.toLowerCase(Locale.ROOT));
|
||||
|
||||
if (isSpecialManufacturer && checkIfBatteryOptimizationEnabled() || checkIfBatteryOptimizationEnabled()) {
|
||||
if (powerManagementService.isPowerSavingExclusionAvailable() || checkIfBatteryOptimizationEnabled()) {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(this, R.style.Theme_ownCloud_Dialog)
|
||||
.setTitle(getString(R.string.battery_optimization_title))
|
||||
.setMessage(getString(R.string.battery_optimization_message))
|
||||
|
|
|
@ -25,5 +25,11 @@
|
|||
<item
|
||||
android:id="@+id/action_create_custom_folder"
|
||||
android:title="@string/autoupload_custom_folder"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_disable_power_save_check"
|
||||
android:title="@string/autoupload_disable_power_save_check"
|
||||
android:visible="false"
|
||||
android:checkable="true" />
|
||||
</group>
|
||||
</menu>
|
||||
|
|
|
@ -884,7 +884,8 @@
|
|||
<string name="copy_internal_link">Copy internal link</string>
|
||||
<string name="copy_internal_link_subline">Only works for users with access to this folder</string>
|
||||
<string name="failed_to_download">Failed to pass file to download manager</string>
|
||||
|
||||
<string name="autoupload_disable_power_save_check">Disable power save check</string>
|
||||
<string name="power_save_check_dialog_message">Disabling power save check might result in uploading files when in low battery state!</string>
|
||||
<string name="etm_title">Engineering Test Mode</string>
|
||||
<string name="etm_preferences">Preferences</string>
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.content.Intent
|
|||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.nhaarman.mockitokotlin2.any
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.eq
|
||||
|
@ -61,13 +62,17 @@ class TestPowerManagementService {
|
|||
|
||||
internal lateinit var powerManagementService: PowerManagementServiceImpl
|
||||
|
||||
@Mock
|
||||
lateinit var preferences: AppPreferences
|
||||
|
||||
@Before
|
||||
fun setUpBase() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
powerManagementService = PowerManagementServiceImpl(
|
||||
context = context,
|
||||
powerManager = platformPowerManager,
|
||||
deviceInfo = deviceInfo
|
||||
context,
|
||||
platformPowerManager,
|
||||
preferences,
|
||||
deviceInfo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +125,21 @@ class TestPowerManagementService {
|
|||
whenever(deviceInfo.vendor).thenReturn("some_other_nice_vendor")
|
||||
assertFalse(powerManagementService.isPowerSavingExclusionAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `power saving check is disabled`() {
|
||||
// GIVEN
|
||||
// a device which falsely returns power save mode enabled
|
||||
// power check is overridden by user
|
||||
whenever(preferences.isPowerCheckDisabled).thenReturn(true)
|
||||
whenever(platformPowerManager.isPowerSaveMode).thenReturn(true)
|
||||
|
||||
// WHEN
|
||||
// power save mode is checked
|
||||
// THEN
|
||||
// power saving is disabled
|
||||
assertFalse(powerManagementService.isPowerSavingEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
class BatteryCharging : Base() {
|
||||
|
|
Loading…
Reference in a new issue