如何使用后台作业在Interval中查找用户访问的应用程序列表?

Kis*_*hor 9 android android-activity android-background

我想找出apps用户在特定时间间隔内访问的列表(例如:5分钟),来自后台作业?这可能在非根android电话上吗?如果可能的话,我非常有兴趣了解答案,因为它将是一个关于android的很好的学习.

has*_*san 7

更新:

在android 5.0中,getRecentTasks()方法的替代方法是getAppTasks.

代码示例:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

原答案:

介绍

ActivityManager类提供了两种返回此类信息的方法.选择getRecentTasks或getRunningTasks方法是合适的,因为返回的任务列表无论如何都不是我们的目标.但是,它将用作确定所需列表的方式的参考点.

代码示例:

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();
}
Run Code Online (Sandbox Code Playgroud)

过滤:此列表包括所有类型的任务,包括系统任务.

代码示例:

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
}
Run Code Online (Sandbox Code Playgroud)

这与长按主页按钮时显示的列表相同.

抽象方法:(后来解释)

在我们将调用的指定时间内确定所需的列表(句点).最近的任务列表将在期间开始时以及在我们将调用间隔的期间内的每个较小的期间之后被要求.

最近的应用程序.在第一个间隔后获取的列表将包含三种类型的应用程序.旧应用程序,不符合我们的利益,新推出和重新启动的应用程序.选择抽象方法背后的原因是检测重新启动的应用程序.

检测新推出的应用:

这些是应用程序.这根本没有出现在第一个获取的列表中.(在此之前).

通过示例解释为什么这种方法:

  • 考虑任何应用程序都是一个好主意.出现在您的应用之前.在稍后提取的列表中重新启动的应用程序.从我们开始操作时开始,这是来自应用内部的应用程序.是最重要的.

在此输入图像描述

  • 但是,你的应用程序.可以从顶部退出并在间隔时间内返回到它.(Facebook> Twitter>您的应用程序).

在此输入图像描述

  • 在稍后提取的列表中另一个应用程序.可能会在顶部.将它作为参考也会因为你的应用程序的原因而失败.失败作为参考.

获胜方法:

在间隔之前获取的列表将是在间隔之后获取的列表的引用.重新启动的应用程序.将是应用程序.出现在第一个有序子列表(fosl)之前.

在此输入图像描述

所有的应用程序.在fosl重新启动之前不仅是什么应用程序.并且,它可以很容易地证明.没有办法在fosl之上重新安排应用程序,其中一些可能已经重新启动而没有改变fosl(变大以包含更多应用程序).你可以锻炼它.

即使用户删除了一些应用程序,fosl方法也会起作用.在间隔内手动从列表中.如果在之前的时间间隔内未检测到删除的应用,则只会检测到它们.但是,它不会影响列表中其余部分的fosl方法.如果用户清除了所有列表,只清除了已清除的应用程序.将无法检测到,也不会检测到在同一时间间隔内启动的那些.

为什么间隔?因为在这么长的时期内,用户可以打开并重新启动应用.然后,清除列表或删除一些.

小间隔也会使用户难以再次打开具有相同顺序的任何顶级子列表,这是fosl方法的唯一弱点.

示例代码:(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;
}
Run Code Online (Sandbox Code Playgroud)

我为应用程序创建了一个GitHub项目.检查出来,并报告错误(如果有的话).

由于缺少我们提到的弱点而无法检测到一两个应用程序,因此希望真正影响您从收集应用程序中获得的研究结果.从大量用户发布.如果你还在做什么呢.否则,你的应用程序.可以经常获得新推出的应用程序 并通知用户.

  • 请注意,当`getRecentTasks()`不再满足您的需要时,您的技术将不再适用于Android 5.0. (2认同)

kan*_*vel -1

是的。这是可能的。您的服务需要每 5 秒运行一次。在该服务中,您必须为用户访问的应用程序编写逻辑。您必须使用 ActivityManager 类来获取正在运行的应用程序。