Skip to content

Commit e72a789

Browse files
show on special vendors "disable power check" in auto upload menu
- tint button - change logic when to show battery warning Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
1 parent c8173c3 commit e72a789

File tree

10 files changed

+114
-24
lines changed

10 files changed

+114
-24
lines changed

src/main/java/com/nextcloud/client/device/DeviceModule.kt renamed to src/main/java/com/nextcloud/client/device/DeviceModule.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,22 @@
1919
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2020
*/
2121

22-
package com.nextcloud.client.device
22+
package com.nextcloud.client.device;
2323

24-
import android.content.Context
25-
import android.os.PowerManager
26-
import dagger.Module
27-
import dagger.Provides
24+
import android.content.Context;
25+
import android.os.PowerManager;
2826

29-
@Module
30-
class DeviceModule {
27+
import com.nextcloud.client.preferences.AppPreferences;
28+
29+
import dagger.Module;
30+
import dagger.Provides;
3131

32+
@Module
33+
public class DeviceModule {
3234
@Provides
33-
fun powerManagementService(context: Context): PowerManagementService {
34-
val platformPowerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
35-
return PowerManagementServiceImpl(
36-
context = context,
37-
powerManager = platformPowerManager,
38-
deviceInfo = DeviceInfo()
39-
)
35+
PowerManagementService powerManagementService(Context context, AppPreferences preferences) {
36+
PowerManager platformPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
37+
38+
return new PowerManagementServiceImpl(context, platformPowerManager, preferences, new DeviceInfo());
4039
}
4140
}

src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ import android.content.IntentFilter
2828
import android.os.BatteryManager
2929
import android.os.Build
3030
import android.os.PowerManager
31+
import com.nextcloud.client.preferences.AppPreferences
32+
import com.nextcloud.client.preferences.AppPreferencesImpl
3133

3234
internal class PowerManagementServiceImpl(
3335
private val context: Context,
3436
private val powerManager: PowerManager,
37+
private val preferences: AppPreferences,
3538
private val deviceInfo: DeviceInfo = DeviceInfo()
3639
) : PowerManagementService {
3740

@@ -41,10 +44,22 @@ internal class PowerManagementServiceImpl(
4144
* break application experience.
4245
*/
4346
val OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS = setOf("samsung", "huawei", "xiaomi")
47+
48+
@JvmStatic
49+
fun fromContext(context: Context): PowerManagementServiceImpl {
50+
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
51+
val preferences = AppPreferencesImpl.fromContext(context)
52+
53+
return PowerManagementServiceImpl(context, powerManager, preferences, DeviceInfo())
54+
}
4455
}
4556

4657
override val isPowerSavingEnabled: Boolean
4758
get() {
59+
if (preferences.isPowerCheckDisabled) {
60+
return false
61+
}
62+
4863
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
4964
if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) {
5065
return powerManager.isPowerSaveMode

src/main/java/com/nextcloud/client/di/ComponentsModule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.owncloud.android.files.BootupBroadcastReceiver;
3030
import com.owncloud.android.files.services.FileDownloader;
3131
import com.owncloud.android.files.services.FileUploader;
32+
import com.owncloud.android.jobs.NContentObserverJob;
3233
import com.owncloud.android.jobs.NotificationJob;
3334
import com.owncloud.android.providers.DiskLruImageCacheFileProvider;
3435
import com.owncloud.android.providers.UsersAndGroupsSearchProvider;
@@ -154,4 +155,6 @@ abstract class ComponentsModule {
154155

155156
@ContributesAndroidInjector abstract AccountManagerService accountManagerService();
156157
@ContributesAndroidInjector abstract OperationsService operationsService();
158+
159+
@ContributesAndroidInjector abstract NContentObserverJob nContentObserverJob();
157160
}

src/main/java/com/nextcloud/client/preferences/AppPreferences.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,8 @@ public interface AppPreferences {
296296
void setPhotoSearchTimestamp(long timestamp);
297297

298298
long getPhotoSearchTimestamp();
299+
300+
boolean isPowerCheckDisabled();
301+
302+
void setPowerCheckDisabled(boolean value);
299303
}

src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public final class AppPreferencesImpl implements AppPreferences {
7373
private static final String PREF__SELECTED_ACCOUNT_NAME = "select_oc_account";
7474
private static final String PREF__MIGRATED_USER_ID = "migrated_user_id";
7575
private static final String PREF__PHOTO_SEARCH_TIMESTAMP = "photo_search_timestamp";
76+
private static final String PREF__POWER_CHECK_DISABLED = "power_check_disabled";
7677

7778
private final Context context;
7879
private final SharedPreferences preferences;
@@ -534,4 +535,14 @@ private static String getKeyFromFolder(String preferenceName, OCFile folder) {
534535

535536
return preferenceName + "_" + folderIdString;
536537
}
538+
539+
@Override
540+
public boolean isPowerCheckDisabled() {
541+
return preferences.getBoolean(PREF__POWER_CHECK_DISABLED, false);
542+
}
543+
544+
@Override
545+
public void setPowerCheckDisabled(boolean value) {
546+
preferences.edit().putBoolean(PREF__POWER_CHECK_DISABLED, value).apply();
547+
}
537548
}

src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141

4242
/**
43-
* App-registered receiver catching the broadcast intent reporting that the system was
43+
* App-registered receiver catching the broadcast intent reporting that the system was
4444
* just boot up.
4545
*/
4646
public class BootupBroadcastReceiver extends BroadcastReceiver {

src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import android.widget.LinearLayout;
4242
import android.widget.TextView;
4343

44+
import com.nextcloud.client.device.PowerManagementService;
4445
import com.nextcloud.client.di.Injectable;
4546
import com.nextcloud.client.preferences.AppPreferences;
4647
import com.owncloud.android.BuildConfig;
@@ -96,7 +97,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
9697
SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener, Injectable {
9798

9899
private static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"};
99-
private static final List<String> SPECIAL_MANUFACTURER = Arrays.asList("Samsung", "Huawei", "Xiaomi");
100100
public static final String EXTRA_SHOW_SIDEBAR = "SHOW_SIDEBAR";
101101
private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG";
102102
private static final String TAG = SyncedFoldersActivity.class.getSimpleName();
@@ -112,6 +112,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
112112
private String path;
113113
private int type;
114114
@Inject AppPreferences preferences;
115+
@Inject PowerManagementService powerManagementService;
115116

116117
@Override
117118
protected void onCreate(Bundle savedInstanceState) {
@@ -175,9 +176,42 @@ protected void onCreate(Bundle savedInstanceState) {
175176
public boolean onCreateOptionsMenu(Menu menu) {
176177
MenuInflater inflater = getMenuInflater();
177178
inflater.inflate(R.menu.synced_folders_menu, menu);
179+
180+
if (powerManagementService.isPowerSavingExclusionAvailable()) {
181+
MenuItem item = menu.findItem(R.id.action_disable_power_save_check);
182+
item.setVisible(true);
183+
184+
item.setChecked(preferences.isPowerCheckDisabled());
185+
186+
item.setOnMenuItemClickListener(this::onDisablePowerSaveCheckClicked);
187+
}
188+
189+
return true;
190+
}
191+
192+
private boolean onDisablePowerSaveCheckClicked(MenuItem powerCheck) {
193+
if (!powerCheck.isChecked()) {
194+
showPowerCheckDialog();
195+
}
196+
197+
preferences.setPowerCheckDisabled(!powerCheck.isChecked());
198+
powerCheck.setChecked(!powerCheck.isChecked());
199+
178200
return true;
179201
}
180202

203+
private void showPowerCheckDialog() {
204+
AlertDialog alertDialog = new AlertDialog.Builder(this)
205+
.setView(findViewById(R.id.root_layout))
206+
.setPositiveButton(R.string.common_ok, (dialog, which) -> dialog.dismiss())
207+
.setTitle(ThemeUtils.getColoredTitle(getResources().getString(R.string.autoupload_disable_power_save_check),
208+
ThemeUtils.primaryAccentColor(this)))
209+
.setMessage(getString(R.string.power_save_check_dialog_message))
210+
.show();
211+
212+
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ThemeUtils.primaryAccentColor(this));
213+
}
214+
181215
/**
182216
* sets up the UI elements and loads all media/synced folders.
183217
*/
@@ -691,10 +725,7 @@ protected void onResume() {
691725
}
692726

693727
private void showBatteryOptimizationInfo() {
694-
695-
boolean isSpecialManufacturer = SPECIAL_MANUFACTURER.contains(Build.MANUFACTURER.toLowerCase(Locale.ROOT));
696-
697-
if (isSpecialManufacturer && checkIfBatteryOptimizationEnabled() || checkIfBatteryOptimizationEnabled()) {
728+
if (powerManagementService.isPowerSavingExclusionAvailable() || checkIfBatteryOptimizationEnabled()) {
698729
AlertDialog alertDialog = new AlertDialog.Builder(this, R.style.Theme_ownCloud_Dialog)
699730
.setTitle(getString(R.string.battery_optimization_title))
700731
.setMessage(getString(R.string.battery_optimization_message))

src/main/res/menu/synced_folders_menu.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,11 @@
2525
<item
2626
android:id="@+id/action_create_custom_folder"
2727
android:title="@string/autoupload_custom_folder"/>
28+
29+
<item
30+
android:id="@+id/action_disable_power_save_check"
31+
android:title="@string/autoupload_disable_power_save_check"
32+
android:visible="false"
33+
android:checkable="true" />
2834
</group>
2935
</menu>

src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,8 @@
884884
<string name="copy_internal_link">Copy internal link</string>
885885
<string name="copy_internal_link_subline">Only works for users with access to this folder</string>
886886
<string name="failed_to_download">Failed to pass file to download manager</string>
887-
887+
<string name="autoupload_disable_power_save_check">Disable power save check</string>
888+
<string name="power_save_check_dialog_message">Disabling power save check might result in uploading files when in low battery state!</string>
888889
<string name="etm_title">Engineering Test Mode</string>
889890
<string name="etm_preferences">Preferences</string>
890891

src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import android.content.Intent
2626
import android.os.BatteryManager
2727
import android.os.Build
2828
import android.os.PowerManager
29+
import com.nextcloud.client.preferences.AppPreferences
2930
import com.nhaarman.mockitokotlin2.any
3031
import com.nhaarman.mockitokotlin2.anyOrNull
3132
import com.nhaarman.mockitokotlin2.eq
@@ -61,13 +62,17 @@ class TestPowerManagementService {
6162

6263
internal lateinit var powerManagementService: PowerManagementServiceImpl
6364

65+
@Mock
66+
lateinit var preferences: AppPreferences
67+
6468
@Before
6569
fun setUpBase() {
6670
MockitoAnnotations.initMocks(this)
6771
powerManagementService = PowerManagementServiceImpl(
68-
context = context,
69-
powerManager = platformPowerManager,
70-
deviceInfo = deviceInfo
72+
context,
73+
platformPowerManager,
74+
preferences,
75+
deviceInfo
7176
)
7277
}
7378
}
@@ -120,6 +125,21 @@ class TestPowerManagementService {
120125
whenever(deviceInfo.vendor).thenReturn("some_other_nice_vendor")
121126
assertFalse(powerManagementService.isPowerSavingExclusionAvailable)
122127
}
128+
129+
@Test
130+
fun `power saving check is disabled`() {
131+
// GIVEN
132+
// a device which falsely returns power save mode enabled
133+
// power check is overridden by user
134+
whenever(preferences.isPowerCheckDisabled).thenReturn(true)
135+
whenever(platformPowerManager.isPowerSaveMode).thenReturn(true)
136+
137+
// WHEN
138+
// power save mode is checked
139+
// THEN
140+
// power saving is disabled
141+
assertFalse(powerManagementService.isPowerSavingEnabled)
142+
}
123143
}
124144

125145
class BatteryCharging : Base() {

0 commit comments

Comments
 (0)