行为变更 | 了解 Android 12 中的 intent-filter

行为变更 | 了解 Android 12 中的 intent-filter

Android 12 一个重要的变更是提高应用和系统的安全性,这个变更影响了所有目标版本为 Android 12 的应用

在 AndroidManifest.xml 文件中注册的 Activity、service 和 broadcast receiver 组件如果有 intent-filter 声明都必须显式申明是否需要对外披露服务 (android:exported)。

❗️如果您的应用出现了以下错误信息,很有可能和这个变更有关。

Installation did not succeed.

The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE

List of apks:

[0] ‘…/build/outputs/apk/debug/app-debug.apk’

Installation failed due to: ‘null’

NSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI:

/data/app/vmdl538800143.tmp/base.apk (at Binary XML file line #…):

com.example.package.ActivityName: Targeting S+ (version 10000 and above) requires that an explicit

value for android:exported be defined when intent filters are present”

解决方法

要解决上述问题,您需要在 AndroidManifest.xml 文件中,为使用了 <intent-filter><activity><activity-alias><service><receiver> 组件声明 android:exported 属性。

我们非常期待收到您对这项关于本要求的反馈,如果有任何建议和想法,请填写这份 简短的调查问卷 向我们反馈,告诉我们您的应用中的哪些用例受到此变更的影响。

⚠️ 请不要 "简单粗暴" 地给这些组件直接添加 android:exported="true",您需要检查并斟酌那些加入了 intent-filter 属性的组件: 用户设备上的任何其他应用都能启动这个组件,这是否是您需要的?

判断组件能否与其他应用的组件或服务相互调用或交互,这取决于应用本身的功能、其他应用如何与本应用交互,以及可能存在的特定应用场景。这里有一些常见例子,例子中包含了 intent-filter 的建议配置以及为什么要这样设置。

为包含 <category android:name="android.intent.category.LAUNCHER" /> 的 Activity 设定 android:exported="true"

这个 Activity 可能是您应用的 MainActivity,由于 Android 上的 Launcher (桌面/启动器) 是一个很常规的应用,这个 Activity 必须设定 exported="true",否则 Launcher 应用就无法启动它。

为包含 <action android:name="android.intent.action.VIEW" /> 的 Activity 设定 android:exported="true"

这个 Activity 负责处理来自其他应用的 "open with" 操作。

为包含 <action android:name="android.intent.action.SEND" /><action android:name="android.intent.action.SEND_MULTIPLE"/> 的 Activity 设定 android:exported="true"

这个 Activity 负责处理来自其他应用分享的内容。如需了解更多,请参阅: 从其他应用接收简单的数据

为包含 <action android:name="android.media.browse.MediaBrowserService" /> 的 Service 设定 android:exported="true"

如果这是一个将应用的媒体库公开给其他应用的 Service,则需要设定为 android:exported="true",以便于其他应用连接和浏览。这个 Service 一般是通过直接或者间接继承 MediaBrowserServiceCompat 来实现的,如果不是,就没有必要设置这个。

为包含 <action android:name="com.google.firebase.MESSAGING_EVENT" /> Service 设定 android:exported="false"

这个 Service 会被 Firebase Cloud Messaging 调用,Service 需要继承 FirebaseMessagingService。这个 Service 不应该设定 android:exported="true",因为无论它的属性值是什么,Firebase 都可以启动这个 Service。如需要了解更多,请参阅: 在 Android 上开发一个基于 Firebase Cloud 的消息应用

为包含 <action android:name="android.intent.action.BOOT_COMPLETED" /> 的 Receiver 设定 android:exported="false"

因为无论是否设定 exported,系统都会向 receiver 发送对应的广播。

背景

在 Android 12 之前,有 intent-filter 属性的组件 (只有 Activity、Service 和 BroadcastReceiver) 自动被默认设定为 exported。

下面的 Activity 默认会 exported:

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

下面的 Activity 不会 exported:

<activity android:name=".MainActivity" />

这个默认的设置看起来可能合理,但这个错误可能会让应用容易受到攻击。举个例子,假设我们的应用有一个播放视频的 Activity:

<activity android:name=”.PlayVideoActivity” />

后来我们发现很多地方都需要显式地调用或启动这个 Activity,为了降低应用的耦合,我们给 Activity 添加了 intent-filter 属性,允许系统选择这个 Activity:

<activity android:name=”.PlayVideoActivity”>
    <intent-filter>
        <action android:name=”android.intent.action.VIEW” />
        <data
            android:mimeType=”video/*”
            android:scheme=”content” />
    </intent-filter>
</activity>

到这里问题就出现了,这个 Activity 设计的目的仅仅是在应用内部使用,可现在却被公开了!

如果我们的应用目标版本是 Android 12,系统会阻止这样的设置,并强制要求我们去设置 android:exported 属性。由于我们不想将 Activity 对外公开,我们可以设置 android:export=false,以确保应用的安全性。

<activity
    android:name=”.PlayVideoActivity”
    android:exported=”false”>
    <intent-filter>
        <action android:name=”android.intent.action.VIEW” />
        <data
            android:mimeType=”video/*”
            android:scheme=”content” />
    </intent-filter>
</activity>

简要总结

Android 12 一个重要的变化是提高了安全性。以 Android 12 为目标版本的应用,如果 AndroidManifest.xml 注册的 activityactivity-aliasservice 或者 broadcast receiver 组件有 intent-filter 属性,必须显式设置 android:exported 的值,否则应用将无法安装。

需要仔细考虑 android:exported 属性需要设置什么值,如果不确定,建议设置 android:exported="false"

了解更多关于 intent 和 intent-filter 的信息,请参阅: 接收一个隐式的 intent

了解更多安全和隐私上的更新,请参阅: 行为变更: 以 Android 12 为目标平台的应用->安全性

了解 Android 12 所有的更新,请参阅: Android 12 首个开发者预览版到来

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io WebMaster | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.