Android 高版本如何获取App安装列表?

有个需求需要获取App内的安装列表,但是现在在高版本Android中,只能获取到一部分App效果,我获取的代码如下:

kotlin 复制代码
			val calendar = Calendar.getInstance()
			
            val packageManager = context.packageManager

            val usageStatsManager  = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager

            val queryList = usageStatsManager.queryAndAggregateUsageStats(
                calendar.timeInMillis ,
                System.currentTimeMillis()
            )

            for (entry in queryList.entries){
				val packageName = entry.value.packageName

                if (packageManager.getLaunchIntentForPackage(packageName) != null){

                    val applicationInfo = findPackageManager(packageManager, packageName) ?: continue

                    // app Name
                    val appName = applicationInfo.loadLabel(packageManager).toString()

                    // 获取 app icon
                    val appIcon = BaseSystemUtils.getAppIcon(context, packageName)
	
					BLog.d("show the data : ${appName}, ${appIcon}")             

  			}

			private fun findPackageManager(packageManager: PackageManager, packageName : String)
    : ApplicationInfo? {
        return try {
            packageManager.getApplicationInfo(packageName, 0)
        } catch (e: Exception) {
            return null
        }
    }

但是只能获取到一部分App的数据,这是因为在 Android 11(API 30)及以上的版本, 由于系统隐私政策的更新,直接使用getApplicationInfo可能无法获取应用信息,那么我们可以添加 Queries 标签进行辅助查询:

首先,我们来了解一下Queries是什么东西,它是一种在Android 11以上设定的特定的包可见机制, 不需要特定的权限,就可以查看指定的App包名.

我们看一下该如何去做:

我们需要在AndroidManifest.xml 中声明我们需要查询的App, 举个例子:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your.package.name">
    
    <!-- 不需要额外的权限声明 -->
    
    <queries>
        <!-- 声明需要查询的包名 -->
        <package android:name="com.example.app1" />
        <package android:name="com.example.app2" />
        
        <!-- 或者声明需要查询的intent -->
        <intent>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent>
    </queries>
    
    <application>
        <!-- 应用配置 -->
    </application>
</manifest>

有几个常用的用法:

  1. 查询特定包名:
xml 复制代码
<queries>
    <package android:name="com.target.app" />
</queries>
  1. 查询所有浏览器:
xml 复制代码
<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="http" />
    </intent>
</queries>
  1. 查询所有启动器应用:
xml 复制代码
<queries>
    <intent>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent>
</queries>
  1. 查询所有支持分享的应用:
xml 复制代码
<queries>
    <intent>
        <action android:name="android.intent.action.SEND" />
        <data android:mimeType="text/plain" />
    </intent>
</queries>
  1. 查询所有图片查看器:
xml 复制代码
<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:mimeType="image/*" />
    </intent>
</queries>

我们声明Queries之后,其它代码不需要改动,即可查询到所有的App数据, 因为这里我想查询的是所有启动器应用:

xml 复制代码
    <queries>
        <intent>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent>
    </queries>

我们可以看到Queries是静态声明的,是我们先声明再去获取的,不能做到动态的获取,啥意思呢?

比如我们在QUeries中定义了如下:

xml 复制代码
<queries>
    <package android:name="com.target.one.app" />
    <package android:name="com.target.two.app" />
</queries>

那么我们在查询数据时,只能查询包名com.target.one.appcom.target.two.appde数据, 不能查询新的com.target.three.app数据, 这个是一个比较硬的伤, 一般遇到这种情况,我们多数情况下会使用 Intent 来声明, 或者使用申请更高级别权限:android.permission.QUERY_ALL_PACKAGES, 当然了,这个需要更高的隐私权限, 不同的厂商对这个权限的敏感度不同.

最后,贴一张Android14获取全部App的效果图:

相关推荐
YaBingSec6 分钟前
网络安全靶场WP:Grafana 任意文件读取漏洞(CVE-2021-43798)
android·笔记·安全·web安全·ssh·grafana
YF021121 分钟前
彻底解决Android非SDK接口绕过限制的深度实践
android·google·app
IVEN_28 分钟前
Gradle 依赖下载 403 Forbidden 修复:全局镜像配置实战
android·后端
恋猫de小郭1 小时前
Flutter 3.44 发布前夕,官方宣布 SwiftPM 将完全取代 CocoaPods
android·前端·flutter
黄林晴1 小时前
重磅发布!KMP 双端订阅支付彻底封神,一套代码搞定 iOS+Android
android·kotlin
Carson带你学Android2 小时前
别再乱学了!深度解读 Google 官方发布 Android 6 大核心 Skills
android·前端·ai编程
张风捷特烈2 小时前
状态管理大乱斗#06 | Riverpod 源码评析 (下) - 外功心法
android·前端·flutter
三少爷的鞋2 小时前
Kotlin 协程 vs Java 虚拟线程:两种并发模型的对比
android
白云LDC11 小时前
Android Studio新建Vecter asset一直显示Loading icons(转圈圈)的解决办法
android·ide·android studio
Rytter14 小时前
某气骑士 libtprt.so 反 Frida 机制分析与绕过
android·安全·网络安全