9

I want to find out the list of apps accessed by user in a particular time interval (ex: 5min), from a background job? Is this possible on a non-rooted android phone? If possible I'm very much interested in knowing the answer as it will be a great learning about android.

Kishor
  • 4,006
  • 7
  • 30
  • 47
  • Would it suffice to record the accessed apps during that interval? – Storo Dec 04 '14 at 02:28
  • I just need application names accesed in that interval. – Kishor Dec 06 '14 at 21:53
  • Did you check my answer? The application though have a bug. not in the approach but it get destroyed after opening a lot of programs. calling the method from a service would solve the problem. and to be sent directly to a web service. or saving it on the device some where. my app display them on list view for testing purpose. it will get lost any way from the UI. even if we have a service. we need to store them. – hasan Dec 12 '14 at 21:47
  • @hasan83 thanks for your answer, but at android 5 `getRecentTasks()` is deprecated for user privacy. Is there any other solutions for this. – Kishor Dec 13 '14 at 10:58
  • Ya thats true I know about that. so far I didn't investigate. but i don't' think so. I will investigate and update my answer regarding. – hasan Dec 13 '14 at 12:03

2 Answers2

7

Update:

In android 5.0 an alternative of getRecentTasks() method is getAppTasks.

Code Sample:

private void listTasks() throws PackageManager.NameNotFoundException {
  ActivityManager mgr = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
  List<ActivityManager.AppTask>  tasks = mgr.getAppTasks();
  String packagename;
  String label;
  for (ActivityManager.AppTask task: tasks){
    packagename = task.getTaskInfo().baseIntent.getComponent().getPackageName();
    label = getPackageManager().getApplicationLabel(getPackageManager().getApplicationInfo(packagename, PackageManager.GET_META_DATA)).toString();
    Log.v(TAG,packagename + ":" + label);
  }
}

Original Answer:

Introduction

The ActivityManager class provides two methods that returns such an information. Choosing getRecentTasks or getRunningTasks method would be appropriate since the returned tasks list is not our goal anyway. but, It will be used as a reference point on the way to determine the desired list.

Code Sample:

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RecentTaskInfo> activitys = activityManager.getRecentTasks(Integer.MAX_VALUE, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
for (int i = 0; i < activitys.size(); i++) {
    RecentTaskInfo activity = activitys.get(i);
    activity.baseIntent.getComponent().getPackageName();
}

Filtering: This list includes all type of tasks including system tasks.

Code Sample:

if (activity.baseIntent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
    // This is an application.
    getPackageManager()
        .getApplicationLabel(getPackageManager()
        .getApplicationInfo(activity.baseIntent.getComponent()
        .getPackageName(), PackageManager.GET_META_DATA)); // application name
}

This is the same list that will display on long pressing the home button.

Abstract Approach: (Explanation comes later)

To determine the desired list within the specified time that we will call (period). The recent tasks list will be asked for in the beginning of the period and after each smaller period within the period that we will call interval.

The recent apps. list fetched after the first interval will contain three type of apps. Old-apps, which are not in our interest, New-launched and Re-launched apps. The reason behind choosing the abstract approach is detecting the Re-launched apps.

Detecting New-launched Apps:

Those are the apps. that simply didn't appear in the very first fetched list. (before the period).

Explanation by examples why this approach:

  • It would be a great idea to consider any app. appeared before your app. in a later fetched list a re-launched app. since when we started the operation, which is from inside the app, your app. was on top of the list.

enter image description here

  • But, your app. may step down from top and gets back to it within the interval time. (Facebook > Twitter > Your App).

enter image description here

  • In a later fetched list another app. may get on top. taking it as a reference will fail too for the same reason your app. failed as a reference.

Winning Approach:

The list fetched before an interval will be the reference for the list fetched after the interval. the re-launched apps. would be the apps. appeared before the first-ordered-sub-list(fosl).

enter image description here

All the apps. before the fosl are re-launched not only What's app. And, It can be proven easily. There is no way to rearrange the apps on top of the fosl in a way that some of them may have been re-launched without the fosl get changed (get bigger to include more apps). you can exercise it.

fosl approach will work too even if user removed some of the apps. from the list manually within the interval. only removed apps will not be detect if they didn't got detected in a previous interval. but, it will not affect the fosl approach for the rest in the list. same thing if user cleared all the list, only the cleared apps. will not detected and not the ones launched after within the same interval.

Why intervals? because for such a long period user can open and relaunch apps. then, clear the list or remove some.

Small intervals would also make it so hard on the user to open any top sublist with the same order again which is the only weakness of the fosl approach.

Sample Code: (fosl)

public int getIndexOfFirstAppBeforeFOSL(ArrayList<App> recentApps) {
    int i=previousRecentApps.size()-1, j = recentApps.size()-1;
    for (; i>=0 && j>=0 ; i--) {
        App app = previousRecentApps.get(i);
        if (app.equals(recentApps.get(j))) {
            j--;
        } else {
            // this application got re-launched and therefore it changed it place in list.
            // or removed manually by user.
        }
    }

    return j;
}

I created a GitHub project for the application. check it out, and report bugs if any.

Missing to detect one or two apps for the weakness we mentioned want really going to effect the research result your are getting from collecting apps. getting launched from a big number of user. if that what are you doing anyway. Otherwise, your app. can frequently get new launched app. and notify the user about it.

hasan
  • 23,815
  • 10
  • 63
  • 101
  • Check this out, It's late night here. I made last minutes modifications to code project. all well as I can say. The approach theoretically looks perfect. report me with bugs in the project code. I will fix. interesting question anyway. – hasan Dec 11 '14 at 01:03
  • 2
    Note that your technique will no longer work as of Android 5.0, when `getRecentTasks()` no longer does what you need it to do. – CommonsWare Dec 13 '14 at 00:14
  • Yes that's true. but It will still work for like 80% of devices for maybe a year and less percentage later. I will update my answer if there a solution on 5.0 or not. – hasan Dec 13 '14 at 12:05
  • Thank you very much for not forgetting to assign the bounty :) but, I don't see the green check mark that indicate that the answer is accepted! – hasan Dec 15 '14 at 16:00
-1

Yes.It is possible.Your service needs to be run for every 5 secs.In that service,you have to write the logic for whichever apps is accessed by user.You have to use ActivityManager class for getting running applications.

kanivel
  • 1,635
  • 3
  • 14
  • 14