Android UsageStats:应用根据启动次数、启动时间、应用名称排序
Android 7.1.1
developers/samples/android/system/AppUsageStatistics/Application/src/main/java/com/example/android/appusagestatistics/AppUsageStatisticsFragment.java
packages/apps/Settings/src/com/android/settings/UsageStatsActivity.java
/**
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/ package com.android.settings; import android.app.Activity;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView; import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map; /**
* Activity to display package usage statistics.
*/
public class UsageStatsActivity extends Activity implements OnItemSelectedListener {
private static final String TAG = "UsageStatsActivity";
private static final boolean localLOGV = false;
private UsageStatsManager mUsageStatsManager;
private LayoutInflater mInflater;
private UsageStatsAdapter mAdapter;
private PackageManager mPm; public static class AppNameComparator implements Comparator<UsageStats> {
private Map<String, String> mAppLabelList; AppNameComparator(Map<String, String> appList) {
mAppLabelList = appList;
} @Override
public final int compare(UsageStats a, UsageStats b) {
String alabel = mAppLabelList.get(a.getPackageName());
String blabel = mAppLabelList.get(b.getPackageName());
return alabel.compareTo(blabel);
}
} public static class LastTimeUsedComparator implements Comparator<UsageStats> {
@Override
public final int compare(UsageStats a, UsageStats b) {
// return by descending order
return (int)(b.getLastTimeUsed() - a.getLastTimeUsed());
}
} public static class UsageTimeComparator implements Comparator<UsageStats> {
@Override
public final int compare(UsageStats a, UsageStats b) {
return (int)(b.getTotalTimeInForeground() - a.getTotalTimeInForeground());
}
} // View Holder used when displaying views
static class AppViewHolder {
TextView pkgName;
TextView lastTimeUsed;
TextView usageTime;
} class UsageStatsAdapter extends BaseAdapter {
// Constants defining order for display order
private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1;
private static final int _DISPLAY_ORDER_APP_NAME = 2; private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
private LastTimeUsedComparator mLastTimeUsedComparator = new LastTimeUsedComparator();
private UsageTimeComparator mUsageTimeComparator = new UsageTimeComparator();
private AppNameComparator mAppLabelComparator;
private final ArrayMap<String, String> mAppLabelMap = new ArrayMap<>();
private final ArrayList<UsageStats> mPackageStats = new ArrayList<>(); UsageStatsAdapter() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -5); final List<UsageStats> stats =
mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
cal.getTimeInMillis(), System.currentTimeMillis());
if (stats == null) {
return;
} ArrayMap<String, UsageStats> map = new ArrayMap<>();
final int statCount = stats.size();
for (int i = 0; i < statCount; i++) {
final android.app.usage.UsageStats pkgStats = stats.get(i); // load application labels for each application
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0);
String label = appInfo.loadLabel(mPm).toString();
mAppLabelMap.put(pkgStats.getPackageName(), label); UsageStats existingStats =
map.get(pkgStats.getPackageName());
if (existingStats == null) {
map.put(pkgStats.getPackageName(), pkgStats);
} else {
existingStats.add(pkgStats);
} } catch (NameNotFoundException e) {
// This package may be gone.
}
}
mPackageStats.addAll(map.values()); // Sort list
mAppLabelComparator = new AppNameComparator(mAppLabelMap);
sortList();
} @Override
public int getCount() {
return mPackageStats.size();
} @Override
public Object getItem(int position) {
return mPackageStats.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
AppViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.usage_stats_item, null); // Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new AppViewHolder();
holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
holder.lastTimeUsed = (TextView) convertView.findViewById(R.id.last_time_used);
holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (AppViewHolder) convertView.getTag();
} // Bind the data efficiently with the holder
UsageStats pkgStats = mPackageStats.get(position);
if (pkgStats != null) {
String label = mAppLabelMap.get(pkgStats.getPackageName());
holder.pkgName.setText(label);
holder.lastTimeUsed.setText(DateUtils.formatSameDayTime(pkgStats.getLastTimeUsed(),
System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM));
holder.usageTime.setText(
DateUtils.formatElapsedTime(pkgStats.getTotalTimeInForeground() / 1000));
} else {
Log.w(TAG, "No usage stats info for package:" + position);
}
return convertView;
} void sortList(int sortOrder) {
if (mDisplayOrder == sortOrder) {
// do nothing
return;
}
mDisplayOrder= sortOrder;
sortList();
}
private void sortList() {
if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
if (localLOGV) Log.i(TAG, "Sorting by usage time");
Collections.sort(mPackageStats, mUsageTimeComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_LAST_TIME_USED) {
if (localLOGV) Log.i(TAG, "Sorting by last time used");
Collections.sort(mPackageStats, mLastTimeUsedComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
if (localLOGV) Log.i(TAG, "Sorting by application name");
Collections.sort(mPackageStats, mAppLabelComparator);
}
notifyDataSetChanged();
}
} /** Called when the activity is first created. */
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.usage_stats); mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mPm = getPackageManager(); Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
typeSpinner.setOnItemSelectedListener(this); ListView listView = (ListView) findViewById(R.id.pkg_list);
mAdapter = new UsageStatsAdapter();
listView.setAdapter(mAdapter);
} @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mAdapter.sortList(position);
} @Override
public void onNothingSelected(AdapterView<?> parent) {
// do nothing
}
}
ENV:Android 4.4.4
1.
packages/apps/Settings/src/com/android/settings/UsageStats.java
import com.android.internal.app.IUsageStats;
import com.android.settings.R;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import com.android.internal.os.PkgUsageStats;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener; /**
* Activity to display package usage statistics.
*/
public class UsageStats extends Activity implements OnItemSelectedListener {
private static final String TAG="UsageStatsActivity";
private static final boolean localLOGV = false;
private Spinner mTypeSpinner;
private ListView mListView;
private IUsageStats mUsageStatsService;
private LayoutInflater mInflater;
private UsageStatsAdapter mAdapter;
private PackageManager mPm; public static class AppNameComparator implements Comparator<PkgUsageStats> {
Map<String, CharSequence> mAppLabelList;
AppNameComparator(Map<String, CharSequence> appList) {
mAppLabelList = appList;
}
public final int compare(PkgUsageStats a, PkgUsageStats b) {
String alabel = mAppLabelList.get(a.packageName).toString();
String blabel = mAppLabelList.get(b.packageName).toString();
return alabel.compareTo(blabel);
}
} public static class LaunchCountComparator implements Comparator<PkgUsageStats> {
public final int compare(PkgUsageStats a, PkgUsageStats b) {
// return by descending order
return b.launchCount - a.launchCount;
}
} public static class UsageTimeComparator implements Comparator<PkgUsageStats> {
public final int compare(PkgUsageStats a, PkgUsageStats b) {
long ret = a.usageTime-b.usageTime;
if (ret == 0) {
return 0;
}
if (ret < 0) {
return 1;
}
return -1;
}
} // View Holder used when displaying views
static class AppViewHolder {
TextView pkgName;
TextView launchCount;
TextView usageTime;
} class UsageStatsAdapter extends BaseAdapter {
// Constants defining order for display order
private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
private static final int _DISPLAY_ORDER_LAUNCH_COUNT = 1;
private static final int _DISPLAY_ORDER_APP_NAME = 2; private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
private List<PkgUsageStats> mUsageStats;
private LaunchCountComparator mLaunchCountComparator;
private UsageTimeComparator mUsageTimeComparator;
private AppNameComparator mAppLabelComparator;
private HashMap<String, CharSequence> mAppLabelMap; UsageStatsAdapter() {
mUsageStats = new ArrayList<PkgUsageStats>();
mAppLabelMap = new HashMap<String, CharSequence>();
PkgUsageStats[] stats;
try {
stats = mUsageStatsService.getAllPkgUsageStats();
} catch (RemoteException e) {
Log.e(TAG, "Failed initializing usage stats service");
return;
}
if (stats == null) {
return;
}
for (PkgUsageStats ps : stats) {
mUsageStats.add(ps);
// load application labels for each application
CharSequence label;
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(ps.packageName, 0);
label = appInfo.loadLabel(mPm);
} catch (NameNotFoundException e) {
label = ps.packageName;
}
mAppLabelMap.put(ps.packageName, label);
}
// Sort list
mLaunchCountComparator = new LaunchCountComparator();
mUsageTimeComparator = new UsageTimeComparator();
mAppLabelComparator = new AppNameComparator(mAppLabelMap);
sortList();
}
public int getCount() {
return mUsageStats.size();
} public Object getItem(int position) {
return mUsageStats.get(position);
} public long getItemId(int position) {
return position;
} public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
AppViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.usage_stats_item, null); // Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new AppViewHolder();
holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
holder.launchCount = (TextView) convertView.findViewById(R.id.launch_count);
holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (AppViewHolder) convertView.getTag();
} // Bind the data efficiently with the holder
PkgUsageStats pkgStats = mUsageStats.get(position);
if (pkgStats != null) {
CharSequence label = mAppLabelMap.get(pkgStats.packageName);
holder.pkgName.setText(label);
holder.launchCount.setText(String.valueOf(pkgStats.launchCount));
holder.usageTime.setText(String.valueOf(pkgStats.usageTime)+" ms");
} else {
Log.w(TAG, "No usage stats info for package:" + position);
}
return convertView;
} void sortList(int sortOrder) {
if (mDisplayOrder == sortOrder) {
// do nothing
return;
}
mDisplayOrder= sortOrder;
sortList();
}
private void sortList() {
if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
if (localLOGV) Log.i(TAG, "Sorting by usage time");
Collections.sort(mUsageStats, mUsageTimeComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_LAUNCH_COUNT) {
if (localLOGV) Log.i(TAG, "Sorting launch count");
Collections.sort(mUsageStats, mLaunchCountComparator);
} else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
if (localLOGV) Log.i(TAG, "Sorting by application name");
Collections.sort(mUsageStats, mAppLabelComparator);
}
notifyDataSetChanged();
}
} /** Called when the activity is first created. */
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mUsageStatsService = IUsageStats.Stub.asInterface(ServiceManager.getService("usagestats"));
if (mUsageStatsService == null) {
Log.e(TAG, "Failed to retrieve usagestats service");
return;
}
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mPm = getPackageManager(); setContentView(R.layout.usage_stats);
mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
mTypeSpinner.setOnItemSelectedListener(this); mListView = (ListView) findViewById(R.id.pkg_list);
// Initialize the inflater mAdapter = new UsageStatsAdapter();
mListView.setAdapter(mAdapter);
} public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
mAdapter.sortList(position);
} public void onNothingSelected(AdapterView<?> parent) {
// do nothing
}
}
2.
frameworks/base/core/java/com/android/internal/app/IUsageStats.aidl
package com.android.internal.app; import android.content.ComponentName;
import com.android.internal.os.PkgUsageStats; interface IUsageStats {
void noteResumeComponent(in ComponentName componentName);
void notePauseComponent(in ComponentName componentName);
void noteLaunchTime(in ComponentName componentName, int millis);
PkgUsageStats getPkgUsageStats(in ComponentName componentName);
PkgUsageStats[] getAllPkgUsageStats();
}
3.
frameworks/base/core/java/com/android/internal/os/PkgUsageStats.java
package com.android.internal.os; import android.os.Parcel;
import android.os.Parcelable; import java.util.HashMap;
import java.util.Map; /**
* implementation of PkgUsageStats associated with an
* application package.
* @hide
*/
public class PkgUsageStats implements Parcelable {
public String packageName;
public int launchCount;
public long usageTime;
public Map<String, Long> componentResumeTimes; public static final Parcelable.Creator<PkgUsageStats> CREATOR
= new Parcelable.Creator<PkgUsageStats>() {
public PkgUsageStats createFromParcel(Parcel in) {
return new PkgUsageStats(in);
} public PkgUsageStats[] newArray(int size) {
return new PkgUsageStats[size];
}
}; public String toString() {
return "PkgUsageStats{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + packageName + "}";
} public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
packageName = pkgName;
launchCount = count;
usageTime = time;
componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
} public PkgUsageStats(Parcel source) {
packageName = source.readString();
launchCount = source.readInt();
usageTime = source.readLong();
final int N = source.readInt();
componentResumeTimes = new HashMap<String, Long>(N);
for (int i = 0; i < N; i++) {
String component = source.readString();
long lastResumeTime = source.readLong();
componentResumeTimes.put(component, lastResumeTime);
}
} public PkgUsageStats(PkgUsageStats pStats) {
packageName = pStats.packageName;
launchCount = pStats.launchCount;
usageTime = pStats.usageTime;
componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
} public int describeContents() {
return 0;
} public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(packageName);
dest.writeInt(launchCount);
dest.writeLong(usageTime);
dest.writeInt(componentResumeTimes.size());
for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
dest.writeString(ent.getKey());
dest.writeLong(ent.getValue());
}
}
}
4.
frameworks/base/core/java/com/android/internal/os/PkgUsageStats.aidl
package com.android.internal.os; parcelable PkgUsageStats;
Android 8.0.0

Android UsageStats:应用根据启动次数、启动时间、应用名称排序的更多相关文章
- 如何在android studio 1.0 启动时设置代理【解决WARN - ateSettings.impl.UpdateChecker - Connection failed.】
		
今天第一次用android studio,下了个比较新的1.0.1 linux版本,结果启动时老是出现以下错误: [ 6987] WARN - ateSettings.impl.UpdateCheck ...
 - Android开发之---Activity启动模式
		
在Android开发中,启动一个新的activity我们可以使用startActivity或startActivityForResult,Android系统使用栈的方式来管理一个APP的页面显示与保存 ...
 - Android中Activity的启动模式
		
简介 Android中的活动启动方式分为4种:standard, singleTop, singleTask, singleInstance.可以在AndroidManifest.xml中通过给< ...
 - 【Android】应用程序启动过程源码分析
		
在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程 ...
 - WinCE启动次数的记录
		
最近一周一直在忙于测试NAND文件系统的稳定性和可靠性,今天终于有所进展.测试组所有同事齐上阵,加上小高和我,测试了一天,都未发现问题.虽然还不能保证完全OK,但至少有所改善了. 测试组今天主要做了文 ...
 - Android应用程序进程启动过程的源代码分析
		
文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...
 - Android应用程序内部启动Activity过程(startActivity)的源代码分析
		
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6703247 上文介绍了Android应用程序的 ...
 - Android 儿子Activity在启动过程中的流程组件 && 儿子Activity在一个新的进程组件启动过程
		
1.儿子Activity在启动过程中的流程组件 在Android Activity启动过程http://blog.csdn.net/jltxgcy/article/details/35984557一文 ...
 - Android添加全屏启动画面
		
有的Android软件需要在启动的时候显示一个启动画面,可以是一张图或者一些设置什么呢,还有一个好处就是,可以趁机在后台加载数据.创建启动画面一般有两种方式:1.建立一个activity,展示启动画面 ...
 - React native 之android的图标和启动图片
		
哎哎呀呀,上篇说到了react native的IOS的图标和启动图片的设置,其实最主要的是尺寸!相应的尺寸设定好了以后就不会报错了! ok~这篇说的是React native的android的图标和启 ...
 
随机推荐
- Sencha Touch2 工作笔记
			
Sencha Touch2 工作笔记 Ext.dataview.List activate( this, newActiveItem, oldActiveItem, eOpts ) Fires whe ...
 - 用户数据验证的正确姿势之assert
			
用户数据验证灰常重要, 不用多说了, 但是实现方法(准确的说是表现形式)有很多人, 如何优雅的完成一个后端验证过滤器是一个值得考量的问题, 我尝试过许多方法, 比如validator.js模块, ex ...
 - Linux下如何查看tomcat是否启动/系统日志等
			
Linux下如何查看tomcat是否启动/系统日志等 查看tomcat是否启动 ps -ef | grep tomcat 或者 ps -ef | grep java 启动tomcat(在tomca ...
 - Session 的生命周期
			
#region EntityMap /// <summary> /// 实体类值的访问器,线程安全 /// </summary> // ...
 - easyUI datagrid 排序
			
easyUI datagrid 排序 1.首先设置datagrid属性sortName 2.设置sortOrder 3.设置remoteSort(注:此属性默认为true,如果如果是对本地数据排序必须 ...
 - Jquery 技术小结
			
前记: 现在项目中经常要用到JS去操作一些事,对整个团队开发来说,JS的书写规范和正确对开发具有较大的帮助.在一个团队中常常会发生JS书写的不统一性和游览器不兼容性等情况发生.我觉的最好的方法就是有一 ...
 - C语言 static静态变量
			
静态变量类型说明符是static. 静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在 静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间 ...
 - Linux中显示一个文件最后几行的命令
			
tail -n 20 filename说明:显示filename最后20行. Linux下tail命令的使用方法.linux tail命令用途是依照要求将指定的文件的最后部分输出到标准设备,通常是终端 ...
 - 关于MyEclipse项目的名字的修改对项目导入导出的影响
			
不要修改项目名字,不管是在MyEclipse中(.project文件里面的额name会变)还是在G:\MyEclipseData目录下(.project文件里面的额name不会变),否则导入的时候不能 ...
 - 学习 C++,关键是要理解概念,而不应过于深究语言的技术细节
			
学习 C++学习 C++,关键是要理解概念,而不应过于深究语言的技术细节. 学习程序设计语言的目的是为了成为一个更好的程序员,也就是说,是为了能更有效率地设计和实现新系统,以及维护旧系统. C++ 支 ...