Browse Source

add battery optimization warning

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 6 years ago
parent
commit
cb1bff1ce0

+ 5 - 0
drawable_resources/battery_alert.svg

@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M0 0h24v24H0z" fill="none" />
+    <path
+        d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM13 18h-2v-2h2v2zm0-4h-2V9h2v5z" />
+</svg>

+ 1 - 0
src/main/AndroidManifest.xml

@@ -64,6 +64,7 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.USE_FINGERPRINT" />
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
 
     <!-- Apps that target Android 9 (API level 28) or higher and use foreground services
     must request the FOREGROUND_SERVICE permission -->

+ 70 - 0
src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

@@ -22,10 +22,14 @@
 package com.owncloud.android.ui.activity;
 
 import android.accounts.Account;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.PowerManager;
 import android.preference.PreferenceManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -38,6 +42,7 @@ import android.widget.TextView;
 import com.google.android.material.appbar.AppBarLayout;
 import com.google.android.material.appbar.CollapsingToolbarLayout;
 import com.google.android.material.bottomnavigation.BottomNavigationView;
+import com.owncloud.android.BuildConfig;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
@@ -72,12 +77,14 @@ import java.util.Map;
 
 import androidx.annotation.NonNull;
 import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AlertDialog;
 import androidx.drawerlayout.widget.DrawerLayout;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
 import static com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS;
 import static com.owncloud.android.datamodel.SyncedFolderDisplayItem.UNPERSISTED_ID;
 
@@ -88,6 +95,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener {
 
     public static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"};
+    public 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();
@@ -511,6 +519,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
 
         if (syncedFolderDisplayItem.isEnabled()) {
             FilesSyncHelper.insertAllDBEntriesForSyncedFolder(syncedFolderDisplayItem);
+
+            showBatteryOptimizationInfo();
         } else {
             String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + syncedFolderDisplayItem.getId();
             arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey);
@@ -601,6 +611,10 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         }
 
         mSyncedFolderPreferencesDialogFragment = null;
+
+        if (syncedFolder.getEnabled()) {
+            showBatteryOptimizationInfo();
+        }
     }
 
     @Override
@@ -681,4 +695,60 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
 
         setDrawerMenuItemChecked(R.id.nav_synced_folders);
     }
+
+    private void showBatteryOptimizationInfo() {
+
+        boolean isSpecialManufacturer = SPECIAL_MANUFACTURER.contains(Build.MANUFACTURER.toLowerCase());
+
+        if ((isSpecialManufacturer && checkIfBatteryOptimizationEnabled()) || 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))
+                .setPositiveButton(getString(R.string.battery_optimization_disable), (dialog, which) -> {
+                    // show instant upload
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                        Intent intent = new Intent(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
+                                                   Uri.parse("package:" + BuildConfig.APPLICATION_ID));
+
+                        if (intent.resolveActivity(getPackageManager()) != null) {
+                            startActivity(intent);
+                        }
+                    } else {
+                        Intent powerUsageIntent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+                        if (getPackageManager().resolveActivity(powerUsageIntent, 0) != null) {
+                            startActivity(powerUsageIntent);
+                        } else {
+                            dialog.dismiss();
+                            DisplayUtils.showSnackMessage(this, getString(R.string.battery_optimization_no_setting));
+                        }
+                    }
+                })
+                .setNegativeButton(getString(R.string.battery_optimization_close), (dialog, which) -> dialog.dismiss())
+                .setIcon(R.drawable.ic_battery_alert)
+                .show();
+
+            int color = ThemeUtils.primaryAccentColor(this);
+            alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(color);
+            alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(color);
+        }
+    }
+
+    /**
+     * Check if battery optimization is enabled. If unknown, fallback to true.
+     *
+     * @return true if battery optimization is enabled
+     */
+    private boolean checkIfBatteryOptimizationEnabled() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+
+            if (powerManager == null) {
+                return true;
+            }
+
+            return !powerManager.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID);
+        } else {
+            return true;
+        }
+    }
 }

+ 9 - 0
src/main/res/drawable/ic_battery_alert.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15.67,4L14,4L14,2h-4v2L8.33,4C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33L17,5.33C17,4.6 16.4,4 15.67,4zM13,18h-2v-2h2v2zM13,14h-2L11,9h2v5z" />
+</vector>

+ 5 - 0
src/main/res/values/strings.xml

@@ -839,4 +839,9 @@
     <string name="enter_filename">Please enter a filename</string>
     <string name="create_file_from_template">Creating file from template…</string>
     <string name="error_retrieving_templates">Error retrieving templates</string>
+    <string name="battery_optimization_title">Battery optimization</string>
+    <string name="battery_optimization_message">Your device may have battery optimization enabled. AutoUpload works only properly if you exclude this app from it.</string>
+    <string name="battery_optimization_disable">disable</string>
+    <string name="battery_optimization_close">Close</string>
+    <string name="battery_optimization_no_setting">Unable to start battery settings directly. Please adjust manually in settings.</string>
 </resources>