Android Package的使用情况统计
来源:互联网 发布:十几万买域名 编辑:程序博客网 时间:2024/05/16 04:41
In developing PhoneLab Conductor, I need to get various statistics about a installed package to determine if a app is actively used by participant. For example, for interactive apps, I’d like to know how many times the user launches the app, and how long user actively interact with the app. For background apps (e.g., data collection), I’d like to know how long the background service has been running.
There is this dumpsys tool in Android which will provide various information about the status of the system, including package statistics.
Here is the sample output.
root@android:/ # dumpsys usagestatsDate: 20140402 com.android.launcher: 2 times, 43748 ms com.android.launcher2.Launcher: 2 starts com.tencent.mm: 1 times, 167750 ms com.tencent.mm.ui.chatting.ChattingUI: 4 starts, 1000-1500ms=2, 4000-5000ms=1 com.tencent.mm.ui.tools.ImageGalleryUI: 1 starts, 250-500ms=1 com.tencent.mm.ui.LauncherUI: 4 starts, 2000-3000ms=1 com.tencent.mm.ui.friend.FMessageConversationUI: 1 starts, 250-500ms=1 com.android.settings: 2 times, 93065 ms com.android.settings.Settings: 2 starts com.android.settings.SubSettings: 2 starts, 250-500ms=1, 500-750ms=2 com.google.android.gm: 1 times, 11396 ms com.google.android.
At first glance, this is a perfect fit for my purpose. But there’re two problems.
- This command needs to be run in shell. How can I get these information programatically using Java code? I definitely don’t want to execute this shell command and then parse its output.
- Only interactive apps’ statistics are included. What about background apps which may don’t have an activity?
IUsageStats Service
After poking around Android Settings app’s source code, I found there is one internal interface called IUsageStats
. It’s defined in framework/base/core/java/com/android/internal/app/IUsageStats.aidl
inside AOSP tree. You can find it here
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();}
Where PkgUsageStats
class is defined in framework/base/core/java/com/android/internal/os/PkgUsageStats.java
link.
public class PkgUsageStats implements Parcelable { public String packageName; public int launchCount; public long usageTime; public Map<String, Long> componentResumeTimes; // other stuff...}
It contains all the information I need about foreground apps!
Now is the problem of how to access the internal class and interface of Android. There’s plenty way to do this. Since I have aosp source tree at hand, I just copy those two files into my project. For PkgUsageStats
, I also need to copy the aidl file (framework/base/core/java/com/android/internal/os/PkgUsageStats.aidl
).
Here is the final directory structure of my src
folder.
src/|-- com| `-- android| `-- internal| |-- app| | `-- IUsageStats.aidl| `-- os| |-- PkgUsageStats.aidl| `-- PkgUsageStats.java`-- other stuff
Here is the code snippet that get the IUsageStats
service.
private static final String SERVICE_MANAGER_CLASS = "android.os.ServiceManager";try { Class serviceManager = Class.forName(SERVICE_MANAGER_CLASS); Method getService = serviceManager.getDeclaredMethod("getService", new Class[]{String.class}); mUsageStatsService = IUsageStats.Stub.asInterface((IBinder)getService.invoke(null, "usagestats"));}catch (Exception e) { Log.e(TAG, "Failed to get service manager class: " + e); mUsageStatsService = null;}
Here I use Java reflection to get the class of android.os.ServiceManager
, which is also internal interface.
After that, you just get all the package statistics like so:
HashMap<String, PkgUsageStats> stats = new HashMap<String, PkgUsageStats>();if (mUsageStatsService != null) { try { PkgUsageStats[] pkgUsageStats = mUsageStatsService.getAllPkgUsageStats(); for (PkgUsageStats s : pkgUsageStats) { stats.put(s.packageName, s); } } catch (Exception e) { Log.e(TAG, "Failed to get package usage stats: " + e); }}
Background Service Running Time
It seems that Settings->Apps->Running Apps are already showing the information that how long a process or service has been running.
After inspecting the source code of Settings app, I found that information is coming from ActivityManager.RunningServiceInfo
. There is a field named activeSince
, which is the time when the service was first made active.
=== UPDATE ===
It seems the reflection need system permission (I haven’t tested yet). Since we build our own platform, it’s not a problem–we just sign our apk with the platform key and declare our app’s user as system in AndroidManifest.xml
.
转自:http://jhshi.me/2014/04/02/get-package-usage-statistics-in-android/
1
android:sharedUserId="android.uid.system"
But if you don’t have the platform key, then this approach probably won’t work. The other way I can think of is you run the dumpsys
command and parse the output, but it still requites root permission.
- Android Package的使用情况统计
- 监控表使用情况的Package
- android应用使用情况统计实现
- Android 5.0 应用使用情况统计信息
- ORACLE空间使用情况统计的SQL
- 统计数据库表使用的情况
- android 查看电量情况,手机信息,电池历史记录,使用情况统计 ,wifi 使用情况
- 在线使用情况统计
- Android 获取手机整体流量使用情况以及某个应用的流量的统计
- ROM,RAM使用情况统计
- bharry's Weblog: 微软内部TFS 使用情况的统计
- 统计sql server数据库的每一个表格使用情况
- linux统计磁盘的使用情况 df du
- 统计本机内存情况和使用状况的脚本
- Linux,du、df统计的硬盘使用情况不一致问题
- Linux,du、df统计的硬盘使用情况不一致问题
- 使用友盟统计情况下的 多渠道打包配置
- AppUasge统计app的使用情况,启动次数,启动时间
- Android Linux调试工具的使用
- Object-C Block的实现方式
- 读取注册表键值
- iOS 检测版本更新
- UIWebView 与JS的交互2
- Android Package的使用情况统计
- C#针对datagridview 操作
- Object C 预处理程序
- Android:浅谈WebView
- 如何获取android控件的高度
- swift中类和结构体的区别
- ios url缓存策略——NSURLCache、 NSURLRequest
- java输入输出流实例
- Android:WebView全面详解