When using UsageStats how to set OPSTR_GET_USAGE_STATS transparently - android

I try to use usage stats but after retrieving successfully the list of installed apps I try to query the usage stats but I get a 0 value.
After looking in StackOverflow I see that there is an extra permission on top of PACKAGE_USAGE_STATS: OPSTR_GET_USAGE_STATS
When I check this permission I don't have it.
Why isn't PACKAGE_USAGE_STATS sufficient?
Does it exist a way to set this permission programmatically?
Otherwise, I don't like the idea of re-directing the user to Settings: isn't it a way to prompt the user in the UI to allow this permission?
Here is an extract of my code:
manifest
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
java code:
void getInstalledApp() {
List<String> installedApps = getInstalledAppList();
if(!checkForPermission())
Log.i("PERM", "false");
List<UsageStats> usageStats =
usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,
getStartTime(), System.currentTimeMillis());
List<UsageStats> stats = new ArrayList<>();
}
private List<String> getInstalledAppList(){
List<ApplicationInfo> infos = packageManager.getInstalledApplications(flags);
List<String> installedApps = new ArrayList<>();
for (ApplicationInfo info : infos){
installedApps.add(info.packageName);
}
return installedApps;
}
private long getStartTime() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -1);
return calendar.getTimeInMillis();
}
private boolean checkForPermission() {
AppOpsManager appOps = (AppOpsManager) activity.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(OPSTR_GET_USAGE_STATS, myUid(), activity.getPackageName());
return mode == MODE_ALLOWED;
}

Check this method for asking permission from user if not granted:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void checkForUsageStatsPermission() {
AppOpsManager appOps = (AppOpsManager) getActivity().getSystemService(Context.APP_OPS_SERVICE);
int mode = 0;
if (appOps != null) {
mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getActivity().getPackageName());
}
if (mode != AppOpsManager.MODE_ALLOWED) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
}
}

Related

getRunningAppProcesses() doesn't work in API 22 and above [duplicate]

It seems Google finally closed all doors for getting the current foreground application package.
After the Lollipop update, which killed getRunningTasks(int maxNum) and thanks to this answer, I used this code to get the foreground application package since Lollipop:
final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) {
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
app.importanceReasonCode == 0 ) {
Integer state = null;
try {
state = field.getInt( app );
} catch (Exception ignored) {
}
if (state != null && state == PROCESS_STATE_TOP) {
currentInfo = app;
break;
}
}
}
return currentInfo;
Android 5.1.1 and above (6.0 Marshmallow), it seems, killed getRunningAppProcesses() as well. It now returns a list of your own application package.
UsageStatsManager
We can use the new UsageStatsManager API as described here but it doesn't work for all applications. Some system applications will return the same package
com.google.android.googlequicksearchbox
AccessibilityService (December 2017: Going to be banned for use by Google)
Some applications use AccessibilityService (as seen here) but it has some disadvantages.
Is there another way of getting the current running application package?
To get a list of running processes on Android 1.6 - Android 6.0 you can use this library I wrote: https://github.com/jaredrummler/AndroidProcesses The library reads /proc to get process info.
Google has significantly restricted access to /proc in Android Nougat. To get a list of running processes on Android Nougat you will need to use UsageStatsManager or have root access.
Click the edit history for previous alternative solutions.
private String printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}
Log.e("adapter", "Current App in foreground is: " + currentApp);
return currentApp;
}
Use this method for getting foreground task.
U will need an System Permission "android:get_usage_stats"
public static boolean needPermissionForBlocking(Context context){
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 true;
}
}
IF user enable this in setting -> Security-> app with usage access. After that u will get foreground task. Similar process Clean matser by Cheetahamobile
google play link
Take a look at https://github.com/ricvalerio/foregroundappchecker, it might be what you need. Provides sample code, and takes away the pain of having to implement cross version foreground detector.
Here are two samples:
AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();
Or regularly check:
AppChecker appChecker = new AppChecker();
appChecker
.when("com.other.app", new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.when("com.my.app", new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.other(new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.timeout(1000)
.start(this);
Google limited this functionality for system apps only. As been reported in a bug ticket, you will need the REAL_GET_TASKS permission to access there.
Applications must now have ...permission.REAL_GET_TASKS to be able to
get process information for all applications. Only the process
information for the calling application will be returned if the app
doesn't have the permission. Privileges apps will temporarily be able
to get process information for all applications if they don't have the
new permission, but have deprecated ...permission.GET_TASKS Also,only
system apps can acquire the REAL_GET_TASKS permission.
Just throwing out a potential optimization to what I imagine is a heavily copy-pasted bit of code for detecting the top-most application on Android M.
This
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}
Can be simplified to this
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) context.getSystemService(
Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
time - 1000 * 1000, time);
if (appStatsList != null && !appStatsList.isEmpty()) {
currentApp = Collections.max(appStatsList, (o1, o2) ->
Long.compare(o1.getLastTimeUsed(), o2.getLastTimeUsed())).getPackageName();
}
}
I found myself using this code in a 2 second loop, and wondered why I was using a complex solution that was O(n*log(n)) when a more simple solution was available in Collections.max() which is O(n).
public class AccessibilityDetectingService extends AccessibilityService {
#Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
#Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
if (event == null ) {
return;
} else if(event.getPackageName() == null && event.getClassName() == null){
return;
}
if (activityInfo != null){
Log.d("CurrentActivity", componentName.flattenToShortString());
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
#Override
public void onInterrupt() {
}
}
}//`enter code here`uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />
Then start the service and app accessibility on in your device
setting->accessibility->App
on that service.
Please try to use getRunningServices() instead of getRunningAppProcesses() method.
ActivityManager mActivityManager = (ActivityManager) getSy stemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> appProcessInfoList = mActivityManager.getRunningServices(Integer.MAX_VALUE);

Detect which app has been launched in android

How to detect which app has been launched by user in my app i.e my application should get notified when Whatsapp is launched by user even if my app is not running in foreground or background.
hike messenger has achieved same functionality with accessibility service.
How can I solve this problem ?
Thanks in advance!!
Depending on the Android version running your application, you will have to use different methods.
On Pre-Lollipop devices, it is pretty straight-forward:
String[] result = new String[2];
List<ActivityManager.RunningTaskInfo> runningTasks;
ComponentName componentInfo;
runningTasks = activityManager.getRunningTasks(1);
componentInfo = runningTasks.get(0).topActivity;
result[0] = componentInfo.getPackageName();
result[1] = componentInfo.getClassName();
If you are on a Lollipop or newer device, you have to use UsageStatsManager class, which requires your application to be granted specific permissions
//no inspection ResourceType
UsageStatsManager mUsageStatsManager = (UsageStatsManager)context.getSystemService("usagestats");
long time = System.currentTimeMillis();
// We get usage stats for the last 10 seconds
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);
// Sort the stats by the last time used
if(stats != null) {
SortedMap<Long,UsageStats> mySortedMap = new TreeMap<>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
}
if(mySortedMap != null && !mySortedMap.isEmpty()) {
return mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
return null;
This will tell you if your apps has been granted permissions:
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;
}
And finally this will launch the Android permission granting activity for the user:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
activity.startActivity(intent);
Hope that helps
Try this code:
ActivityManager activityManager = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
for(int i = 0; i < procInfos.size(); i++)
{
if(procInfos.get(i).processName.equals("put the package name here"))
{
Toast.makeText(getApplicationContext(), "Notify Message", Toast.LENGTH_LONG).show();
}
}
No, this is not really possible using the public SDK.
You can get the current running process by ActivityManager#getRunningAppProcesses But it is definitely impossible to get notified .However, it isn't the most accurate, or efficient method

Get foreground activity from package name?

I am trying to get running activity name (Foreground activity name) from package name as you all know that we can get currently running activity name
via this line
mActivityManager.getRunningTasks(1).get(0).topActivity.getClassName()
but this work only bellow android 5.0 i need same thing in above 5.0
i am able to get current package name but not activity
security is enhanced from android Lollipop; see this article for more details: getAppTask
You could get foreground activities via UsageStats class; first, you have to add this permission in your manifest:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
and this declaration:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your_application_package">
This will disable warning that permission is system level and will not be granted to third-party apps. User of the device can grant permission through the Settings application.
So, in onCreate() method of your MainActivity, check if user granted this permission
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
if(!hasPermission()){
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),
Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
}
}
And if no, ask user to enable it:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS){
if (!hasPermission()){
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),
Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
}
}
}
private boolean hasPermission() {
AppOpsManager appOps = (AppOpsManager)
getSystemService(Context.APP_OPS_SERVICE);
int mode = 0;
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.KITKAT) {
mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(), getPackageName());
}
return mode == AppOpsManager.MODE_ALLOWED;
}
Finally, here's a snippet to put in a background service, that gives you package name of current foreground activites:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private String getUsageStatsForegroundActivityName() {
UsageStatsManager mUsageStatsManager = (UsageStatsManager) MyApplication.getInstance().getSystemService(Context.USAGE_STATS_SERVICE);
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 60;
// result
String topActivity = null;
// We get usage stats for the last minute
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, beginTime, endTime);
// Sort the stats by the last time used
if (stats != null) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
topActivity = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
logger.info("topActivity: " + topActivity);
}
}
if (topActivity != null)
return topActivity;
else
return Constant.ACTIVITY_NOT_FOUND;
}

Check if my application has usage access enabled

I'm using the new UsageStatsManager API to get current foreground application in Android 5.0 Lollipop.
In order to use this API, the user must enable the application in the Settings->Security->Apps with usage access screen.
I send the user directly to this screen with this Intent:
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
Now, I want to validate the user enabled my application.
I wanted to do so like I validate the user enabled my application to use the NotificationListenerService but I have no idea what is the String key, if it even exists.
Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
// Tried Settings.ACTION_USAGE_ACCESS_SETTINGS as key but it returns null
Second approach was to query the usage stats and check if it returns results (it returns an empty array when the app is not enabled) and it works most of the times but sometimes it returns 0 results even when my app is enabled.
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
}
Is there a way to check if my application has usage access enabled?
Received a great answer by someone on Twitter, tested working:
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;
}
I previously used the same code as Bao Le, but I've run into the problem that certain devices (e.g. VF-895N) report usage stats as enabled even when they're not. As a workaround I've modified my code like this:
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());
}
Successfully tested on multiple devices.
Here's my all-around solution for this (based on similar question and answer 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
}
Detecting when the usage access changes
Use this class to be notified when your app is granted or revoked usage access.
#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);
}
}
}
};
}
Credits
Based on code from epicality in another answer.
This is an alternative solutions:
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;
This works down to 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;
None of the answer worked for me so i made this
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;
}
}
this code working in lollipop and marshmallow i used this code in my app
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);
}
}
If they are using an Amazon Fire tablet (and possibly other Fire OS devices) the user can download the application from a user installed Google Play Store then not have the option you want activated available in their OS. I know this because as a Fire OS user this happened to me a few minutes ago. Detecting whether a user has Fire OS and, if so, offering an option which actually exists would be fantastic for both user and dev.
try this ,
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;
}

Is there an alternative for getRunningTask API

I was using getRunningTask API in one of my application to find the Foreground application. This API has been deprecated since Lollipop. After this deprecation, I preferred getRunningAppProcess API along with Importance_Foreground. I also ruled out REASON_SERVICE and REASON_PROVIDER from this list. I filtered out the system applications based on a logic, which worked perfectly. The problem is that, If Application A is on foreground, I get Application B as a spike. So, this approach is currently questionable. Is there any other alternative to the getRunningTask API?? Or am I missing any simple thing in the current approach. Please help guys.
Based on the answer to this question
String getTopPackage(){
long ts = System.currentTimeMillis();
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");
List<UsageStats> usageStats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, ts-1000, ts);
if (usageStats == null || usageStats.size() == 0) {
return NONE_PKG;
}
Collections.sort(usageStats, mRecentComp);
return usageStats.get(0).getPackageName();
}
This is the mRecentComp:
static class RecentUseComparator implements Comparator<UsageStats> {
#Override
public int compare(UsageStats lhs, UsageStats rhs) {
return (lhs.getLastTimeUsed() > rhs.getLastTimeUsed()) ? -1 : (lhs.getLastTimeUsed() == rhs.getLastTimeUsed()) ? 0 : 1;
}
}
This permission is needed:
<uses-permission xmlns:tools="http://schemas.android.com/tools"
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
And you will need user authorization to request the stats, use this to direct the user to the settings page:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
And you can check if you already have permission like this:
public static boolean needPermissionForBlocking(Context context) {
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 true;
}
}
Get the list of RunningAppProcessInfo by ActivityManager.getRunningAppProcesses().
Choose the RuningAppProcessInfo with whose importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND and whose processState == ActivityManager.START_TASK_TO_FRONT.
(The former is easy, the latter is difficult because the reflection is necessary)
See my answer for this question getRunningTasks doesn't work in Android L

Categories

Resources