背景信息
當(dāng)我們看到別人手機里有一個酷炫的軟件的時候,也想安裝研究研究的時候,會怎么辦呢?
我和你一樣,想當(dāng)然的會問一下這個應(yīng)用叫什么名字,然后從應(yīng)用商店里面去搜索,如果幸運的話,就會從應(yīng)用商店里面給搜索出來。但是也有不幸的情況是吧?我們知道應(yīng)用商店有小米、安智、360、應(yīng)用寶等等非常的多,并不是每個 APP 都會上傳到所有的應(yīng)用商店,所以我們從自己應(yīng)用商店里搜索對應(yīng)的 APP 失敗的可能性還是有的,尤其是小眾一點的 APP。那這時候我們會怎么辦呢?
既然從應(yīng)用商店搜不到,那就直接網(wǎng)頁搜索吧,從官網(wǎng)或者是其他網(wǎng)站搜索到后下載,然后傳到手機上進(jìn)行安裝。但是這個流程好麻煩啊,還得搜索,從搜索結(jié)果中篩選出那個靠譜的下載地址,下載,傳到手機安裝。
通過這兩個方法我們總能下載安裝這個酷炫的 APP。但是針對應(yīng)用商店找不到,又不得不去網(wǎng)頁搜索的情況有沒有更便捷的方法呢?比如讓別人直接把安裝包發(fā)給自己,省下檢索的時間多好啊。別說,還真有辦法,且聽我細(xì)細(xì)道來哈。

問題分析
問題的關(guān)鍵在于獲取到已安裝應(yīng)用的信息,然后從這些信息中找到對應(yīng)的安裝包文件,找到文件后怎么發(fā)送就看大家的喜好了~
獲取已安裝應(yīng)用的信息,關(guān)鍵在于兩個類:
-
PackageInfo:這個類收集的是AndroidManifest.xml文件中的所有信息。 -
ApplicationInfo:這個類收集的是AndroidManifest.xml中<application>標(biāo)簽中的所有信息。
接下來就來看看如何實現(xiàn)吧。
代碼實現(xiàn)
首先我們來定義一個類來包裝我們想要獲取的信息。
data class InstalledAppInfo(
val packageName: String, // 包名
val versionCode: Int, // 版本號
val versionName: String, // 版本名
val firstInstallTime: Long, // 首次安裝時間
val lastUpdateTime: Long, // 最近一次更新時間
val sourceDir: String, // APK 文件位置
val label: String, // 應(yīng)用名
val icon: Drawable, // 應(yīng)用圖標(biāo)
val systemApp: Boolean // 系統(tǒng) APP
)
核心代碼很少,就一個方法而已。
fun Context.installedAppInfoList(): List<InstalledAppInfo> {
val installedAppInfoList = mutableListOf<InstalledAppInfo>()
val packageInfoList = packageManager.getInstalledPackages(0)
packageInfoList.forEach {
it.apply {
val installedAppInfo = InstalledAppInfo(
packageName = packageName,
versionCode = versionCode,
versionName = versionName,
firstInstallTime = firstInstallTime,
lastUpdateTime = lastUpdateTime,
sourceDir = applicationInfo.sourceDir,
label = packageManager.getApplicationLabel(it.applicationInfo).toString(),
icon = packageManager.getApplicationIcon(it.applicationInfo),
systemApp = !applicationInfo.sourceDir.contains("/data/app/"))
installedAppInfoList.add(installedAppInfo)
}
}
return installedAppInfoList
}
這里有幾點需要注意:
- 這個方法比較耗時,所以在自己使用的過程中不要放在主線程中。
- 系統(tǒng)應(yīng)用的判斷是通過 APK 文件的目錄進(jìn)行的。試過使用
ApplicationInfo#flags來判斷,結(jié)果不行。
至此,我們的核心工作已經(jīng)完成了,至于獲取到這些信息之后怎么去用那就發(fā)揮各自的創(chuàng)造性吧。啊哈哈哈哈~
總結(jié)
整體來說這個案例不難,但是的確實用啊。這里我給定義成了 Context 的擴展方法,可以放在自己的工具庫中,這樣就可以避免寫重復(fù)的代碼了。
最后提一句,這個案例源碼地址:https://github.com/gaoshijie365/Case-InstalledAppInfo