Deal with Doze in the less painful way

This commit is contained in:
arrase 2016-12-08 15:22:53 +01:00
parent 2aa2b4c370
commit 41ebcc5050
9 changed files with 137 additions and 65 deletions

View File

@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" /> <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_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" /> <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />

View File

@ -30,6 +30,7 @@ import org.torproject.android.ui.Rotate3dAnimation;
import org.torproject.android.ui.hiddenservices.ClientCookiesActivity; import org.torproject.android.ui.hiddenservices.ClientCookiesActivity;
import org.torproject.android.ui.hiddenservices.HiddenServicesActivity; import org.torproject.android.ui.hiddenservices.HiddenServicesActivity;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils; 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.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.vpn.VPNEnableActivity; 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_SETTINGS = 0x9874;
private final static int REQUEST_VPN_APPS_SELECT = 8889; 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 // message types for mStatusUpdateHandler
private final static int STATUS_UPDATE = 1; private final static int STATUS_UPDATE = 1;
private static final int MESSAGE_TRAFFIC_COUNT = 2; private static final int MESSAGE_TRAFFIC_COUNT = 2;
@ -586,7 +585,7 @@ public class OrbotMainActivity extends AppCompatActivity
Prefs.putUseVpn(enable); Prefs.putUseVpn(enable);
if (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); startActivityForResult(new Intent(OrbotMainActivity.this, AppManager.class), REQUEST_VPN_APPS_SELECT);
else else
startActivity(new Intent(OrbotMainActivity.this, VPNEnableActivity.class)); startActivity(new Intent(OrbotMainActivity.this, VPNEnableActivity.class));

View File

@ -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.AddCookieDialog;
import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog; import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog; 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.providers.CookieContentProvider;
import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class ClientCookiesActivity extends AppCompatActivity { public class ClientCookiesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3; public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3;
@ -111,9 +111,9 @@ public class ClientCookiesActivity extends AppCompatActivity {
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.cookie_restore_backup) { if (id == R.id.cookie_restore_backup) {
if (PermissionManager.usesRuntimePermissions() if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) { && !PermissionManager.hasExternalWritePermission(this)) {
PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR); PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR);
return true; return true;
} }

View File

@ -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.HSActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog; import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectHSBackupDialog; 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.providers.HSContentProvider;
import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class HiddenServicesActivity extends AppCompatActivity { public class HiddenServicesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR = 1; public final int WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR = 1;
@ -150,9 +150,9 @@ public class HiddenServicesActivity extends AppCompatActivity {
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.menu_restore_backup) { if (id == R.id.menu_restore_backup) {
if (PermissionManager.usesRuntimePermissions() if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) { && !PermissionManager.hasExternalWritePermission(this)) {
PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR); PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR);
return true; return true;
} }
@ -194,6 +194,21 @@ public class HiddenServicesActivity extends AppCompatActivity {
mAdapter.changeCursor(mResolver.query( mAdapter.changeCursor(mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null 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();
}
} }
} }
} }

View File

@ -15,7 +15,7 @@ import android.widget.Toast;
import org.torproject.android.R; import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils; 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 class CookieActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG = 4; 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) { public void onClick(View v) {
Context mContext = v.getContext(); Context mContext = v.getContext();
if (PermissionManager.usesRuntimePermissions() if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) { && !PermissionManager.hasExternalWritePermission(mContext)) {
PermissionManager.requestPermissions( PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG); getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG);
return; return;

View File

@ -17,7 +17,7 @@ import android.widget.Toast;
import org.torproject.android.R; import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils; 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 class HSActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG = 2; 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) { public void onClick(View v) {
Context mContext = v.getContext(); Context mContext = v.getContext();
if (PermissionManager.usesRuntimePermissions() if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) { && !PermissionManager.hasExternalWritePermission(mContext)) {
PermissionManager.requestPermissions( PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG); getActivity(), WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG);
return; return;

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -376,4 +376,8 @@
<string name="confirm_cookie_deletion">Confirm cookie deletion</string> <string name="confirm_cookie_deletion">Confirm cookie deletion</string>
<string name="hosted_services">Hosted Services</string> <string name="hosted_services">Hosted Services</string>
<string name="share_as_qr">Share as QR</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> </resources>