reference to : http://blog.csdn.net/elder_sword/article/details/50508257

前段时间要做一个统计手机中激活量的东东,这个统计不是单独的某个应用统计,是整个手机中所有预装应用的安装量。第一时间想到的就是后台去跑个 service,隔一段时间去扫一遍,和程序锁原理类似。但是这种方案有个弊端,大家也都了解,就是费电,当然也有优点,那就是统计精确。还有另外一种方 案,就是android自带的统计,之前也只是粗略的知道有这么回事,没有仔细看过。

具体操作,在拨号界面输入 ×#×#4636#×#×,手机会自动跳转到测试页面,然后点击使用情况统计数据,你就会看到统计的界面了。一开始感觉这个需求应该好做了,但仔细一看不 对啊,5.1的手机上面就没有打开次数这一栏了,5.0之前是好用的,没关系这里打开次数下面会说到的。说了一堆,下面上代码。

首先是UsageStatsManager这个类,先看下介绍

这里说的很清楚 需要android.permission.PACKAGE_USAGE_STATS这个权限,而且是system级别,不能在第三方应用中使用,但是在Settings里面有个选项是可以赋给你的应用查询的权限。

但前提你必须把这个权限写到你的manifest里面,否则在这个列表回看不到你的应用。这时你会发现manifest报错,导致应用不能直接运行,没关系,看代码。

<uses-permission  android:name="android.permission.PACKAGE_USAGE_STATS"  tools:ignore="ProtectedPermissions"/>

这样写可以让你代码正常运行

获取统计列表

public static List<UsageStats> getUsageStatsList(Context context){
UsageStatsManager usm = getUsageStatsManager(context);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -1);
long startTime = calendar.getTimeInMillis();
Log.d(TAG, "Range start:" + dateFormat.format(startTime) );
Log.d(TAG, "Range end:" + dateFormat.format(endTime));
List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,startTime,endTime);
return usageStatsList;
}
@SuppressWarnings("ResourceType")
private static UsageStatsManager getUsageStatsManager(Context context) {
UsageStatsManager usm = (UsageStatsManager) context.getSystemService("usagestats");
return usm;
}

这个方法第一次是空的,因为你没有权限,判断为空之后去跳转到Settings,这里大家看到了,我传的startTime,是过去一年的,而这个方法统计是有时间段的,上面的注释也有说。我统计的是过去一年到当前的所有应用的使用次数。

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);

赋完权限之后就可以正常获取到列表
打印所需要的值

public static void printUsageStats(List<UsageStats> usageStatsList) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException{
for (UsageStats u : usageStatsList){
Log.d(TAG, "Pkg: " + u.getPackageName() + "\t " + "ForegroundTime: "
+ DateUtils.formatElapsedTime(u.getTotalTimeInForeground() / 1000)+" lasttimeuser:"+DateUtils.formatSameDayTime(u.getLastTimeUsed(),
System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM)
+"times"+u.getClass().getDeclaredField("mLaunchCount").getInt(u));
}

这里大家看见了,我获取打开次数mLaunchCount的方法,没错,就是反射。到这里,一般第三方应用的需求应该可以满足了,但是系统类的应用要去手动打开权限未免有些突兀。我又跟代码到对应switch打开的代码,结合自己应用的需求

AppOpsManager mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),PackageManager.GET_PERMISSIONS);
mAppOpsManager.setMode(43, packageInfo.applicationInfo.uid,context.getPackageName(), AppOpsManager.MODE_ALLOWED);

上面这段代码可以让系统应用自动有权限。有一段setMode(43, 这里的43是抄之前switch打开的代码

致此,所有代码结束。最后顺带说一句,我这里是用来统计激活量,所以打开次数要求不是很精确,这种方式可以满足,但是要求统计非常精确的需要再考虑 一下。因为这种方式拿到的打开次数应该是和自身的其他service相关,比如已很很简单的demo,它的打开次数是精确的,但是如果带有一个 service,打开次数就会以2增长,第一次为2,第二次为4,这里我是自己理解的,代码跟到后面能力有限,没有找到真正的原因,还请大家谅解。

[Android] Android5.1系统自带的应用启动次数统计的更多相关文章

  1. Android manifest之系统自带的permission

    Android manifest之系统自带的permission 本文描述Android系统自带的permission.点击查看:“关于permission的原始定义和说明”.点击查看:“Androi ...

  2. android开发中系统自带语音模块的使用

    android开发中系统自带语音模块的使用需求:项目中需要添加语音搜索模块,增加用户体验解决过程:在网上搜到语音搜索例子,参考网上代码,加入到了自己的项目,完成产品要求.这个问题很好解决,网上能找到很 ...

  3. Android开发——去掉系统自带标题栏的几种方式

    https://blog.csdn.net/qq_28585471/article/details/75991613 今天在练习自定义标题栏(Android初级开发(四)——补充3)的过程中遇到了隐藏 ...

  4. Android 面试必备 - 系统、App、Activity 启动过程“一锅端”

    Android 系统启动过程 从系统层看: linux 系统层 Android系统服务层 Zygote 从开机启动到Home Launcher: 启动bootloader (小程序:初始化硬件) 加载 ...

  5. Android分享---调用系统自带的分享功能

    以前我们总想到友盟等平台分享功能的集成,集成这玩意还得下载对应的jar包.当然,用这些平台的分享并不是说什么好处都没有,至少人家的统计功能还是很实用的.不过有的时候我们是不需要多余功能的,只需要能分享 ...

  6. 【linux】查看linux系统自带的服务启动文件

    =============================================================== 1.查看所有启动文件 systemctl list-unit-files ...

  7. Android调用系统自带的设置界面

    Android有很多系统自带的设置界面,如设置声音,设置网络等. 在开发中可以调用这些系统自带的设置界面. 点击以下列表中的选项,就可以调出相应的系统自带的设置界面. 如点击“无线和网络设置”,可以调 ...

  8. (转)Android调用系统自带的文件管理器进行文件选择并获得路径

    Android区别于iOS的沙盒模式,可以通过文件浏览器浏览本地的存储器.Android API也提供了相应的接口. 基本思路,先通过Android API调用系统自带的文件浏览器选取文件获得URI, ...

  9. Android改变系统自带环形ProgressBar的大小

    MainActivity如下: package cc.testprogressbar; import android.os.Bundle; import android.app.Activity; / ...

随机推荐

  1. 微信电脑版微信1.1 for Windows更新 可@人/转发撤回消息/可播小视频

    微信电脑版微信1.1 for Windows发布更新了,版本号为1.1.0.18,群聊可@人/可转发撤回消息/可播小视频,功能越来越接近微信手机版了. 本次更新的一些新特点: 群聊中可以@人. 消息可 ...

  2. Ubuntu 14 修改默认打开方式

    通过研究,有三种修改方式. 方式一: 修改路径:右上角“系统设置” -> 详细信息 -> 默认应用程序 但是,有个缺陷,可修改的项比较少. 方式二: 例如,修改pdf的打开方式,只要查看任 ...

  3. lua 使用

    根据公司自身业务需要,总结常用到的lua语法 Lua中的string库 链接:http://www.jb51.net/article/57613.htm string.len(s)          ...

  4. Maven编译项目报错:某些类找不到符号

      遇到Maven在编译项目源码时候出现找不到符号错误,主要归结为以下几个问题: 1. 可能项目编码格式不统一. 2. 可能项目编码使用的JDK版本不统一. 项目可能是当前项目也可能是继承的父项目,还 ...

  5. HDU 5120 Intersection(2014北京赛区现场赛I题 计算几何)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5120 解题报告:给你两个完全相同的圆环,要你求这两个圆环相交的部分面积是多少? 题意看了好久没懂.圆环 ...

  6. iOS开发——UI基础-UIScrollView

    一.UIScrollView使用的步骤 1.创建UIScrollView 2.将需要展示的内容添加到UIScrollView中 3.设置UIScrollView的滚动范围 (contentSize) ...

  7. OpenCV进阶之路:神经网络识别车牌字符

    1. 关于OpenCV进阶之路 前段时间写过一些关于OpenCV基础知识方面的系列文章,主要内容是面向OpenCV初学者,介绍OpenCV中一些常用的函数的接口和调用方法,相关的内容在OpenCV的手 ...

  8. 子类重载父类的方法“parent::方法名”转于 恩聪PHP学习教程

    在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...

  9. windows下的getopt/getoptlong函数

    windows下的getopt/getoptlong函数 getopt/getopt_long函数是GNU C中的函数,在linux编程中很常用到.这里就不介绍了. windows下没有找到类似的函数 ...

  10. Apache Thrift 环境配置

    在 Ubuntu 14.04 下Apache Thrift 的安装方法: 1安装依赖包 sudo apt-get install libboost-dev libboost-test-dev libb ...