上篇文章已经解释了Android5.1系统是如何获取打开次数(如果不懂可以先读我上篇文章http://blog.youkuaiyun.com/elder_sword/article/details/50809642),但最后我们用系统api拿到的并不是精确的打开次数,有人可能会问,不就一个打开次数嘛,我去写个service,不断去扫栈顶activity获取包名来监听次数不可以吗?当然可以,只要你能接受。这里我接着上次的问题,怎么才能拿到精确的打开次数呢?
最终我们分析得出是因为相同的应用可能在打开的时候会同时打开多个activity,其实说简单也很简单,就是每个包名只取一个class去当作打开的唯一标识
下面我写几个测试方法,分别打印出我们自己过滤的和系统的
public class MainActivity extends Activity {
private Button bt_statistics;
private UsageStatsManager mUsmManager;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
public final String TAG_U = "StatsTest_Usage";
public final String TAG_E = "StatsTest_Events";
public final String TAG_A = "StatsTest_Aggregate";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_statistics = (Button) findViewById(R.id.bt_statistics);
mUsmManager = getUsageStatsManager();
bt_statistics.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (getUsageList().isEmpty()) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
} else {
printCurrentUsageStatus();
}
}
});
}
public void printCurrentUsageStatus() {
try {
printEvents();
printAggregatedStats();
printUsageStats(getUsageList());
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressWarnings("ResourceType")
private UsageStatsManager getUsageStatsManager() {
UsageStatsManager usm = (UsageStatsManager) getSystemService("usagestats");
return usm;
}
public void printEvents() throws NoSuchFieldException {
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1);
long startTime = calendar.getTimeInMillis();
Log.d(TAG_U, "Range start:" + dateFormat.format(startTime));
Log.d(TAG_U, "Range end:" + dateFormat.format(endTime));
UsageEvents events = mUsmManager.queryEvents(startTime, endTime);
HashMap<String, String> pkgNames = new HashMap<String, String>();
HashMap<String, Integer> times = new HashMap<String, Integer>();
while (events.hasNextEvent()) {
UsageEvents.Event e = new UsageEvents.Event();
events.getNextEvent(e);
if (e != null && e.getEventType() == 1) {
String packageName = e.getPackageName();
String className = e.getClassName();
String clazz = pkgNames.get(packageName);
if (clazz == null || clazz.equals("")) {
pkgNames.put(packageName, className);
times.put(packageName, 1);
} else if (clazz.equals(className)) {
times.put(packageName, times.get(packageName) + 1);
}
Log.d(TAG_U, "Event:----lasttime = " + DateUtils.formatSameDayTime(e.getTimeStamp(), System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM)
+ "---- pkgname = " + packageName
+ "----class = " + e.getClassName()
+ "----type =" + e.getEventType());
}
}
Log.d(TAG_U, times + "");
}
public void printUsageStats(List<UsageStats> usageStatsList) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException {
for (UsageStats u : usageStatsList) {
Log.d(TAG_E, "Pkg = " + u.getPackageName()
+ "----ForegroundTime = " + DateUtils.formatElapsedTime(u.getTotalTimeInForeground() / 1000)
+ "----lasttimeuser = " + DateUtils.formatSameDayTime(u.getLastTimeUsed(), System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM)
+ "----times = " + u.getClass().getDeclaredField("mLaunchCount").getInt(u));
}
}
public void printAggregatedStats() throws NoSuchFieldException, IllegalAccessException {
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1);
long startTime = calendar.getTimeInMillis();
Map<String, UsageStats> map = mUsmManager.queryAndAggregateUsageStats(startTime, endTime);
for (Map.Entry<String, UsageStats> entry : map.entrySet()) {
UsageStats stats = entry.getValue();
Log.d(TAG_A,"key= " + entry.getKey() + "Pkg = " + stats.getPackageName()
+ "----ForegroundTime = " + DateUtils.formatElapsedTime(stats.getTotalTimeInForeground() / 1000)
+ "----lasttimeuser = " + DateUtils.formatSameDayTime(stats.getLastTimeUsed(), System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM)
+ "----times = " + stats.getClass().getDeclaredField("mLaunchCount").getInt(stats));
}
}
private List<UsageStats> getUsageList() {
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1);
long startTime = calendar.getTimeInMillis();
List<UsageStats> usageList = mUsmManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
return usageList;
}
}
这里我自己过滤的是先拿到系统event列表,这个列表可以看到并没像queryUsageStats方法传intervalType参数,但其实内部是写死了intervalType 用INTERVAL_BEST,主要原因是event列表里的东西只会保留几天的,而你拿到的只是当天的event。我们可以看一下log
StatsTest_Usage
03-05 17:22:23.773 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Range start:3-5-2015 17:22:23
03-05 17:22:23.773 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Range end:3-5-2016 17:22:23
03-05 17:22:23.786 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午9:03:09---- pkgname = com.android.mms----class = com.android.mms.ui.DialogModeActivity----type =1
03-05 17:22:23.787 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:28:13---- pkgname = com.android.mms----class = com.android.mms.ui.DialogModeActivity----type =1
03-05 17:22:23.787 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:28:17---- pkgname = com.android.pplauncher3----class = com.android.pplauncher3.Launcher----type =1
03-05 17:22:23.787 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:28:31---- pkgname = com.android.settings----class = com.android.settings.Settings----type =1
03-05 17:22:23.788 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:28:33---- pkgname = com.android.pplauncher3----class = com.android.pplauncher3.Launcher----type =1
03-05 17:22:23.788 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:28:41---- pkgname = com.tencent.mobileqq----class = com.tencent.mobileqq.activity.SplashActivity----type =1
03-05 17:22:23.789 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:29:02---- pkgname = com.tencent.mobileqq----class = cooperation.qzone.QzoneGPUPluginProxyActivity----type =1
03-05 17:22:23.789 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:30:11---- pkgname = com.tencent.mobileqq----class = com.tencent.mobileqq.activity.QQBrowserDelegationActivity----type =1
03-05 17:22:23.790 2604-2604/com.elder.usagetest D/StatsTest_Usage﹕ Event:----lasttime = 上午10:30:11---- pkgname = com.tencent.mobileqq----class = com.tencent.mobileqq.activity.QQBrowserActivity----type =1
03-