明确Android的intent(-filters)

评论 7 浏览 0 2021-02-19

Android 12 即将发生一项重要变化,它提高了应用程序和平台的安全性。此更改会影响所有 以 Android 12 为目标平台的应用。

具有声明的intent-filters的Activities, services, and broadcast receivers,现在必须明确地声明它们是否应该被导出。

❗️如果您的应用因这些错误消息而失败,则很可能与此更改有关。

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’

或者

INSTALL_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”

修复

这些错误的解决方法是在任何<activity><activity-alias><service><receiver>组件中添加android:exported的属性,这些组件在应用程序AndroidManifest.xml文件中声明了<intent-filter>

⚠️ 不要只是将android:exported=”true”添加到所有这些组件中!检查每个包含<intent-filter>定义的组件,并问自己:“我是否希望安装在某人设备上的任何应用程序都能够启动该组件?”。

这个问题的答案取决于应用程序的作用、其他应用程序如何与之互动,以及其他应用程序的具体考虑。以下是一些常见的意图过滤器的例子,并附有建议值和对为什么选择它的解释。

<category android:name=”android.intent.category.LAUNCHER” />的Activity。android:exported=”true”

这可能是你的应用程序的MainActivity,由于安卓上的启动器可能是一个普通的应用程序,这个活动必须被导出,否则启动器将无法启动它。

<action android:name=”android.intent.action.VIEW” />的Activity。android:exported=”true”

该活动负责处理来自其他应用程序的 "与其他应用程序一起打开 "动作。

<action android:name=”android.intent.action.SEND” /><action android:name=”android.intent.action.SEND_MULTIPLE”/>的Activity。android:exported=”true”

这个活动负责处理其他应用程序与它共享的内容。参见从其他应用程序接收简单数据

<action android:name=”android.media.browse.MediaBrowserService” />的Service。android:exported=”true”

如果这是一个将应用程序的媒体库暴露给其他应用程序的Service,那么它应该被导出,以允许其他应用程序连接并浏览该库。该服务可能直接或间接地扩展了 MediaBrowserServiceCompat。如果不是这样,那么可能就没有必要导出它。

<action android:name=”com.google.firebase.MESSAGING_EVENT” />的Service。android:exported=”false”

这是Firebase云信息服务将调用的服务,应该扩展FirebaseMessagingService。这个服务应该被导出,因为无论它是否被导出,Firebase都能启动这个组件。更多信息,请参见在Android上设置一个Firebase云消息客户端应用

接收器Receiver上有<action android:name=”android.intent.action.BOOT_COMPLETED” />android:exported=”false”

因为系统正在向广播接收器传递这个动作,所以无论它是否被导出,它都可以这样做。

背景介绍

在Android 12之前,声明了intent-filter的组件(仅限activites, services, and broadcast receivers )会自动导出。

该activity默认为导出。

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

这项activity未被导出。

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

虽然这似乎是一个合理的默认值,但这里的错误可能会使应用程序受到攻击。例如,假设我们的应用程序有一个播放视频的活动。

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

后来我们发现,我们从很多地方明确地链接到这个活动,因此,为了让我们的应用程序更加松散地耦合,我们改变了我们的活动,使其包括一个intent-filter,以允许系统选择该活动。

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

突然间,我们遇到了一个问题。我们的活动只被设计为由我们的应用程序内部使用,但现在却被导出了!这就是为什么我们的活动会被导出。

一旦我们以Android 12为目标,系统将通过要求我们明确android:exported的值来防止这种情况。在这种情况下,我们不希望它被导出,所以我们可以设置该属性,并保持我们的应用程序安全。

<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>

TLDR

为了提高安全性,安卓12将有一个重要的变化。以该版本为目标的应用程序将需要明确声明任何activityactivity-aliasservice或广播receiverandroid:exported属性的值,这些文件在其AndroidManifest.xml文件中包括一个intent-filter。如果不这样做,该应用程序将不能被安装。

仔细考虑将这个属性设置为什么值,当有疑问时,倾向于设置android:exported=”false”

有关intent和intent-filters的更多信息,请参见接收隐含的intent

有关安全和隐私的其他更新的更多信息,请参见本页面

有关Android 12中的所有变化的更多信息,请查看开发预览版1的博文!

最后更新2022-11-09
7 个评论
#1 Sam Stenner 2021-06-05

我正试图将我们的应用程序升级到目标Android 12,但我们的一些依赖项没有在其清单中明确定义导出属性(如Stripe),所以当清单被合并时,结果是一个无效的清单,所以应用程序无法安装。在这种情况下,我们应该怎么做?

Shubham Pathak 2021-06-15

我有同样的问题!此外,它是否影响我在模拟器或真实设备上运行应用程序?我试着在外部libs的缓存清单中添加exported来检查,但仍然得到错误。

#2 Abir Ahsan Tahmim 2022-05-10

你能解决这个问题吗?

https://stackoverflow.com/a/72163871/12902996

#3 Hea Ran Won 2022-02-15

你简直是救了我的命。我有这个错误已经好几个星期了!

#4 Noel Villaman 2022-01-26

是的,这很有效。如果你一直收到和我一样的信息,你必须检查你正在使用的库。我不得不删除一个库,现在一切都正常了。

#5 Ayyappa J 2021-11-12

对于BOOT_COMPLETE接收器,即使导出是false的,系统应用程序也能进行通信吗?

#6 AndroidDeveloperLB 2021-04-10

为什么会被添加?

那我怎么知道该放什么呢,除了试一试,看一看是否能正常工作?

例如,androidx.core.content.FileProvider案例是否应该被导出,或者不导出?

为什么谷歌不能为我们提供正确迁移的工具?这是一个如此重要的变化,可能会引起问题。

你可以将接收器设置为exported="false",因为 "系统正在交付这个动作",这个解释似乎不对,因为在使用 "android.intent.action.MY_PACKAGE_REPLACED "时,我看到它需要被设置为 "true"。不过不确定 "android.appwidget.action.APPWIDGET_UPDATE "的情况(似乎在设置为false时可以工作)。

这一点和包装的可见性。

我仍然不明白在许多情况下如何正确设置。这种烦人的事情...为什么还需要这些改变呢?

#7 Jorge Castillo Pérez 2021-02-20

😅

标签