穆晶波 2026-02-27 04:30 采纳率: 98.5%
浏览 0
已采纳

Android 11+ 获取所有已安装应用列表需要什么权限?

在 Android 11(API 30)及更高版本中,调用 `PackageManager.getInstalledApplications()` 或 `getInstalledPackages()` 默认**仅返回当前应用自身及系统核心应用信息**,无法获取其他第三方应用列表。这是因 Google 引入了**包可见性(Package Visibility)限制**。开发者需在 `AndroidManifest.xml` 中显式声明 `` 元素,指明目标应用的包名、intent filter 或通用类别(如 `android.intent.category.BROWSABLE`)。例如,要查询所有已安装应用,需添加 ``(逐个声明)或使用 `` 等宽泛声明——但后者仍受 Play 商店政策与运行时行为约束。值得注意的是:**无需动态权限(如 QUERY_ALL_PACKAGES),但若需无差别访问全部应用(含未声明目标),必须在 `AndroidManifest.xml` 中声明 `android.permission.QUERY_ALL_PACKAGES`,且该权限为“特殊权限”,需经用户手动授予(Android 11+ 仅限特定用例,如杀毒、无障碍、设备管理类应用,普通应用极难通过 Google Play 审核)。** 常见误区是误以为 `INSTALL_PACKAGES` 或 `GET_TASKS` 仍有效——这些权限早已废弃或失效。
  • 写回答

1条回答 默认 最新

  • 冯宣 2026-02-27 04:31
    关注
    ```html

    一、现象层:API 行为突变——为什么我的应用“看不见”其他 App?

    从 Android 11(API 30)起,PackageManager.getInstalledApplications(0)getInstalledPackages(0) 的返回结果急剧收缩:仅包含自身包、系统签名应用(如 Settings、SystemUI)、以及满足 包可见性(Package Visibility)策略 的第三方应用。这不是 Bug,而是 Google 强制推行的隐私沙箱核心机制之一。

    二、机制层:Package Visibility 的三重约束模型

    • 静态声明优先:必须在 AndroidManifest.xml<queries> 根节点下显式声明目标应用能力
    • 意图导向匹配:支持 <intent> 子项(含 action/category/data),例如可发现所有浏览器:<intent><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.BROWSABLE"/></intent>
    • 包名白名单兜底:对已知关键依赖(如微信 SDK、支付宝 SDK),建议使用 <package android:name="com.tencent.mm"/> 精确声明

    三、权限层:QUERY_ALL_PACKAGES —— 特殊权限的“双刃剑”

    维度说明
    声明方式需在 AndroidManifest.xml 中添加:<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
    授予方式非运行时动态请求;需用户进入「设置 → 应用 → 权限管理 → 查看所有应用」手动开启(Android 12+ UI 路径略有差异)
    Play 商店审核红线仅允许设备管理类(Device Admin)、无障碍服务(AccessibilityService)、杀毒/安全类、家长控制、Launcher 类应用申请;普通工具/社交/电商类应用几乎 100% 拒绝上架

    四、实践层:典型 <queries> 声明模式对比

    <!-- 方案A:最小化声明(推荐)-->
    <queries>
      <package android:name="com.android.chrome"/>
      <package android:name="com.google.android.apps.nbu.files"/>
      <intent>
        <action android:name="android.intent.action.SEND"/>
        <data android:mimeType="text/plain"/>
      </intent>
    </queries>
    
    <!-- 方案B:宽泛但受限的声明(慎用)-->
    <queries>
      <intent>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.BROWSABLE"/>
      </intent>
      <intent>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent>
    </queries>

    五、误区澄清层:已被废弃/无效的旧权限与 API

    1. android.permission.GET_TASKS:API 21+ 已废弃,返回空 TaskInfo 列表
    2. android.permission.INSTALL_PACKAGES:仅用于系统签名应用,普通应用调用 PackageInstaller 仍需用户确认界面,且无法绕过 Package Visibility
    3. queryIntentActivities() 若未在 <queries> 中声明对应 intent,将返回空 List(即使目标 App 已安装)

    六、架构层:适配 Package Visibility 的现代设计范式

    graph LR A[调用 getInstalledPackages] --> B{是否需全量访问?} B -->|否| C[基于业务场景精简声明 ] B -->|是| D[评估是否符合 QUERY_ALL_PACKAGES 合规场景] D -->|是| E[申请权限 + 提交 Play 审核材料] D -->|否| F[重构方案:改用 Intent 分发/Deep Link 探测/WorkManager 周期性探测]

    七、兼容层:跨版本平滑过渡策略

    建议采用 Build.VERSION.SDK_INT >= Build.VERSION_CODES.R 分支判断,并封装统一 PackageManager 封装器:

    • Android 10 及以下:直接调用 getInstalledPackages(0)
    • Android 11+:先尝试带 PackageManager.MATCH_VISIBLE_TO_INSTANT_APPS 标志(已弃用),再 fallback 至 getInstalledPackages(PackageManager.MATCH_DEFAULT_ONLY) + 静态声明校验
    • 对关键依赖包(如分享 SDK),强制在 <queries> 中声明,避免运行时 ActivityNotFoundException

    八、审计层:自动化检测包可见性合规性的 CI/CD 实践

    可在 Gradle 构建阶段集成 Lint 规则或自定义脚本扫描:

    1. 检查 AndroidManifest.xml 是否缺失 <queries> 节点
    2. 验证所有 Intent.createChooser() 中使用的 Action/Categories 是否已在 <queries> 中覆盖
    3. 比对 APK 中 AndroidManifest.xml 与线上渠道 SDK 文档要求的包名白名单一致性

    九、生态层:Google Play 政策与 OEM 定制行为差异

    华为 HMS、小米 MIUI、OPPO ColorOS 等厂商在 Android 11+ 基础上进一步收紧可见性逻辑:

    • 部分国产 ROM 对 <queries><intent>data schema 匹配更严格(如要求完整 host/path)
    • 华为 AppGallery 要求提交 QUERY_ALL_PACKAGES 使用场景说明文档,并进行人工复审
    • 三星 One UI 12+ 引入“后台应用探测限制”,即使声明了 <package>,若目标 App 处于冻结状态,仍可能返回 null

    十、演进层:Android 14(API 34)新增约束与前瞻

    Android 14 引入 android:exported="true" 默认规则强化及 QUERY_ALL_PACKAGES 运行时二次确认弹窗:

    1. 所有 <activity>/<service> 若含 intent-filter,必须显式声明 android:exported
    2. 调用 getInstalledPackages(PackageManager.MATCH_ALL) 时,系统会触发额外权限确认对话框(即使 manifest 已声明)
    3. Google 正推动 AppSearchShortcutManager 替代传统包枚举,建议长期规划迁移路径
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 2月28日
  • 创建了问题 2月27日