通過PackageManager獲得你想要的App信息!
一、前言
開門見山,開篇明義。有些場景下,我們會需要獲取一些其它 App 的各項信息,例如:App 名稱,包名、Icon 等。這個時候就需要使用到 PackageManager 這個類了。
本篇就 PackageManager 的使用,做一個詳盡的講解,助你拿到各項 App 的信息,當(dāng)然也包括一些未安裝的 App 的信息。
二、需要提前了解的一些類
當(dāng)你需要獲取到指定 App 的各項信息的時候,你需要操作一些 Android 為我們提供的對應(yīng)的 Api。
你首先需要獲取 PackageManager(以下簡稱 PM) 對象,通過 PM 對象,你就可以獲取到你需要的各項 App 的信息類。
這里涉及到的 App 信息類包括:PackageInfo、ApplicationInfo、ActivityInfo/ServiceInfo/ProviderInfo 等,還有一個 ResolveInfo 類,它比較特殊一點,不和前面的結(jié)構(gòu)為從屬關(guān)系。
這些類,都可以在根據(jù) AndroidManifest.xml 中定義的組件進行劃分,大概的結(jié)構(gòu)如下。
可以看到,它們之間的關(guān)系還它挺復(fù)雜的。
一個 PackageInfo 對應(yīng)一個 ApplicationInfo,而其中又包含若干個 ActivityInfo、ServiceInfo、ProviderInfo。
2.1 PackageManager
PackageManager 是一個抽象類,我們一般操作的 PackageManager ,實際上是它的實現(xiàn)類 ApplicationPackageManager 這個對象。
在 Context 中,就有獲取 PM 對象的方法,getPackageManager(),所以四大組件想要獲取它是非常簡單的。
PM 中,提供了非常多的方法,供我們通過不同的條件,獲取到 PackageInfo 對象、ApplicationInfo 對象等,它是本文的基礎(chǔ)。
2.2 PackageInfo
PackageInfo 從名稱上也可以看出來,它主要用于存儲獲取到的 Package 的一些信息,包括:包名(packageName)、版本號(versionCode)、版本名(versionName)。
基本上拿到了 PackageInfo ,你就可以拿到大部分此 Apk 相關(guān)的信息了。
并且,PackageInfo 中有一個 applicationInfo 的字段,是可以直接獲取到與它相關(guān)的 ApplicationInfo 對象的。
這里介紹幾個 PackageInfo 中,比較常用的字段:
- packageName:包名。
- versionCode:版本號
- versionName:版本名。
- firstInstallTime:首次安裝時間。
- lastUpdateTime:最后一次覆蓋安裝時間。
2.3 ApplicationInfo
ApplicationInfo 相對于 PackageInfo 用的會比較少一些。它主要用于獲取 Apk 定義在 AndroidManifest.xml 中的一些信息。
這里介紹幾個比價常用的:
- packageName:包名
- targetSdkVersion:目標(biāo) SDK 版本。
- minSdkVersion:最小支持 SDK 版本,有 Api 限制,最低在 Api Level 24 及以上支持。
- sourceDir:App 的 Apk 源文件存放的目錄。
- dataDir:data 目錄的全路徑。
- metaData:Manifest 中定義的 meta 標(biāo)簽數(shù)據(jù)。
- uid:當(dāng)前 App 分配的 uid。
可以看到 ApplicationInfo 涵蓋的信息,基本上都是在 AndroidManifest.xml 中定義的信息,并且有一些屬性是有 Api Level 限制的,所以不確定的屬性,提前看一下文檔,確定是否全版本支持。
2.4 ActivityInfo
ActivityInfo、ServiceInfo、ProviderInfo 這三個是平級的,熟悉的一眼就能看出來,它們就是 Android 定義的四大組件中的幾個。各自涵蓋了一部分信息。一般在外部獲取其他 App 的信息的時候,不會獲取到這么細(xì)致的數(shù)據(jù),如果有,看看這幾個類準(zhǔn)沒錯。
那么就不再費時去介紹它們了。
三、基本操作
到現(xiàn)在基本上就已經(jīng)了解到在當(dāng)前設(shè)備上獲取到 Apk 信息的各項類了。
直接擺源碼說屬性有點枯燥。接下來我們就帶著實際問題,來看看具體如何使用 PM。
3.1 獲取所有安裝的 App
如果想要獲取當(dāng)前設(shè)備上已經(jīng)安裝的所有 App,可以使用 getInstalledPackages() 方法獲取到它所有的已安裝 App 的 PackageInfo 。
PackageManager 中,很多方法都會需要傳遞一個 flags 的字段,它表示你當(dāng)前需要獲取到的 App 的信息。取值范圍有挺多的,獲取不同的信息使用不同的 Flags,通常如果沒有額外的要求,直接使用 GET_ACTIVITYS 即可。
3.2 判斷 App 是否安裝
這里主要說的是通過包名,判斷 App 是否安裝在當(dāng)前設(shè)備上。
最簡單的邏輯就是去獲取 PackageInfo ,如果能拿回來數(shù)據(jù),就說明是有安裝的。
3.3 通過包名獲取PackageInfo
其實前面判斷 App 是否安裝的時候,就已經(jīng)獲取到了 PackageInfo 信息,這里只需要將它返回出去即可。
3.4 獲取版本號和版本名
這里只需要根據(jù) PackageInfo 中的字段,獲取到對應(yīng)的值就好了。
3.5 獲取 App 的名稱
獲取 App 的名稱,就需要用到 ApplicationInfo 這個對象了,其中 loadLabel() 方法返回的,就是 App 的名稱。
3.6 獲取 App 的 Icon
在 ApplicationInfo 中,還可以通過 loadIcon() 獲取到 App 的 Icon。它返回的是一個 Drawable 對象,可以直接使用。
3.7 根據(jù)Apk 文件,獲取 PackageInfo
前面介紹的方法,都是基于一個已安裝的 App 的包名,來獲取額外的信息。
但是有時候,我們只有一個未安裝的 Apk 文件,想要解析出 Apk 文件中的額外信息,PM 中,也有對應(yīng)的 Api。非常的方便,直接使用 getPackageArchiveInfo() 即可。
只要拿到這個 Apk 文件相關(guān)的 PackageInfo 信息,就有辦法拿到其他的名稱、icon 、版本號、版本名、包名等信息。和前面介紹的例子類似,這里就不再一一列舉了。
四、查缺補漏
整體來說,到這里已經(jīng)講解清楚如何使用 PM 獲取 App 的基本信息。
但是并不包含 App 在運行時的一些內(nèi)存的情況,哪些數(shù)據(jù)你想獲取,單單依靠 PackageManager 是做不到的,就不再這里展開說了,有機會再詳細(xì)說明一下。
還有就是,PM 中,很多方法,都是有可能觸發(fā) 『Package manager has died』這個 RuntimeException 的,其實就是很多個線程在頻繁調(diào)用。如果想要避免,加鎖加緩存即可。具體的情況,可以看看我之前的文章《PackageManager可以亂用嗎?》。
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉(zhuǎn)載請通過微信公眾號聯(lián)系作者獲取授權(quán)】