commit 41ebcc50507b346e37d7aced4d6d88b49fe174be Author: arrase arrase@gmail.com Date: Thu Dec 8 15:22:53 2016 +0100
Deal with Doze in the less painful way --- app/src/main/AndroidManifest.xml | 1 + .../org/torproject/android/OrbotMainActivity.java | 5 +- .../ui/hiddenservices/ClientCookiesActivity.java | 6 +- .../ui/hiddenservices/HiddenServicesActivity.java | 21 ++++- .../dialogs/CookieActionsDialog.java | 6 +- .../ui/hiddenservices/dialogs/HSActionsDialog.java | 6 +- .../permissions/PermissionManager.java | 103 +++++++++++++++++++++ .../hiddenservices/storage/PermissionManager.java | 50 ---------- app/src/main/res/values/strings.xml | 4 + 9 files changed, 137 insertions(+), 65 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7dd9c1c..a713cf5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,7 @@ <uses-permission android:name="android.permission.ACCESS_SUPERUSER" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java index 3abcdb8..1a468d4 100644 --- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java +++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java @@ -30,6 +30,7 @@ import org.torproject.android.ui.Rotate3dAnimation; import org.torproject.android.ui.hiddenservices.ClientCookiesActivity; import org.torproject.android.ui.hiddenservices.HiddenServicesActivity; import org.torproject.android.ui.hiddenservices.backup.BackupUtils; +import org.torproject.android.ui.hiddenservices.permissions.PermissionManager; import org.torproject.android.ui.hiddenservices.providers.HSContentProvider; import org.torproject.android.vpn.VPNEnableActivity;
@@ -124,8 +125,6 @@ public class OrbotMainActivity extends AppCompatActivity private final static int REQUEST_SETTINGS = 0x9874; private final static int REQUEST_VPN_APPS_SELECT = 8889;
- private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; - // message types for mStatusUpdateHandler private final static int STATUS_UPDATE = 1; private static final int MESSAGE_TRAFFIC_COUNT = 2; @@ -586,7 +585,7 @@ public class OrbotMainActivity extends AppCompatActivity Prefs.putUseVpn(enable);
if (enable) { - if (mIsLollipop) //let the user choose the apps + if (PermissionManager.isLollipopOrHigher()) //let the user choose the apps startActivityForResult(new Intent(OrbotMainActivity.this, AppManager.class), REQUEST_VPN_APPS_SELECT); else startActivity(new Intent(OrbotMainActivity.this, VPNEnableActivity.class)); diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java index 0b94812..ffbe3d5 100644 --- a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java +++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java @@ -28,8 +28,8 @@ import org.torproject.android.ui.hiddenservices.adapters.ClienCookiesAdapter; import org.torproject.android.ui.hiddenservices.dialogs.AddCookieDialog; import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog; import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog; +import org.torproject.android.ui.hiddenservices.permissions.PermissionManager; import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider; -import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class ClientCookiesActivity extends AppCompatActivity { public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3; @@ -111,9 +111,9 @@ public class ClientCookiesActivity extends AppCompatActivity { int id = item.getItemId();
if (id == R.id.cookie_restore_backup) { - if (PermissionManager.usesRuntimePermissions() + if (PermissionManager.isLollipopOrHigher() && !PermissionManager.hasExternalWritePermission(this)) { - PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR); + PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR); return true; }
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java index ae2cd55..f644558 100644 --- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java +++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java @@ -25,8 +25,8 @@ import org.torproject.android.ui.hiddenservices.adapters.OnionListAdapter; import org.torproject.android.ui.hiddenservices.dialogs.HSActionsDialog; import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog; import org.torproject.android.ui.hiddenservices.dialogs.SelectHSBackupDialog; +import org.torproject.android.ui.hiddenservices.permissions.PermissionManager; import org.torproject.android.ui.hiddenservices.providers.HSContentProvider; -import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class HiddenServicesActivity extends AppCompatActivity { public final int WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR = 1; @@ -150,9 +150,9 @@ public class HiddenServicesActivity extends AppCompatActivity { int id = item.getItemId();
if (id == R.id.menu_restore_backup) { - if (PermissionManager.usesRuntimePermissions() + if (PermissionManager.isLollipopOrHigher() && !PermissionManager.hasExternalWritePermission(this)) { - PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR); + PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR); return true; }
@@ -194,6 +194,21 @@ public class HiddenServicesActivity extends AppCompatActivity { mAdapter.changeCursor(mResolver.query( HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null )); + + if (PermissionManager.isLollipopOrHigher()) { + Cursor active = mResolver.query( + HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, HSContentProvider.HiddenService.ENABLED + "=1", null, null + ); + + if (active == null) return; + + if (active.getCount() > 0) // Call only if there running services + PermissionManager.requestBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext()); + else // Drop whe not needed + PermissionManager.requestDropBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext()); + + active.close(); + } } } } diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java index e5683da..7b5a2cf 100644 --- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java +++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java @@ -15,7 +15,7 @@ import android.widget.Toast;
import org.torproject.android.R; import org.torproject.android.ui.hiddenservices.backup.BackupUtils; -import org.torproject.android.ui.hiddenservices.storage.PermissionManager; +import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class CookieActionsDialog extends DialogFragment { public static final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG = 4; @@ -36,10 +36,10 @@ public class CookieActionsDialog extends DialogFragment { public void onClick(View v) { Context mContext = v.getContext();
- if (PermissionManager.usesRuntimePermissions() + if (PermissionManager.isLollipopOrHigher() && !PermissionManager.hasExternalWritePermission(mContext)) {
- PermissionManager.requestPermissions( + PermissionManager.requestExternalWritePermissions( getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG);
return; diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java index ff7f7e1..5be7691 100644 --- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java +++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java @@ -17,7 +17,7 @@ import android.widget.Toast;
import org.torproject.android.R; import org.torproject.android.ui.hiddenservices.backup.BackupUtils; -import org.torproject.android.ui.hiddenservices.storage.PermissionManager; +import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class HSActionsDialog extends DialogFragment { public static final int WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG = 2; @@ -38,10 +38,10 @@ public class HSActionsDialog extends DialogFragment { public void onClick(View v) { Context mContext = v.getContext();
- if (PermissionManager.usesRuntimePermissions() + if (PermissionManager.isLollipopOrHigher() && !PermissionManager.hasExternalWritePermission(mContext)) {
- PermissionManager.requestPermissions( + PermissionManager.requestExternalWritePermissions( getActivity(), WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG);
return; diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java new file mode 100644 index 0000000..a9df5a9 --- /dev/null +++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java @@ -0,0 +1,103 @@ +package org.torproject.android.ui.hiddenservices.permissions; + + +import android.Manifest; +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.PowerManager; +import android.provider.Settings; +import android.support.design.widget.Snackbar; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentActivity; +import android.view.View; + +import org.torproject.android.R; + +public class PermissionManager { + public static int VERY_LONG_LENGTH = 6000; + + public static boolean isLollipopOrHigher() { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP); + } + + @SuppressLint("NewApi") + public static boolean hasExternalWritePermission(Context context) { + return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); + } + + public static void requestExternalWritePermissions(FragmentActivity activity, int action) { + final int mAction = action; + final FragmentActivity mActivity = activity; + + if (ActivityCompat.shouldShowRequestPermissionRationale + (mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + Snackbar.make(mActivity.findViewById(android.R.id.content), + R.string.please_grant_permissions_for_external_storage, + Snackbar.LENGTH_INDEFINITE).setAction(R.string.activate, + new View.OnClickListener() { + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(mActivity, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + mAction); + } + }).show(); + } else { + ActivityCompat.requestPermissions(mActivity, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + mAction); + } + } + + @TargetApi(Build.VERSION_CODES.M) + public static void requestBatteryPermmssions(FragmentActivity activity, Context context) { + final Context mContext = context; + final String packageName = mContext.getPackageName(); + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + + if (pm.isIgnoringBatteryOptimizations(packageName)) + return; + + Snackbar.make(activity.findViewById(android.R.id.content), + R.string.consider_disable_battery_optimizations, + VERY_LONG_LENGTH).setAction(R.string.disable, + new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + mContext.startActivity(intent); + } + }).show(); + } + + @TargetApi(Build.VERSION_CODES.M) + public static void requestDropBatteryPermmssions(FragmentActivity activity, Context context) { + final Context mContext = context; + + final String packageName = context.getPackageName(); + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + + if (!pm.isIgnoringBatteryOptimizations(packageName)) + return; + + Snackbar.make(activity.findViewById(android.R.id.content), + R.string.consider_enable_battery_optimizations, + VERY_LONG_LENGTH).setAction(R.string.enable, + new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); + mContext.startActivity(intent); + } + }).show(); + } +} + diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java deleted file mode 100644 index 3a3cf09..0000000 --- a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.torproject.android.ui.hiddenservices.storage; - - -import android.Manifest; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Build; -import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.FragmentActivity; -import android.view.View; - -import org.torproject.android.R; - -public class PermissionManager { - - public static boolean usesRuntimePermissions() { - return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1); - } - - @SuppressLint("NewApi") - public static boolean hasExternalWritePermission(Context context) { - return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); - } - - public static void requestPermissions(FragmentActivity activity, int action) { - final int mAction = action; - final FragmentActivity mActivity = activity; - - if (ActivityCompat.shouldShowRequestPermissionRationale - (mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - Snackbar.make(mActivity.findViewById(android.R.id.content), - R.string.please_grant_permissions_for_external_storage, - Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", - new View.OnClickListener() { - @Override - public void onClick(View v) { - ActivityCompat.requestPermissions(mActivity, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - mAction); - } - }).show(); - } else { - ActivityCompat.requestPermissions(mActivity, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - mAction); - } - } -} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6a07c44..41b9e81 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -376,4 +376,8 @@ <string name="confirm_cookie_deletion">Confirm cookie deletion</string> <string name="hosted_services">Hosted Services</string> <string name="share_as_qr">Share as QR</string> + <string name="disable">Disable</string> + <string name="enable">Enable</string> + <string name="consider_disable_battery_optimizations">Consider disable battery optimizations</string> + <string name="consider_enable_battery_optimizations">Consider enable battery optimizations</string> </resources>
tor-commits@lists.torproject.org