Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 检查我的应用程序是否启用了使用权限_Android_Usage Statistics - Fatal编程技术网

Android 检查我的应用程序是否启用了使用权限

Android 检查我的应用程序是否启用了使用权限,android,usage-statistics,Android,Usage Statistics,我正在使用新的usagestastsmanagerAPI在android5.0棒棒糖中运行。 要使用此API,用户必须在设置->安全->具有使用权限的应用程序屏幕中启用该应用程序 我将用户直接发送到此屏幕,目的如下: startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); 现在,我想验证用户启用我的应用程序。 我想这样做,就像验证用户使我的应用程序能够使用NotificationListenerService一样,但

我正在使用新的
usagestastsmanager
API在android5.0棒棒糖中运行。 要使用此API,用户必须在
设置->安全->具有使用权限的应用程序
屏幕中启用该应用程序

我将用户直接发送到此屏幕,目的如下:


startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
现在,我想验证用户启用我的应用程序。 我想这样做,就像验证用户使我的应用程序能够使用
NotificationListenerService
一样,但我不知道字符串键是什么,如果它存在的话。

Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
// Tried Settings.ACTION_USAGE_ACCESS_SETTINGS as key but it returns null

有没有办法检查我的应用程序是否启用了使用访问权限?

在Twitter上收到了一个很好的答案,测试工作:

try {
   PackageManager packageManager = context.getPackageManager();
   ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
   AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
   int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
   return (mode == AppOpsManager.MODE_ALLOWED);

} catch (PackageManager.NameNotFoundException e) {
   return false;
}

这是一种替代解决方案:

AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
                    android.os.Process.myUid(), context.getPackageName());
return mode == AppOpsManager.MODE_ALLOWED;

这段代码在棒棒糖和棉花糖中工作,我在我的应用程序中使用了这段代码

if (Build.VERSION.SDK_INT >= 21) {
            UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
            long time = System.currentTimeMillis();
            List stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);

            if (stats == null || stats.isEmpty()) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_USAGE_ACCESS_SETTINGS);
                context.startActivity(intent);
            }
    }

如果他们使用的是亚马逊Fire平板电脑(可能还有其他Fire操作系统设备),用户可以从用户安装的Google Play商店下载应用程序,但在他们的操作系统中没有您想要激活的选项。我知道这一点,因为作为一个FireOS用户,这几分钟前发生在我身上。检测用户是否有Fire操作系统,如果有,提供一个实际存在的选项对用户和开发人员来说都是非常棒的。

我以前使用了与Bao Le相同的代码,但我遇到了一个问题,即某些设备(例如VF-895N)报告使用情况统计数据,即使它们没有启用。作为一种解决方法,我对代码进行了如下修改:

public static boolean hasPermission(@NonNull final Context context) {
    // Usage Stats is theoretically available on API v19+, but official/reliable support starts with API v21.
    if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
        return false;
    }

    final AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

    if (appOpsManager == null) {
        return false;
    }

    final int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
    if (mode != AppOpsManager.MODE_ALLOWED) {
        return false;
    }

    // Verify that access is possible. Some devices "lie" and return MODE_ALLOWED even when it's not.
    final long now = System.currentTimeMillis();
    final UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    final List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, now - 1000 * 10, now);
    return (stats != null && !stats.isEmpty());
}
公共静态布尔hasPermission(@NonNull final Context){
//理论上,API v19+上提供了使用统计数据,但官方/可靠的支持从API v21开始。
if(VERSION.SDK\u INT
已在多台设备上成功测试。

请尝试此操作

public boolean check_UsgAccs(){
    long tme = System.currentTimeMillis();
    UsageStatsManager usm = (UsageStatsManager)getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
    List<UsageStats> al= usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, tme - (1000 * 1000), tme);
        return  al.size()>0;

    }
public boolean check_UsgAccs(){
long tme=System.currentTimeMillis();
UsageStatsManager usm=(UsageStatsManager)getApplicationContext().getSystemService(Context.USAGE\u STATS\u SERVICE);
List al=usm.queryUsageStats(usagestastmanager.INTERVAL_按年,tme-(1000*1000),tme);
返回al.size()>0;
}
这适用于KitKat(API 19)

检测使用权限何时更改 使用此类可在您的应用被授予或撤销使用权限时收到通知

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class UsagePermissionMonitor {

    private final Context context;
    private final AppOpsManager appOpsManager;
    private final Handler handler;
    private boolean isListening;
    private Boolean lastValue;

    public UsagePermissionMonitor(Context context) {
        this.context = context;
        appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        handler = new Handler();
    }

    public void startListening() {
        appOpsManager.startWatchingMode(AppOpsManager.OPSTR_GET_USAGE_STATS, context.getPackageName(), usageOpListener);
        isListening = true;
    }

    public void stopListening() {
        lastValue = null;
        isListening = false;
        appOpsManager.stopWatchingMode(usageOpListener);
        handler.removeCallbacks(checkUsagePermission);
    }

    private final AppOpsManager.OnOpChangedListener usageOpListener = new AppOpsManager.OnOpChangedListener() {
        @Override
        public void onOpChanged(String op, String packageName) {
            // Android sometimes sets packageName to null
            if (packageName == null || context.getPackageName().equals(packageName)) {
                // Android actually notifies us of changes to ops other than the one we registered for, so filtering them out
                if (AppOpsManager.OPSTR_GET_USAGE_STATS.equals(op)) {
                    // We're not in main thread, so post to main thread queue
                    handler.post(checkUsagePermission);
                }
            }
        }
    };

    private final Runnable checkUsagePermission = new Runnable() {
        @Override
        public void run() {
            if (isListening) {
                int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, Process.myUid(), context.getPackageName());
                boolean enabled = mode == AppOpsManager.MODE_ALLOWED;

                // Each change to the permission results in two callbacks instead of one.
                // Filtering out the duplicates.
                if (lastValue == null || lastValue != enabled) {
                    lastValue = enabled;

                    // TODO: Do something with the result
                    Log.i(UsagePermissionMonitor.class.getSimpleName(), "Usage permission changed: " + enabled);
                }
            }
        }
    };

}
信用
基于中的代码。

以下是我对此的全面解决方案(基于类似的问题和答案):

公共静态权限状态getUsageStatsPermissionsStatus(上下文){
if(VERSION.SDK\u INT
没有一个答案对我有效,所以我做了这个

public boolean permissiontodetectapp(Context context) {
    try {
        ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
        return ((AppOpsManager) context.getSystemService(APP_OPS_SERVICE)).checkOpNoThrow("android:get_usage_stats", applicationInfo.uid, applicationInfo.packageName) != 0;
    } catch (PackageManager.NameNotFoundException unused) {
        return true;
    }
}

lluz:你知道我如何自动打开它吗?@user8430它写在OP.startActivity(新意图(设置、动作、使用、访问、设置))中;你只能将用户发送到屏幕,不能为他自动启用。我知道了。非常感谢。我发现另一个问题是,当用户正确选择应用程序时,我们如何关闭意图。因为,在我选择应用程序后,我必须按后退按钮返回我的活动。我正在寻找一种在用户选择目标时自动返回活动的方法app@user8430在将用户发送到“设置”屏幕并检查他是否返回简历->检查权限是否已授予之前,请使用布尔标志。我发现有一个人的问题与我的问题相同,如果用户单击“允许”,我们是否可以获得任何回拨ActivityResult@Umar,你说这对棒棒糖不起作用,但你是说KitKat吗?它在KitKat上不起作用,因为AppOpsManager.OPSTR_GET_USAGE_STATS仅在API级别21支持。将该常量替换为“android:get_usage_stats”,这将适用于KitKat。出于好奇,
UsageStatsManager
是否真的适用于KitKat?我以为它只能从棒棒糖中获得。是的,使用状态管理器只能从API 22中工作。但是上面的代码与usage status manager无关。我调查了这段代码中的额外检查,发现它实际上并不需要:到底为什么要否决?这是一种正确的方法,它可以处理所有情况。所有Android版本,以及用户/系统应用程序都一样……请注意,Unsecfectheckopnothrow是checkOpNoThrow的新名称(在Android Q中使用),因为checkOpNoThrow现在已被弃用。为什么它不安全?为什么反对它?只是为了改名?
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class UsagePermissionMonitor {

    private final Context context;
    private final AppOpsManager appOpsManager;
    private final Handler handler;
    private boolean isListening;
    private Boolean lastValue;

    public UsagePermissionMonitor(Context context) {
        this.context = context;
        appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        handler = new Handler();
    }

    public void startListening() {
        appOpsManager.startWatchingMode(AppOpsManager.OPSTR_GET_USAGE_STATS, context.getPackageName(), usageOpListener);
        isListening = true;
    }

    public void stopListening() {
        lastValue = null;
        isListening = false;
        appOpsManager.stopWatchingMode(usageOpListener);
        handler.removeCallbacks(checkUsagePermission);
    }

    private final AppOpsManager.OnOpChangedListener usageOpListener = new AppOpsManager.OnOpChangedListener() {
        @Override
        public void onOpChanged(String op, String packageName) {
            // Android sometimes sets packageName to null
            if (packageName == null || context.getPackageName().equals(packageName)) {
                // Android actually notifies us of changes to ops other than the one we registered for, so filtering them out
                if (AppOpsManager.OPSTR_GET_USAGE_STATS.equals(op)) {
                    // We're not in main thread, so post to main thread queue
                    handler.post(checkUsagePermission);
                }
            }
        }
    };

    private final Runnable checkUsagePermission = new Runnable() {
        @Override
        public void run() {
            if (isListening) {
                int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, Process.myUid(), context.getPackageName());
                boolean enabled = mode == AppOpsManager.MODE_ALLOWED;

                // Each change to the permission results in two callbacks instead of one.
                // Filtering out the duplicates.
                if (lastValue == null || lastValue != enabled) {
                    lastValue = enabled;

                    // TODO: Do something with the result
                    Log.i(UsagePermissionMonitor.class.getSimpleName(), "Usage permission changed: " + enabled);
                }
            }
        }
    };

}
public static PermissionStatus getUsageStatsPermissionsStatus(Context context) {
    if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)
        return PermissionStatus.CANNOT_BE_GRANTED;
    AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    final int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
    boolean granted = mode == AppOpsManager.MODE_DEFAULT ?
            (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED)
            : (mode == AppOpsManager.MODE_ALLOWED);
    return granted ? PermissionStatus.GRANTED : PermissionStatus.DENIED;
}

public enum PermissionStatus {
    GRANTED, DENIED, CANNOT_BE_GRANTED
}
public boolean permissiontodetectapp(Context context) {
    try {
        ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
        return ((AppOpsManager) context.getSystemService(APP_OPS_SERVICE)).checkOpNoThrow("android:get_usage_stats", applicationInfo.uid, applicationInfo.packageName) != 0;
    } catch (PackageManager.NameNotFoundException unused) {
        return true;
    }
}