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,這里我是自己理解的,代碼跟到后面能力有限,沒有找到真正的原因,還請大家諒解。