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的效果图:

相关推荐
程思扬5 小时前
Android笔记: 实现点击事件透传到底部
android·前端·windows·经验分享·笔记·科技·ui
带电的小王5 小时前
Android Studio:Linux环境下安装与配置
android·linux·android studio
柯南二号8 小时前
Android 实现多语言功能
android·gitee
梦浪流云8 小时前
RK3576 Android14 状态栏和导航栏增加显示控制功能
android·java
我是大佬的大佬8 小时前
在Android Studio中如何实现contentprovider实验+SQLite数据库(保姆级教程)
android·开发语言·sqlite·android studio
Grassto9 小时前
Android adb 调试,不在手机上点击信任 “允许usb调试” 即可连接的方式(手机需root)
android·adb
哥咫匙传说11 小时前
frameworks 之 AMS与ActivityThread交互
android·车载系统
大G哥11 小时前
Android 13 Hotseat定制化修改——001 hotseat布局方向
android
我命由我1234514 小时前
11-2.Android 项目结构 - themes.xml 文件基础解读
android·xml·java·java-ee·gitee·android jetpack·android runtime
还记得梦想吗14 小时前
android adb 无线连接 (wifi)
android·linux·adb