目的:想获取手机上所有应用的基本信息,如包名,版本号,图标什么的.
通过packageManager.getInstalledPackages方法,代码如下
@SuppressLint("QueryPermissionsNeeded")
fun getInstalledPackagesInfo(context: Context): MutableList<AppInfo> {
// app包名包含的字符
val searchStringJlc = "tencent"
// app包名包含的字符
val searchStringJls = "ali"
// 可配置的app, provider中包含的字符
val searchProviderConfig = "jlcProvider"
val packageManager = context.packageManager
//获取应用的Activity和 Content Provider 的信息
val packages =
packageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES or PackageManager.GET_PROVIDERS)
packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES)
val appList = mutableListOf<AppInfo>()
LogUtils.d("检查的包名:${packages.toString()}")
for (packageInfo in packages) {
val packageName = packageInfo.packageName
if (packageName.contains(searchStringJlc) || packageName.contains(searchStringJls,ignoreCase = true)
) {
val applicationInfo = packageManager.getApplicationInfo(packageName, 0)
val appName = packageManager.getApplicationLabel(applicationInfo).toString()
val versionName = packageInfo.versionName
val versionCode =
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
packageInfo.versionCode.toLong()
}
val authorityList = mutableListOf<String>()
// 获取应用的 Content Provider 的 authority
val providers = packageManager.queryContentProviders(
packageName,
packageInfo.applicationInfo.uid,
0
)
for (providerInfo in providers) {
if (providerInfo.authority.contains(searchProviderConfig)) {
authorityList.add(providerInfo.authority)
}
}
// 获取应用的图标
val appIcon = packageManager.getApplicationIcon(applicationInfo)
// 构造 AppInfo 对象并添加到列表
val appInfo =
AppInfo(
packageName,
appName,
versionName,
versionCode,
authorityList,
appIcon
)
LogUtils.d("收录的应用:${appInfo.toString()}")
appList.add(appInfo)
}
}
return appList
}
/**
* 应用信息
*/
data class AppInfo(
//应用包名
val packageName: String,
//应用名称
var appName: String,
// 版本名称
var versionName: String,
//版本号
var versionCode: Long,
// provider名称
var authority: MutableList<String>,
// 应用图标
var icon: Drawable,
)
问题,在Android11 设备上三方包名被加密显示了
如下,获取的包名
检查的包名:[PackageInfo{88c0018 com.miui.screenrecorder},
PackageInfo{6338a71 com.miui.contentextension},
PackageInfo{c869056 com.qualcomm.qti.qcolor},
PackageInfo{dc9d8d7 com.google.android.ext.services},
PackageInfo{c4d05c4 com.qualcomm.qti.improvetouch.service}, ....
解决办法
方法一、在AndroidManifest,xml 配置查询所有应用及与之交互
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
实测有效
方法二、如果上面权限失效,添加 queries访问指定具体应用的包名
在AndroidManifest,xml 配置访问 特定应用可访问包信息
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 联网权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android 11的 软件包可见性 权限允许你获取应用的包大小信息,以及访问与包相关的其他信息,例如应用名称、版本名称等。 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<!--针对性配置(如果上面权限失效),特定应用可访问包信息-->
<queries>
<!--微信-->
<package android:name="com.tencent.mm" />
<!--支付宝-->
<package android:name="com.eg.android.AlipayGphone" />
<package android:name="hk.alipay.wallet" />
</queries>
<application
android:name=".MApplicaiton"
...
实测有效