mirror of https://github.com/termux/termux-app
543 lines
26 KiB
Java
543 lines
26 KiB
Java
package com.termux.shared.android;
|
|
|
|
import android.Manifest;
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.app.Service;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.pm.PackageInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Environment;
|
|
import android.os.PowerManager;
|
|
import android.provider.Settings;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.termux.shared.R;
|
|
import com.termux.shared.file.FileUtils;
|
|
import com.termux.shared.logger.Logger;
|
|
import com.termux.shared.errors.Error;
|
|
import com.termux.shared.errors.FunctionErrno;
|
|
import com.termux.shared.activity.ActivityUtils;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
public class PermissionUtils {
|
|
|
|
public static final int REQUEST_GRANT_STORAGE_PERMISSION = 1000;
|
|
|
|
public static final int REQUEST_DISABLE_BATTERY_OPTIMIZATIONS = 2000;
|
|
public static final int REQUEST_GRANT_DISPLAY_OVER_OTHER_APPS_PERMISSION = 2001;
|
|
|
|
private static final String LOG_TAG = "PermissionUtils";
|
|
|
|
|
|
/**
|
|
* Check if app has been granted the required permission.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param permission The {@link String} name for permission to check.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkPermission(@NonNull Context context, @NonNull String permission) {
|
|
return checkPermissions(context, new String[]{permission});
|
|
}
|
|
|
|
/**
|
|
* Check if app has been granted the required permissions.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param permissions The {@link String[]} names for permissions to check.
|
|
* @return Returns {@code true} if permissions are granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkPermissions(@NonNull Context context, @NonNull String[] permissions) {
|
|
// checkSelfPermission may return true for permissions not even requested
|
|
List<String> permissionsNotRequested = getPermissionsNotRequested(context, permissions);
|
|
if (permissionsNotRequested.size() > 0) {
|
|
Logger.logError(LOG_TAG,
|
|
context.getString(R.string.error_attempted_to_check_for_permissions_not_requested,
|
|
Joiner.on(", ").join(permissionsNotRequested)));
|
|
return false;
|
|
}
|
|
|
|
int result;
|
|
for (String permission : permissions) {
|
|
result = ContextCompat.checkSelfPermission(context, permission);
|
|
if (result != PackageManager.PERMISSION_GRANTED) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Request user to grant required permissions to the app.
|
|
*
|
|
* @param context The context for operations. It must be an instance of {@link Activity} or
|
|
* {@link AppCompatActivity}.
|
|
* @param permission The {@link String} name for permission to request.
|
|
* @param requestCode The request code to use while asking for permission. It must be `>=0` or
|
|
* will fail silently and will log an exception.
|
|
* @return Returns {@code true} if requesting the permission was successful, otherwise {@code false}.
|
|
*/
|
|
public static boolean requestPermission(@NonNull Context context, @NonNull String permission,
|
|
int requestCode) {
|
|
return requestPermissions(context, new String[]{permission}, requestCode);
|
|
}
|
|
|
|
/**
|
|
* Request user to grant required permissions to the app.
|
|
*
|
|
* On sdk 30 (android 11), Activity.onRequestPermissionsResult() will pass
|
|
* {@link PackageManager#PERMISSION_DENIED} (-1) without asking the user for the permission
|
|
* if user previously denied the permission prompt. On sdk 29 (android 10),
|
|
* Activity.onRequestPermissionsResult() will pass {@link PackageManager#PERMISSION_DENIED} (-1)
|
|
* without asking the user for the permission if user previously selected "Deny & don't ask again"
|
|
* option in prompt. The user will have to manually enable permission in app info in Android
|
|
* settings. If user grants and then denies in settings, then next time prompt will shown.
|
|
*
|
|
* @param context The context for operations. It must be an instance of {@link Activity} or
|
|
* {@link AppCompatActivity}.
|
|
* @param permissions The {@link String[]} names for permissions to request.
|
|
* @param requestCode The request code to use while asking for permissions. It must be `>=0` or
|
|
* will fail silently and will log an exception.
|
|
* @return Returns {@code true} if requesting the permissions was successful, otherwise {@code false}.
|
|
*/
|
|
public static boolean requestPermissions(@NonNull Context context, @NonNull String[] permissions,
|
|
int requestCode) {
|
|
List<String> permissionsNotRequested = getPermissionsNotRequested(context, permissions);
|
|
if (permissionsNotRequested.size() > 0) {
|
|
Logger.logErrorAndShowToast(context, LOG_TAG,
|
|
context.getString(R.string.error_attempted_to_ask_for_permissions_not_requested,
|
|
Joiner.on(", ").join(permissionsNotRequested)));
|
|
return false;
|
|
}
|
|
|
|
for (String permission : permissions) {
|
|
int result = ContextCompat.checkSelfPermission(context, permission);
|
|
// If at least one permission not granted
|
|
if (result != PackageManager.PERMISSION_GRANTED) {
|
|
Logger.logInfo(LOG_TAG, "Requesting Permissions: " + Arrays.toString(permissions));
|
|
|
|
try {
|
|
if (context instanceof AppCompatActivity)
|
|
((AppCompatActivity) context).requestPermissions(permissions, requestCode);
|
|
else if (context instanceof Activity)
|
|
((Activity) context).requestPermissions(permissions, requestCode);
|
|
else {
|
|
Error.logErrorAndShowToast(context, LOG_TAG,
|
|
FunctionErrno.ERRNO_PARAMETER_NOT_INSTANCE_OF.getError("context", "requestPermissions", "Activity or AppCompatActivity"));
|
|
return false;
|
|
}
|
|
} catch (Exception e) {
|
|
String errmsg = context.getString(R.string.error_failed_to_request_permissions, requestCode, Arrays.toString(permissions));
|
|
Logger.logStackTraceWithMessage(LOG_TAG, errmsg, e);
|
|
Logger.showToast(context, errmsg + "\n" + e.getMessage(), true);
|
|
return false;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Check if app has requested the required permission in the manifest.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param permission The {@link String} name for permission to check.
|
|
* @return Returns {@code true} if permission has been requested, otherwise {@code false}.
|
|
*/
|
|
public static boolean isPermissionRequested(@NonNull Context context, @NonNull String permission) {
|
|
return getPermissionsNotRequested(context, new String[]{permission}).size() == 0;
|
|
}
|
|
|
|
/**
|
|
* Check if app has requested the required permissions or not in the manifest.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param permissions The {@link String[]} names for permissions to check.
|
|
* @return Returns {@link List<String>} of permissions that have not been requested. It will have
|
|
* size 0 if all permissions have been requested.
|
|
*/
|
|
@NonNull
|
|
public static List<String> getPermissionsNotRequested(@NonNull Context context, @NonNull String[] permissions) {
|
|
List<String> permissionsNotRequested = new ArrayList<>();
|
|
Collections.addAll(permissionsNotRequested, permissions);
|
|
|
|
PackageInfo packageInfo = PackageUtils.getPackageInfoForPackage(context, PackageManager.GET_PERMISSIONS);
|
|
if (packageInfo == null) {
|
|
return permissionsNotRequested;
|
|
}
|
|
|
|
// If no permissions are requested, then nothing to check
|
|
if (packageInfo.requestedPermissions == null || packageInfo.requestedPermissions.length == 0)
|
|
return permissionsNotRequested;
|
|
|
|
List<String> requestedPermissionsList = Arrays.asList(packageInfo.requestedPermissions);
|
|
for (String permission : permissions) {
|
|
if (requestedPermissionsList.contains(permission)) {
|
|
permissionsNotRequested.remove(permission);
|
|
}
|
|
}
|
|
|
|
return permissionsNotRequested;
|
|
}
|
|
|
|
|
|
|
|
|
|
/** If path is under primary external storage directory and storage permission is missing,
|
|
* then legacy or manage external storage permission will be requested from the user via a call
|
|
* to {@link #checkAndRequestLegacyOrManageExternalStoragePermission(Context, int, boolean)}.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param filePath The path to check.
|
|
* @param requestCode The request code to use while asking for permission.
|
|
* @param showErrorMessage If an error message toast should be shown if permission is not granted.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
@SuppressLint("SdCardPath")
|
|
public static boolean checkAndRequestLegacyOrManageExternalStoragePermissionIfPathOnPrimaryExternalStorage(
|
|
@NonNull Context context, String filePath, int requestCode, boolean showErrorMessage) {
|
|
// If path is under primary external storage directory, then check for missing permissions.
|
|
if (!FileUtils.isPathInDirPaths(filePath,
|
|
Arrays.asList(Environment.getExternalStorageDirectory().getAbsolutePath(), "/sdcard"), true))
|
|
return true;
|
|
|
|
return checkAndRequestLegacyOrManageExternalStoragePermission(context, requestCode, showErrorMessage);
|
|
}
|
|
|
|
/**
|
|
* Check if legacy or manage external storage permissions has been granted. If
|
|
* {@link #isLegacyExternalStoragePossible(Context)} returns {@code true}, them it will be
|
|
* checked if app has has been granted {@link Manifest.permission#READ_EXTERNAL_STORAGE} and
|
|
* {@link Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions, otherwise it will be checked
|
|
* if app has been granted the {@link Manifest.permission#MANAGE_EXTERNAL_STORAGE} permission.
|
|
*
|
|
* If storage permission is missing, it will be requested from the user if {@code context} is an
|
|
* instance of {@link Activity} or {@link AppCompatActivity} and {@code requestCode}
|
|
* is `>=0` and the function will automatically return. The caller should register for
|
|
* Activity.onActivityResult() and Activity.onRequestPermissionsResult() and call this function
|
|
* again but set {@code requestCode} to `-1` to check if permission was granted or not.
|
|
*
|
|
* Caller must add following to AndroidManifest.xml of the app, otherwise errors will be thrown.
|
|
* {@code
|
|
* <manifest
|
|
* <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
* <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
* <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
|
|
*
|
|
* <application
|
|
* android:requestLegacyExternalStorage="true"
|
|
* ....
|
|
* </application>
|
|
* </manifest>
|
|
*}
|
|
* @param context The context for operations.
|
|
* @param requestCode The request code to use while asking for permission.
|
|
* @param showErrorMessage If an error message toast should be shown if permission is not granted.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkAndRequestLegacyOrManageExternalStoragePermission(@NonNull Context context,
|
|
int requestCode,
|
|
boolean showErrorMessage) {
|
|
String errmsg;
|
|
boolean requestLegacyStoragePermission = isLegacyExternalStoragePossible(context);
|
|
boolean checkIfHasRequestedLegacyExternalStorage = checkIfHasRequestedLegacyExternalStorage(context);
|
|
|
|
if (requestLegacyStoragePermission && checkIfHasRequestedLegacyExternalStorage) {
|
|
// Check if requestLegacyExternalStorage is set to true in app manifest
|
|
if (!hasRequestedLegacyExternalStorage(context, showErrorMessage))
|
|
return false;
|
|
}
|
|
|
|
if (checkStoragePermission(context, requestLegacyStoragePermission)) {
|
|
return true;
|
|
}
|
|
|
|
errmsg = context.getString(R.string.msg_storage_permission_not_granted);
|
|
Logger.logError(LOG_TAG, errmsg);
|
|
if (showErrorMessage)
|
|
Logger.showToast(context, errmsg, false);
|
|
|
|
if (requestCode < 0)
|
|
return false;
|
|
|
|
if (requestLegacyStoragePermission || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
|
requestLegacyStorageExternalPermission(context, requestCode);
|
|
} else {
|
|
requestManageStorageExternalPermission(context, requestCode);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if app has been granted storage permission.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param checkLegacyStoragePermission If set to {@code true}, then it will be checked if app
|
|
* has been granted {@link Manifest.permission#READ_EXTERNAL_STORAGE}
|
|
* and {@link Manifest.permission#WRITE_EXTERNAL_STORAGE}
|
|
* permissions, otherwise it will be checked if app has been
|
|
* granted the {@link Manifest.permission#MANAGE_EXTERNAL_STORAGE}
|
|
* permission.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkStoragePermission(@NonNull Context context, boolean checkLegacyStoragePermission) {
|
|
if (checkLegacyStoragePermission || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
|
return checkPermissions(context,
|
|
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
|
|
Manifest.permission.WRITE_EXTERNAL_STORAGE});
|
|
} else {
|
|
return Environment.isExternalStorageManager();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Request user to grant {@link Manifest.permission#READ_EXTERNAL_STORAGE} and
|
|
* {@link Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions to the app.
|
|
*
|
|
* @param context The context for operations. It must be an instance of {@link Activity} or
|
|
* {@link AppCompatActivity}.
|
|
* @param requestCode The request code to use while asking for permission. It must be `>=0` or
|
|
* will fail silently and will log an exception.
|
|
* @return Returns {@code true} if requesting the permission was successful, otherwise {@code false}.
|
|
*/
|
|
public static boolean requestLegacyStorageExternalPermission(@NonNull Context context, int requestCode) {
|
|
Logger.logInfo(LOG_TAG, "Requesting legacy external storage permission");
|
|
return requestPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, requestCode);
|
|
}
|
|
|
|
/** Wrapper for {@link #requestManageStorageExternalPermission(Context, int)}. */
|
|
@RequiresApi(api = Build.VERSION_CODES.R)
|
|
public static Error requestManageStorageExternalPermission(@NonNull Context context) {
|
|
return requestManageStorageExternalPermission(context, -1);
|
|
}
|
|
|
|
/**
|
|
* Request user to grant {@link Manifest.permission#MANAGE_EXTERNAL_STORAGE} permission to the app.
|
|
*
|
|
* @param context The context for operations, like an {@link Activity} or {@link Service} context.
|
|
* It must be an instance of {@link Activity} or {@link AppCompatActivity} if
|
|
* result is required via the Activity#onActivityResult() callback and
|
|
* {@code requestCode} is `>=0`.
|
|
* @param requestCode The request code to use while asking for permission. It must be `>=0` if
|
|
* result it required.
|
|
* @return Returns the {@code error} if requesting the permission was not successful, otherwise {@code null}.
|
|
*/
|
|
@RequiresApi(api = Build.VERSION_CODES.R)
|
|
public static Error requestManageStorageExternalPermission(@NonNull Context context, int requestCode) {
|
|
Logger.logInfo(LOG_TAG, "Requesting manage external storage permission");
|
|
|
|
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
|
|
intent.addCategory("android.intent.category.DEFAULT");
|
|
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
|
|
|
Error error;
|
|
if (requestCode >=0)
|
|
error = ActivityUtils.startActivityForResult(context, requestCode, intent, true, false);
|
|
else
|
|
error = ActivityUtils.startActivity(context, intent, true, false);
|
|
|
|
// Use fallback if matching Activity did not exist for ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION.
|
|
if (error != null) {
|
|
intent = new Intent();
|
|
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
|
|
if (requestCode >=0)
|
|
return ActivityUtils.startActivityForResult(context, requestCode, intent);
|
|
else
|
|
return ActivityUtils.startActivity(context, intent);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* If app is targeting targetSdkVersion 30 (android 11) and running on sdk 30 (android 11) or
|
|
* higher, then {@link android.R.attr#requestLegacyExternalStorage} attribute is ignored.
|
|
* https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage
|
|
*/
|
|
public static boolean isLegacyExternalStoragePossible(@NonNull Context context) {
|
|
return !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
|
PackageUtils.getTargetSDKForPackage(context) >= Build.VERSION_CODES.R);
|
|
}
|
|
|
|
/**
|
|
* Return whether it should be checked if app has set
|
|
* {@link android.R.attr#requestLegacyExternalStorage} attribute to {@code true}, if storage
|
|
* permissions are to be requested based on if {@link #isLegacyExternalStoragePossible(Context)}
|
|
* return {@code true}.
|
|
*
|
|
* If app is targeting targetSdkVersion 30 (android 11), then legacy storage can only be
|
|
* requested if running on sdk 29 (android 10).
|
|
* If app is targeting targetSdkVersion 29 (android 10), then legacy storage can only be
|
|
* requested if running on sdk 29 (android 10) and higher.
|
|
*/
|
|
public static boolean checkIfHasRequestedLegacyExternalStorage(@NonNull Context context) {
|
|
int targetSdkVersion = PackageUtils.getTargetSDKForPackage(context);
|
|
|
|
if (targetSdkVersion >= Build.VERSION_CODES.R) {
|
|
return Build.VERSION.SDK_INT == Build.VERSION_CODES.Q;
|
|
} else if (targetSdkVersion == Build.VERSION_CODES.Q) {
|
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call to {@link Environment#isExternalStorageLegacy()} will not return the actual value defined
|
|
* in app manifest for {@link android.R.attr#requestLegacyExternalStorage} attribute,
|
|
* since an app may inherit its legacy state based on when it was first installed, target sdk and
|
|
* other factors. To provide consistent experience for all users regardless of current legacy
|
|
* state on a specific device, we directly use the value defined in app` manifest.
|
|
*/
|
|
public static boolean hasRequestedLegacyExternalStorage(@NonNull Context context,
|
|
boolean showErrorMessage) {
|
|
String errmsg;
|
|
Boolean hasRequestedLegacyExternalStorage = PackageUtils.hasRequestedLegacyExternalStorage(context);
|
|
if (hasRequestedLegacyExternalStorage != null && !hasRequestedLegacyExternalStorage) {
|
|
errmsg = context.getString(R.string.error_has_not_requested_legacy_external_storage,
|
|
context.getPackageName(), PackageUtils.getTargetSDKForPackage(context), Build.VERSION.SDK_INT);
|
|
Logger.logError(LOG_TAG, errmsg);
|
|
if (showErrorMessage)
|
|
Logger.showToast(context, errmsg, true);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Check if {@link Manifest.permission#SYSTEM_ALERT_WINDOW} permission has been granted.
|
|
*
|
|
* @param context The context for operations.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkDisplayOverOtherAppsPermission(@NonNull Context context) {
|
|
return Settings.canDrawOverlays(context);
|
|
}
|
|
|
|
/** Wrapper for {@link #requestDisplayOverOtherAppsPermission(Context, int)}. */
|
|
public static Error requestDisplayOverOtherAppsPermission(@NonNull Context context) {
|
|
return requestDisplayOverOtherAppsPermission(context, -1);
|
|
}
|
|
|
|
/**
|
|
* Request user to grant {@link Manifest.permission#SYSTEM_ALERT_WINDOW} permission to the app.
|
|
*
|
|
* @param context The context for operations, like an {@link Activity} or {@link Service} context.
|
|
* It must be an instance of {@link Activity} or {@link AppCompatActivity} if
|
|
* result is required via the Activity#onActivityResult() callback and
|
|
* {@code requestCode} is `>=0`.
|
|
* @param requestCode The request code to use while asking for permission. It must be `>=0` if
|
|
* result it required.
|
|
* @return Returns the {@code error} if requesting the permission was not successful, otherwise {@code null}.
|
|
*/
|
|
public static Error requestDisplayOverOtherAppsPermission(@NonNull Context context, int requestCode) {
|
|
Logger.logInfo(LOG_TAG, "Requesting display over apps permission");
|
|
|
|
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
|
|
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
|
|
|
if (requestCode >=0)
|
|
return ActivityUtils.startActivityForResult(context, requestCode, intent);
|
|
else
|
|
return ActivityUtils.startActivity(context, intent);
|
|
}
|
|
|
|
/**
|
|
* Check if running on sdk 29 (android 10) or higher and {@link Manifest.permission#SYSTEM_ALERT_WINDOW}
|
|
* permission has been granted or not.
|
|
*
|
|
* @param context The context for operations.
|
|
* @param logResults If it should be logged that permission has been granted or not.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean validateDisplayOverOtherAppsPermissionForPostAndroid10(@NonNull Context context,
|
|
boolean logResults) {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true;
|
|
|
|
if (!checkDisplayOverOtherAppsPermission(context)) {
|
|
if (logResults)
|
|
Logger.logWarn(LOG_TAG, context.getPackageName() + " does not have Display over other apps (SYSTEM_ALERT_WINDOW) permission");
|
|
return false;
|
|
} else {
|
|
if (logResults)
|
|
Logger.logDebug(LOG_TAG, context.getPackageName() + " already has Display over other apps (SYSTEM_ALERT_WINDOW) permission");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Check if {@link Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS} permission has been
|
|
* granted.
|
|
*
|
|
* @param context The context for operations.
|
|
* @return Returns {@code true} if permission is granted, otherwise {@code false}.
|
|
*/
|
|
public static boolean checkIfBatteryOptimizationsDisabled(@NonNull Context context) {
|
|
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
|
return powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
|
|
}
|
|
|
|
/** Wrapper for {@link #requestDisableBatteryOptimizations(Context, int)}. */
|
|
public static Error requestDisableBatteryOptimizations(@NonNull Context context) {
|
|
return requestDisableBatteryOptimizations(context, -1);
|
|
}
|
|
|
|
/**
|
|
* Request user to grant {@link Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}
|
|
* permission to the app.
|
|
*
|
|
* @param context The context for operations, like an {@link Activity} or {@link Service} context.
|
|
* It must be an instance of {@link Activity} or {@link AppCompatActivity} if
|
|
* result is required via the Activity#onActivityResult() callback and
|
|
* {@code requestCode} is `>=0`.
|
|
* @param requestCode The request code to use while asking for permission. It must be `>=0` if
|
|
* result it required.
|
|
* @return Returns the {@code error} if requesting the permission was not successful, otherwise {@code null}.
|
|
*/
|
|
@SuppressLint("BatteryLife")
|
|
public static Error requestDisableBatteryOptimizations(@NonNull Context context, int requestCode) {
|
|
Logger.logInfo(LOG_TAG, "Requesting to disable battery optimizations");
|
|
|
|
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
|
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
|
|
|
if (requestCode >=0)
|
|
return ActivityUtils.startActivityForResult(context, requestCode, intent);
|
|
else
|
|
return ActivityUtils.startActivity(context, intent);
|
|
}
|
|
|
|
}
|