清单合并失败:针对 Android 12 的应用程序 - Android Studio 错误 [重复]

Posted

技术标签:

【中文标题】清单合并失败:针对 Android 12 的应用程序 - Android Studio 错误 [重复]【英文标题】:Android Studio error: "Manifest merger failed: Apps targeting Android 12" 【发布时间】:2021-07-28 09:53:56 【问题描述】:

我已将我的模拟器版本和 android SDK 版本更新为 Android S (Android 12)。更新后,我无法运行该项目。我无法运行 hello world 项目(空项目),但我可以构建 Gradle,但无法运行该项目。我总是得到错误:

清单合并失败:针对 Android 12 及更高版本的应用 需要为 android: exported 指定显式值,当 相应的组件定义了一个意图过滤器。看 https://developer.android.com/guide/topics/manifest/activity-element#exported 了解详情。

有人可以帮帮我吗?

这是截图:

那么问题是在使用android 12 SDK时如何解决这个问题? This question 是关于将解决方案应用于此问题后的问题,并且与此问题不同。另外,这个问题早于this

【问题讨论】:

那么...您的AndroidManifest.xml 是否具有<intent-filter> 的每个组件都明确设置了android:exported 属性?请包括您的整个AndroidManifest.xml 我有同样的问题,即使我已经为所有具有 的活动以及所有接收者和提供者定义了“android:exported”。 @Stan 我遇到了同样的问题。使用“合并清单”视图检查合并清单的最终结果,以查看是否有任何组件缺少导出的值。在我的情况下,我在单独的清单中声明了一个缺少导出属性的活动。您可能需要将目标 SDK 暂时降级回 30,以便编译合并的清单。 我可以通过以下步骤调试问题:***.com/a/67668116/3274125 这能回答你的问题吗? Manifest merger failed targeting Android 12 【参考方案1】:

您需要指定android:exported="false"android:exported="true"

清单:

<activity
          android:name=".MainActivity"
          android:exported="true"
          android:theme="@style/Theme.MyApplication.NoActionBar">
          <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
    </activity>

如document中所述

如果您的应用以 Android 12 为目标平台并包含 Activity、服务或 使用意图过滤器的广播接收器,您必须明确 为这些应用组件声明 android:exported 属性。

警告:如果活动、服务或广播接收器使用意图 过滤器并且没有明确声明的值 android:exported,您的应用无法安装在运行的设备上 安卓 12。

还有check 何时对“android:exported”值使用真/假

【讨论】:

您只需要指定 android:exported。但根据您的用例,您可以将其设置为 true 或 false @MarcCalandro 我跟进了所有步骤,还包括exported = true,但发生了同样的错误。有什么建议吗? 是的,我不明白为什么这被接受为解决方案。我已经把 android:exported 放在每一个有/没有意图过滤器的活动上。还是不行。很可能是由某种依赖引起的。 这为我解决了这个问题:***.com/a/67668116/1859486 感谢 @Alix 将我指向此 ***.com/a/67668116/1859486。如果您仍然失败,那么您还需要将android:exported 添加到您的接收器***.com/a/68605049/9101876【参考方案2】:

在您的清单中,在您的默认启动活动属性中添加 android:exported="true" 或 android:exported="false"。

完成!您可以在 Android 12 上运行您的应用。

<manifest ...

<activity
        android:name=".ui.dashboard.DashboardActivity"
        android:screenOrientation="portrait"
        android:exported="true"
        android:theme="@style/AppTheme.Launcher">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

根据您的要求设置 android:exported 值。

广播接收器是否可以从其应用程序之外的非系统源接收消息 - 如果可以,则为“true”,如果不能,则为“false”。如果为“false”,则广播接收器只能接收系统发送的消息、同一应用程序的组件或具有相同用户 ID 的应用程序。

如果未指定,默认值取决于广播接收器是否包含意图过滤器。如果接收器包含至少一个意图过滤器,则默认值为“true”。否则,默认值为“false”。

此属性不是限制广播接收器外部曝光的唯一方法。您还可以使用权限来限制可以发送消息的外部实体(请参阅权限属性)。

来自Android Documentation

【讨论】:

对我不起作用。看起来我们中的一些人通过 3rd 方库遇到了这个问题,在这种情况下这不会解决它。【参考方案3】:

如果您在清单中没有找到没有标签“android:exported = false”的活动的地方,那么它很可能在您的依赖项中......为了查明确切的位置,首先降级 "compileSdkVersion" 到 30 和 "targetSdkVersion" 到 30 以便它构建。

android 
    compileSdkVersion("android-S")
    buildToolsVersion "30.0.3"

    defaultConfig 
        ...
        minSdkVersion 23
        targetSdkVersion("S")
        ...

之后,在 manifest.xml 主窗口中有一个带有“合并清单”的选项卡,您可以检查哪些活动完全没有“android:exported = false”属性。 就我而言,这是因为 3rd 方工具: build.gradle(:app):

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
//and 
debugImplementation "com.github.markzhai:blockcanary-android:1.5.0"
releaseImplementation "com.github.markzhai:blockcanary-no-op:1.5.0"

另外,对于服务,我必须添加属性

 <service
                android:name=".autofillservice.MyAutofillService"
                android:exported="true"
                android:permission="android.permission.BIND_AUTOFILL">

<service
                android:name="com.demo.myApp.my_access.MyAccessService"
                android:enabled="true"
                android:exported="true"
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

由于我的问题出在第 3 方依赖项中,并且不会很快更新,我只是在需要覆盖初始声明的地方添加了一个带有 android:exported="true" 和 exports="false" 标志的声明,也因为我在 Debug 中只需要这个依赖项,所以我在 src/debug 中添加了一个新的 AndroidManifest.xml 文件:

对于泄漏金丝雀:

<?xml version="1.0" encoding="UTF-8"?>  

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application>
        <activity
                android:name="leakcanary.internal.activity.LeakActivity"
                android:exported="true"
                android:icon="@mipmap/leak_canary_icon"
                android:label="@string/leak_canary_display_activity_label"
                android:taskAffinity="com.squareup.leakcanary.$applicationId"
                android:theme="@style/leak_canary_LeakCanary.Base">
            <intent-filter android:label="@string/leak_canary_import_hprof_file">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="file" />
                <data android:scheme="content" />
                <data android:mimeType="*/*" />
                <data android:host="*" />

                <data android:pathPattern=".*\\.hprof" />
                <data android:pathPattern=".*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.hprof" />                
            </intent-filter>
        </activity>
        <activity
                android:name="leakcanary.internal.RequestStoragePermissionActivity"
                android:excludeFromRecents="true"
                android:exported="false"
                android:icon="@mipmap/leak_canary_icon"
                android:label="@string/leak_canary_storage_permission_activity_label"
                android:taskAffinity="com.squareup.leakcanary.$applicationId"
                android:theme="@style/leak_canary_Theme.Transparent" />

        <receiver
                android:name="leakcanary.internal.NotificationReceiver"
                android:exported="false" />
    </application>
</manifest>

您不妨使用 tools:node="merge" 属性并声明 android:exported=true|false 正如@LeoFarage 所建议的那样

【讨论】:

这个!谢谢,Leak Canary 需要更新到 2.7 才能针对 Android 12 (31)。 如果原因是外部库,那我们无能为力吗?只是要求 ext-lib 的所有者在他们这边修复它? 实际上,我们明确地添加了一个活动和意图过滤器,它覆盖了依赖项中声明的内容(请参阅我编辑的评论)。就我而言,我在 src/debug 文件夹中添加了一个单独的 AndroidManifest.xml,因为我只需要该依赖项进行调试。 唯一有效的解决方案!谢谢。 您不需要完全覆盖活动条目。您可以使用tools:node="merge" 属性并声明android:exported=true|false。这应该将属性添加到最终合并的 AndroidManifest 中的目标 Activity。检查此链接以了解如何处理项目中的清单:developer.android.com/studio/build/manage-manifests【参考方案4】:

在我的项目中针对 Android 12 后,我遇到了同样的问题。问题是,这个项目很大,有多个AndroidManifest.xml 文件,而android:exported 在很多地方都丢失了。我最终创建了一个 gradle 任务来自动为我填充缺少的 android:exported 属性。我想我可以分享它,以防有人也在处理复杂的项目,也为未来的寻求者。这是link。

【讨论】:

非常感谢!您的脚本帮助我检测到 androidx.test.core-1.3.0 中没有此属性的一些活动。即使在那之后,从项目中删除这个库依赖项也不是一件容易的事......我看到 androidx 开发人员如何为 Android 12 做好准备...... 这应该有更多的赞成票。为我省去了很多麻烦【参考方案5】:

我还必须将android:exported="true" 添加到我在清单中声明的​​所有receiver 中。所以我有这样的事情:

<receiver android:name=".alarms.AlarmReScheduler"
      android:exported="true">
      <intent-filter>
          <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
          <action android:name="android.intent.action.BOOT_COMPLETED" />
          <action android:name="android.intent.action.QUICKBOOT_POWERON" />
          <action android:name="android.intent.action.PACKAGE_REPLACED" />
          <!--For HTC devices-->
          <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
      </intent-filter>
</receiver>

编辑

我认为您不应该将android:exported="true" 添加到所有内容中,您应该只在那些广播接收器需要对 Android 操作系统可见时添加它。该代码中的 Intent 过滤器意味着我希望 Android OS 唤醒我的 Android 应用并执行操作。 android.intent.action.BOOT_COMPLETED 是一个很好的例子,因为 Android 操作系统会向设备中安装的每个应用程序发送广播。所以从技术上讲,这意味着任何具有带有动作的意图过滤器的广播接收器都应该始终声明android:exported="true"。如果我犯了错误,请纠正我。

【讨论】:

【参考方案6】:

您的问题可能因以下帖子而被标记为重复:Manifest merger failed targeting Android 12,尽管您的问题是在一周前发布的。我现在看不到国旗。

为了澄清另一个答案,请注意 android:exported 应该为您的主要活动设置为 true,否则它不会启动,尽管来自 Android Studio 的令人鼓舞的“启动成功”消息,因为没有其他应用程序,甚至是 Android 系统本身,可以启动它。

<activity
    android:name=".MainActivity"
    android:exported="true"

对于其他意图隐藏在合并清单中的活动,这通常设置为 false。

【讨论】:

【参考方案7】:

在你的启动器活动中声明“android:exported”

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

如果为真“android:exported=true”,则意味着任何应用都可以访问该活动,并且可以通过其确切的类名启动。

如果为 false “android:exported = false”,则表示该活动只能由具有相同用户 ID 的同一应用程序的组件或特权系统组件启动。

更多详情请查看here。

【讨论】:

【参考方案8】:

即使我在所有活动、接收器等中添加了android:exported="true",我仍然收到此错误。对我有用的是将compileSdkVersiontargetSdkVersion 更改为30。

【讨论】:

【参考方案9】:

This will help for 2021 users.

在您的两个 build.gradle 文件之一中,您应该能够找到 targetSDK 31 行。将其更改为 30,然后进行 gradle 同步(主代码窗口上方会出现一个小栏,您可以在其中单击“同步现在”),你应该很高兴。

【讨论】:

降级不是解决办法! 为什么有人要降级??每个人都应该了解最新的 android 版本。截至我发表评论时,Android 12(API 级别 31)是当前版本。

以上是关于清单合并失败:针对 Android 12 的应用程序 - Android Studio 错误 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Android Gradle Manifest 合并失败

Android Gradle Manifest 合并失败

清单合并失败:属性 application@appComponentFactory 无法解决此问题

清单合并失败,Android Studio 中出现多个错误

清单合并失败并出现多个错误:Android Studio Java

Android Studio 错误:清单合并失败:uses-sdk:minSdkVersion