前言
v1.3.1-beta即將來襲,其中有一個新功能。用戶可以實(shí)時查看設(shè)備上的App列表。有了該功能,用戶可以快捷地根據(jù)應(yīng)用名或包名搜索對應(yīng)包信息,快捷啟動、卸載。

以往的方式
如果只是獲取app簡單的信息,我們可以使用兩種方法:
使用
adb shell pm list package
來獲取應(yīng)用列表,但是僅含包名,想獲取更多版本、中文名等等,還需要根據(jù)包名挨個使用
adb shell dumpsys package com.tencent.mm
來獲取app中文名,版本等等
但是無法獲取應(yīng)用圖標(biāo)在sdk里面自帶了aapt工具,可以解析apk文件
類似的,先查找所有包名及對應(yīng)apk位置
adb shell pm list packages -f
我們可以看到apk的位置和包名,把a(bǔ)pk文件拉取到pc本地
adb pull /data/app/com.tencent.mmxxxxxxxxxxxxxxxxxxxx==/base.apk
用aapt工具解析這個拉到本地的apk文件
aapt d badging base.apk
這樣就能獲取信息了,但是也是沒有應(yīng)用圖標(biāo)
那應(yīng)用圖標(biāo)我們怎么獲取呢?
Sonic的方式
Sonic通過Sonic助手,通過apk的形式,在設(shè)備上獲取信息。步驟如下:
- 安卓的Activity的context里邊有g(shù)etPackageManager()方法,我們可以根據(jù)該方法列出設(shè)備所有應(yīng)用。
List<PackageInfo> packages = getPackageManager().getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
- 這時候會有疑問,如果只按照第一步,會返回大量無關(guān)應(yīng)用,連同設(shè)備系統(tǒng)應(yīng)用一并返回,生成了許多無關(guān)數(shù)據(jù)。我該怎么篩選呢?
廢話不多說,直接上代碼
for (int i = 0; i < packages.size(); i++) {
PackageInfo packageInfo = packages.get(i);
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
//xxxx
}
}
ApplicationInfo.FLAG_SYSTEM的意思是獲取當(dāng)前flag的末尾,為0即為非系統(tǒng)app
- 通過loadIcon方法獲得應(yīng)用圖標(biāo)
tmpInfo.appIcon = ImgUtil.drawableToDataUri(packageInfo.applicationInfo.loadIcon(getPackageManager()));
不過應(yīng)用圖標(biāo)獲取過來是Drawable對象,我們需要將Drawable轉(zhuǎn)換為base64.
- 轉(zhuǎn)換為base64,因為我們應(yīng)用圖標(biāo)屬于一次性數(shù)據(jù),不需要持久化,所以我將畫質(zhì)降到10(滿是100),畢竟轉(zhuǎn)換為base64之后,圖標(biāo)大小會變?yōu)?.333倍,無論是前端渲染還是agent的接收都需要關(guān)注這個大小。關(guān)于ByteArrayOutputStream為什么不需要close() 點(diǎn)擊這里
public static String bitmapToDataUri(Bitmap bitmap) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 10, out);
String base64 = Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP);
return base64;
}
在Activity的onStart事件開啟一個socket,等Agent連接之后,發(fā)送所有信息給Agent,然后socket就可以斷開釋放資源了。
前端直接渲染,完成!
不過該方式還是有優(yōu)化空間,目前接收大量base64的時候,前端加載還是會有卡頓的情況,但是將二進(jìn)制發(fā)送給Agent進(jìn)行base64編碼,Agent的工作量又會增加,本地生成再pull到Agent的方式又太慢。如果你有更好的想法,歡迎一起留言討論~
噢對了,apk的開源地址: 這里