獲取使用時長和點選次數
Android5.0之前,通過PkgUsageStats這個類可以統計到應用的使用情況,但這些類在SDK不公開。這裡提供一種我們的解決方案,僅供參考:
sdk上級目錄/sdk/platforms/android-19/data/layoutlib.jar
將layoutlib.jar使用User Library的方式(AndroidStudio可以使用Provided新增依賴),然後就可以使用這些類,下面給出具體實現:
// 獲取使用時長
public static long getUseDuration(String pkgName) {
// 注意適配性問題,無法找到該類
try{
com.android.internal.app.IUsageStats mUsageStatsService = com.android.internal.app.IUsageStats.Stub
.asInterface(ServiceManager.getService("usagestats"));
PkgUsageStats[] stats;
try {
stats = mUsageStatsService.getAllPkgUsageStats();
} catch (Exception e) {
LogUtil.d("no permission get use duration");
e.printStackTrace();
return 0;
}
if (stats == null) {
return 0;
}
for (PkgUsageStats ps : stats) {
if (ps.packageName.equals(pkgName)) {
return ps.usageTime;
}
}
}catch(Exception e){
}
return 0;
}
// 獲取使用次數
public static long getUseTime(String pkgName) {
// 注意適配性問題,無法找到該類
try{
com.android.internal.app.IUsageStats mUsageStatsService = com.android.internal.app.IUsageStats.Stub
.asInterface(ServiceManager.getService("usagestats"));
PkgUsageStats[] stats = null;
try {
stats = mUsageStatsService.getAllPkgUsageStats();
} catch (Exception e) {
LogUtil.d("no permission get use duration");
e.printStackTrace();
return 0;
}
if (stats == null) {
return 0;
}
for (PkgUsageStats ps : stats) {
if (ps.packageName.equals(pkgName)) {
return ps.launchCount;
}
}
}catch(Exception e){
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
走一下IUsageStats 原始碼,從getAllPkgUsageStats()方法,將帶到的資訊儲存到PkgUsageStats[]陣列中並返回;
……省略程式碼
private static final java.lang.String DESCRIPTOR = "com.android.internal.app.IUsageStats";
……省略程式碼
private android.os.IBinder mRemote;
More ...Proxy(android.os.IBinder remote) {
mRemote = remote;
}
……省略程式碼
@Override
public com.android.internal.os.PkgUsageStats[] More ...getAllPkgUsageStats() throws android.os.RemoteException{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.android.internal.os.PkgUsageStats[] _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAllPkgUsageStats, _data, _reply, 0);
_reply.readException();
//資訊的陣列
_result = _reply.createTypedArray(com.android.internal.os.PkgUsageStats.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
內部實現都是Parcel 和 Parcelable(之後補充這塊知識),簡單看一下createTypedArray()
public final <T> T[] More ...createTypedArray(Parcelable.Creator<T> c) {
int N = readInt();
if (N < 0) {
return null;
}
T[] l = c.newArray(N);
for (int i=0; i<N; i++) {
if (readInt() != 0) {
l[i] = c.createFromParcel(this);
}
}
return l;
}
//呼叫native方法
public final long More ...readInt() {
return nativeReadInt(mNativePtr);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
同流量一樣,Linux 系統下所有的資訊都是以檔案的形式存在的,所以應用程式的使用資訊也會被儲存在作業系統的檔案中,將資訊從檔案中讀出,然後就將其用Parcelable序列化的過程;最後在看一下PkgUsageStats類原始碼:
public class More ...PkgUsageStats implements Parcelable {
//包名
public String packageName;
//啟動次數
public int launchCount;
//使用時長
public long usageTime;
……省略大量程式碼
}
1
2
3
4
5
6
7
8
9
根據自身的業務邏輯,判斷包名,獲取每個應用的點選次數和使用時長;
以上只能保證寫程式碼的時候不會出現錯誤提示,但是執行起來並不會帶到想要的效果,還需要一下幾步:
在應用程式的AndroidManifest.xml中的manifest節點中加入”android:sharedUserId=”android.uid.system”這個屬性。
使用目標系統的platform金鑰來重新給apk檔案重新簽名。
如果有相應的檔案,使用如下批處理,a.apk表示你自己的apk,b.apk表示系統簽名後生成的新apk
java -jar signapk.jar -w platform.x509.pem platform.pk8 a.apk b.apk
pause
之後將新生成的檔案放到系統目錄即可統計應用的使用次數和使用時長,具體情況視程式碼邏輯而定。
搜尋
複製