我在Android 5.0 Lollipop中使用新的UsageStatsManager
API到get current foreground application。
要使用此API,用户必须在Settings->Security->Apps with usage access
屏幕中启用该应用程序。
我使用此Intent将用户直接发送到此屏幕:
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
现在,我想验证用户启用了我的应用程序。
我想这样做就像我验证用户启用我的应用程序使用NotificationListenerService
但我不知道什么是String键,如果它甚至存在。
Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
// Tried Settings.ACTION_USAGE_ACCESS_SETTINGS as key but it returns null
第二种方法是查询使用情况统计数据并检查它是否返回结果(当应用程序未启用时返回一个空数组)并且它大部分时间都有效,但有时即使我的应用程序启用也会返回0结果。
UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService("usagestats");
long time = System.currentTimeMillis();
List stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);
if (stats == null || stats.isEmpty()) {
// Usage access is not enabled
}
有没有办法检查我的应用程序是否启用了使用权限?
答案 0 :(得分:28)
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;
}
答案 1 :(得分:4)
我之前使用过和宝乐相同的代码,但是我遇到了某些设备(例如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());
}
在多台设备上成功测试。
答案 2 :(得分:2)
这是另一种解决方案:
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;
答案 3 :(得分:1)
这是我的全方位解决方案(基于类似的问题here):
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
}
答案 4 :(得分:0)
这适用于KitKat(API 19)
AppOpsManager appOps = (AppOpsManager) context
.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow("android:get_usage_stats",
android.os.Process.myUid(), context.getPackageName());
boolean granted = mode == AppOpsManager.MODE_ALLOWED;
答案 5 :(得分:0)
使用该类可在 您的应用被授予或撤销使用权限时收到通知。
@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) {
// 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);
}
}
}
};
}
基于epicality中another answer的代码。
答案 6 :(得分:0)
没有答案对我有用,所以我做到了
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;
}
}
答案 7 :(得分:-1)
这个代码在棒棒糖和marshmallow工作我在我的应用程序中使用了这段代码
{% if messages %}<ul>{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}</ul>{% endif %}
答案 8 :(得分:-1)
如果他们使用的是亚马逊Fire平板电脑(可能还有其他Fire OS设备),用户可以从用户安装的Google Play商店下载应用程序,然后在操作系统中没有您想要激活的选项。我知道这是因为作为Fire OS用户,几分钟前发生在我身上。检测用户是否具有Fire OS,如果是,提供实际存在的选项对于用户和开发者来说都是非常棒的。
答案 9 :(得分:-1)
尝试一下,
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;
}