android:exported 需要为 <activity> 显式指定。面向 Android 12 及更高版本的应用需要指定

Posted

技术标签:

【中文标题】android:exported 需要为 <activity> 显式指定。面向 Android 12 及更高版本的应用需要指定【英文标题】:android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify 【发布时间】:2021-10-03 20:01:47 【问题描述】:

升级到 android 12 后,应用程序无法编译。它显示

“清单合并失败,出现多个错误,请参阅日志”

合并清单中显示错误:

合并错误: 错误:需要明确指定 android:exported 为 .当相应组件定义了 Intent 过滤器时,面向 Android 12 及更高版本的应用需要为 android:exported 指定显式值。有关详细信息,请参阅 https://developer.android.com/guide/topics/manifest/activity-element#exported。主清单(此文件)

我已经用android:exported="false" 设置了所有活动。但它仍然显示这个问题。

我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="eu.siacs.conversations">

    <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission
        android:name="android.permission.READ_PHONE_STATE"
        android:maxSdkVersion="22" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    <uses-feature
        android:name="android.hardware.location"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location.gps"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location.network"
        android:required="false" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.microphone"
        android:required="false" />

    <application
        android:name=".Application"
        android:allowBackup="false"
        android:allowClearUserData="true"
        android:appCategory="social"
        android:hardwareAccelerated="true"
        android:icon="@mipmap/ic_app_launch"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:networkSecurityConfig="@xml/network_security_configuration"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_app_launch_round"
        android:theme="@style/ConversationsTheme"
        android:usesCleartextTraffic="true"
        android:windowSoftInputMode="adjustPan|adjustResize"
        tools:replace="android:label"
        tools:targetApi="q">
        <activity
            android:name=".ui.search.GroupSearchActivity"
            android:exported="true" />
        <activity
            android:name=".ui.profileUpdating.FavouritesActivity"
            android:exported="true" />
        <activity
            android:name=".ui.profileUpdating.NameActivity"
            android:exported="true" />
        <activity
            android:name=".ui.CompulsoryUpdateActivity"
            android:exported="true" />
        <activity android:name=".ui.payments.doPayment.DoPaymentActivity"
            android:exported="true" />
        <activity android:name=".ui.individualList.IndividualListActivity"
            android:exported="true" />
        <activity android:name=".ui.payments.setPayment.SetPaymentActivity"
            android:exported="true" />
        <activity android:name=".ui.login.otpActivity.OTPActivity"
            android:exported="true" />
        <activity android:name=".ui.login.loginActivity.LoginActivity"
            android:exported="true" />

        <service android:name=".services.XmppConnectionService" android:exported="true" />

        <receiver android:name=".services.EventReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.intent.action.ACTION_SHUTDOWN" />
                <action android:name="android.media.RINGER_MODE_CHANGED" />
            </intent-filter>
        </receiver>

        <activity
            android:name=".ui.ShareLocationActivity"
            android:label="@string/title_activity_share_location"
            android:exported="true"/>
        <activity
            android:name=".ui.SearchActivity"
            android:label="@string/search_messages"
            android:exported="true" />
        <activity
            android:name=".ui.RecordingActivity"
            android:configChanges="orientation|screenSize"
            android:theme="@style/ConversationsTheme.Dialog"
            android:exported="true" />
        <activity
            android:name=".ui.ShowLocationActivity"
            android:label="@string/title_activity_show_location"
            android:exported="true" />
        <activity
            android:name=".ui.SplashActivity"
            android:theme="@style/SplashTheme"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.ConversationsActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:minWidth="300dp"
            android:minHeight="300dp"
            android:exported="true"
            android:windowSoftInputMode="stateHidden" />
        <activity
            android:name=".ui.ScanActivity"
            android:screenOrientation="portrait"
            android:exported="true"
            android:theme="@style/ConversationsTheme.FullScreen"
            android:windowSoftInputMode="stateAlwaysHidden" />
        <activity
            android:name=".ui.UriHandlerActivity"
            android:label="@string/app_name"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

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

                <data android:scheme="xmpp" />
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />

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

                <data android:scheme="https" />
                <data android:host="im.app.in" />
                <data android:pathPrefix="/i/" />
                <data android:pathPrefix="/j/" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SENDTO" />

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

                <data android:scheme="imto" />
                <data android:host="jabber" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.StartConversationActivity"
            android:label="@string/title_activity_start_conversation"
            android:launchMode="singleTop"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.SettingsActivity"
            android:label="@string/title_activity_settings"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.NOTIFICATION_PREFERENCES" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.ChooseContactActivity"
            android:label="@string/title_activity_choose_contact"
            android:exported="true" />
        <activity
            android:name=".ui.BlocklistActivity"
            android:label="@string/title_activity_block_list"
            android:exported="true"/>
        <activity
            android:name=".ui.ChangePasswordActivity"
            android:label="@string/change_password_on_server"
            android:exported="true"/>
        <activity
            android:name=".ui.ChooseAccountForProfilePictureActivity"
            android:enabled="false"
            android:label="@string/choose_account"
            android:exported="true">
            <intent-filter android:label="@string/set_profile_picture">
                <action android:name="android.intent.action.ATTACH_DATA" />

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

                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.ShareViaAccountActivity"
            android:label="@string/title_activity_share_via_account"
            android:launchMode="singleTop"
            android:exported="true" />
        <activity
            android:name=".ui.EditAccountActivity"
            android:launchMode="singleTop"
            android:exported="true"
            android:windowSoftInputMode="stateHidden|adjustResize" />
        <activity
            android:name=".ui.ConferenceDetailsActivity"
            android:label="@string/action_muc_details"
            android:exported="true"
            android:windowSoftInputMode="stateHidden" />
        <activity
            android:name=".ui.ContactDetailsActivity"
            android:exported="true"
            android:windowSoftInputMode="stateHidden" />
        <activity
            android:name=".ui.PublishProfilePictureActivity"
            android:label="@string/mgmt_account_publish_avatar"
            android:exported="true"
            android:windowSoftInputMode="stateHidden" />
        <activity
            android:name=".ui.PublishGroupChatProfilePictureActivity"
            android:exported="true"
            android:label="@string/group_chat_avatar" />
        <activity
            android:name=".ui.ShareWithActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <action android:name="android.intent.action.SEND_MULTIPLE" />

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

                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <action android:name="android.intent.action.SEND_MULTIPLE" />

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

                <data android:mimeType="*/*" />
            </intent-filter>

            <!-- the value here needs to be the full class name; independent of the configured applicationId -->
            <meta-data
                android:name="android.service.chooser.chooser_target_service"
                android:value="eu.siacs.conversations.services.ContactChooserTargetService" />
        </activity>
        <activity
            android:name=".ui.TrustKeysActivity"
            android:label="@string/trust_omemo_fingerprints"
            android:exported="true"
            android:windowSoftInputMode="stateAlwaysHidden" />
        <activity
            android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
            android:exported="true"
            android:theme="@style/Base.Theme.AppCompat" />
        <activity android:name=".ui.MemorizingActivity"
            android:exported="true" />
        <activity
            android:name=".ui.MediaBrowserActivity"
            android:exported="true"
            android:label="@string/media_browser" />

        <service android:name=".services.ExportBackupService" android:exported="true"/>
        <service android:name=".services.ImportBackupService" android:exported="true"/>
        <service
            android:name=".services.ContactChooserTargetService"
            android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE"
            android:exported="true">
            <intent-filter>
                <action android:name="android.service.chooser.ChooserTargetService" />
            </intent-filter>
        </service>
        <service android:name=".services.CompulsoryUpdateService" android:exported="true"/>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="$applicationId.files"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        <provider
            android:name=".services.BarcodeProvider"
            android:authorities="$applicationId.barcodes"
            android:exported="false"
            android:grantUriPermissions="true" />

        <activity
            android:name=".ui.ShortcutActivity"
            android:label="@string/contact"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.CREATE_SHORTCUT" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.MucUsersActivity"
            android:exported="true"
            android:label="@string/group_chat_members" />
        <activity
            android:name=".ui.ChannelDiscoveryActivity"
            android:exported="true"
            android:label="@string/discover_channels" />
        <activity
            android:name=".ui.RtpSessionActivity"
            android:autoRemoveFromRecents="true"
            android:exported="true"
            android:launchMode="singleInstance"
            android:supportsPictureInPicture="true" />
    </application>

</manifest>

我的第二个清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="eu.siacs.conversations">

    <application tools:ignore="GoogleAppIndexingWarning">
        <activity
            android:name=".ui.ManageAccountActivity"
            android:label="@string/title_activity_manage_accounts"
            android:launchMode="singleTask"
            android:exported="true"/>
        <activity
            android:name=".ui.MagicCreateActivity"
            android:label="@string/create_new_account"
            android:launchMode="singleTask"
            android:exported="true"/>
        <activity
            android:name=".ui.EasyOnboardingInviteActivity"
            android:label="@string/invite_to_app"
            android:launchMode="singleTask" />
        <activity
            android:name=".ui.ImportBackupActivity"
            android:label="@string/restore_backup"
            android:launchMode="singleTask"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="application/vnd.conversations.backup" />
                <data android:scheme="content" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="application/vnd.conversations.backup" />
                <data android:scheme="file" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

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

                <data android:scheme="content" />
                <data android:host="*" />
                <data android:mimeType="*/*" />
                <data android:pathPattern=".*\\.ceb" />
                <data android:pathPattern=".*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.ceb" />
            </intent-filter>
            <intent-filter>
                <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:host="*" />
                <data android:mimeType="*/*" />
                <data android:pathPattern=".*\\.ceb" />
                <data android:pathPattern=".*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.ceb" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.ceb" />
            </intent-filter>
        </activity>
    </application>
</manifest>

我的 gradle 文件:

import com.android.build.OutputFile

// Top-level build file where you can add configuration options common to all
// sub-projects/modules.
buildscript 
    ext.kotlin_version = "1.5.21"
    repositories 
        google()
        mavenCentral()
        maven  url 'https://jitpack.io' 
        gradlePluginPortal()
    
    dependencies 
        classpath 'com.android.tools.build:gradle:4.2.2'
        classpath 'com.google.gms:google-services:4.3.8'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    


apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'

repositories 
    google()
    mavenCentral()
    jcenter()
    maven  url 'https://jitpack.io' 


configurations 
    conversationsFreeCompatImplementation


dependencies 
    implementation 'androidx.viewpager:viewpager:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    implementation 'org.sufficientlysecure:openpgp-api:10.0'
    implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'androidx.exifinterface:exifinterface:1.3.2'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
    implementation 'androidx.emoji:emoji:1.1.0'
    implementation 'com.google.android.material:material:1.4.0'
    conversationsFreeCompatImplementation 'androidx.emoji:emoji-bundled:1.1.0'
    implementation 'org.bouncycastle:bcmail-jdk15on:1.64'
    //zxing stopped supporting Java 7 so we have to stick with 3.3.3
    //https://github.com/zxing/zxing/issues/1170
    implementation 'com.google.zxing:core:3.4.1'
    implementation 'de.measite.minidns:minidns-hla:0.2.4'
    implementation 'me.leolin:ShortcutBadger:1.1.22@aar'
    implementation 'org.whispersystems:signal-protocol-java:2.8.1'
    implementation 'com.makeramen:roundedimageview:2.3.0'
    implementation "com.wefika:flowlayout:0.4.1"
    implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
    implementation 'org.jxmpp:jxmpp-jid:1.0.1'
    implementation 'org.osmdroid:osmdroid-android:6.1.10'
    implementation 'org.hsluv:hsluv:0.2'
    implementation 'org.conscrypt:conscrypt-android:2.5.2'
    implementation 'me.drakeet.support:toastcompat:1.1.0'
    implementation "com.leinardi.android:speed-dial:3.2.0"

    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.2"
    implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'

    implementation 'com.google.guava:guava:30.1.1-android'
    implementation 'org.webrtc:google-webrtc:1.0.32006'

    // Lifecycle Helper
    implementation "androidx.activity:activity-ktx:1.3.0-rc02"
    implementation "androidx.fragment:fragment-ktx:1.3.6"

    //Navigation
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'

    //CardView
    implementation "androidx.cardview:cardview:1.0.0"

    //Country Code Picker
    implementation 'com.hbb20:ccp:2.5.3'

    //Firebase
    implementation 'com.google.firebase:firebase-bom:28.3.0'
    implementation 'com.google.firebase:firebase-auth-ktx:21.0.1'
    implementation 'androidx.browser:browser:1.3.0'

    //OTP view
    implementation 'com.github.mukeshsolanki:android-otpview-pinview:2.1.2'

    //Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    //Gson
    implementation 'com.google.code.gson:gson:2.8.7'

    //Multidex
    implementation 'androidx.multidex:multidex:2.0.1'

    //Round Image
    implementation 'de.hdodenhof:circleimageview:3.1.0'

    // Button with image and text
    implementation 'com.github.Omega-R:OmegaCenterIconButton:0.0.4@aar'

    //Razor pay
    implementation 'com.razorpay:checkout:1.6.10'

    //Mixpanel Tracking
    implementation 'com.mixpanel.android:mixpanel-android:5.9.1'

    //Loading screen
    implementation 'com.wang.avi:library:2.1.3'

    //Loading
    implementation 'com.wang.avi:library:2.1.3'

    //Form
    implementation 'com.quickbirdstudios:surveykit:1.1.0'


ext 
    travisBuild = System.getenv("TRAVIS") == "true"
    preDexEnabled = System.getProperty("pre-dex", "true")
    abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'x86_64': 3, 'arm64-v8a': 4]


android 
    compileSdkVersion 31

    defaultConfig 
        minSdkVersion 24
        targetSdkVersion 31
        versionCode 44
        versionName "2.0.4"
        multiDexEnabled = true
        archivesBaseName += "-$versionName"
        applicationId "com.app.app"
        resValue "string", "applicationId", applicationId
        def appName = "app"
        resValue "string", "app_name", appName
        buildConfigField "String", "APP_NAME", "\"$appName\""
    

    splits 
        abi 
            universalApk true
            enable true
        
    

    configurations 
        compile.exclude group: 'org.jetbrains' , module:'annotations'
    

    dataBinding 
        enabled true
    

    dexOptions 
        // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false.
        preDexLibraries = preDexEnabled && !travisBuild
        jumboMode true
    

    compileOptions 
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    

    flavorDimensions("mode", "distribution", "emoji")

    productFlavors 

        conversations 
            dimension "mode"
        
        free 
            dimension "distribution"
            versionNameSuffix "+f"
        
        compat 
            dimension "emoji"
            versionNameSuffix "c"
        
    

    sourceSets 
        conversationsFreeCompat 
            java 
                srcDir 'src/freeCompat/java'
                srcDir 'src/conversationsFree/java'
            
        
    

    buildTypes 
        release 
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            versionNameSuffix "r"
        
        debug 
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            versionNameSuffix "d"
        
    


    if (new File("signing.properties").exists()) 
        Properties props = new Properties()
        props.load(new FileInputStream(file("signing.properties")))

        signingConfigs 
            release 
                storeFile file(props['keystore'])
                storePassword props['keystore.password']
                keyAlias props['keystore.alias']
                keyPassword props['keystore.password']
            
        
        buildTypes.release.signingConfig = signingConfigs.release
    

    lintOptions 
        disable 'MissingTranslation', 'InvalidPackage','AppCompatResource'
    

    subprojects 

        afterEvaluate 
            if (getPlugins().hasPlugin('android') ||
                    getPlugins().hasPlugin('android-library')) 

                configure(android.lintOptions) 
                    disable 'AndroidGradlePluginVersion', 'MissingTranslation'
                
            

        
    

    packagingOptions 
        exclude 'META-INF/BCKEY.DSA'
        exclude 'META-INF/BCKEY.SF'
    

    android.applicationVariants.all  variant ->
        variant.outputs.each  output ->
            def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
            if (baseAbiVersionCode != null) 
                output.versionCodeOverride = (100 * variant.versionCode) + baseAbiVersionCode
            
        

    

【问题讨论】:

请在此处分享崩溃日志。 通常我想我会查看app/build/intermediates/manifest_merge_blame_file/ 下的文件。但是,如果在清单合并期间构建失败,那么可能甚至不会生成责备文件。在那种情况下,我真的不知道。 @AshiqueBava 正如迈克尔指出的那样,罪魁祸首可能不在合并的清单文件中。我必须检查“外部库”中列出的每个条目的每个清单文件,最后找到丢失的一个。然后,您要么必须更新库,要么在他们的问题跟踪器中提交问题。 @Jakoss 我正忙于其他一些项目。我一有时间就会去看看。感谢您的宝贵时间。 @dng 谢谢!!永远不会应付这个。一旦你提到它,就会想“哦,一定是那个 3rd 方库”并删除了其中一些。罪魁祸首竟然是androidx.fragment:fragment-testing:1.3.6 :( 【参考方案1】:

我遇到了这个问题,我使用的库之一没有正确设置。

您可以通过以下步骤找到它:

为 30 设置目标 SDK 转到合并的清单: 转到所有库的单独清单文件(如果已创建合并清单,则可以跳过此步骤,您可以查看合并清单) 查找是否有任何活动、服务、接收者或提供者没有exported,并将其设置为相应的需求。我们可以通过将其添加到应用程序的清单中来覆盖在库清单中编写的规范。更多信息:Documentation、Similar issue in a SDK。 为 31 设置目标 SDK 这样覆盖您找到的所有条目:
<receiver android:name="<name_of_the_entry>"
                android:exported="false or true"
                tools:node="merge" />

【讨论】:

在做一个干净的项目后,错误会再次出现:( 那么你还有一些未导出的条目。检查所有条目?广播接收器、服务、活动和提供者? @Jakoss 是的,兄弟,我们检查了所有库文件并且项目正常工作,但在重建项目后,gradle 将清理本地文件并再次下载并修改我们的编辑,因此此解决方案将不起作用 @AbdulmalekDery 看看我的回答,你不要修改临时文件中的清单。您必须为您的 manifest.xml 中的所有条目添加 tools:node="merge" 条目 用这个方法发现了一个过时的依赖。 +1【参考方案2】:

修复这样的问题可能有点麻烦,因为 IDE 没有提供错误的详细信息,它只是告诉你有一个没有导出参数的 Activity、Receiver 或 Service,但没有告诉你是哪一个是。按照 Jakos 的建议,您可以手动检查合并后的清单,或者使用 this script 以防生成的清单太大。

之后,如果它是项目的一部分,您可以通过添加导出的属性来修改受影响的条目,或者如果它是库的一部分,则覆盖它:

<activity android:name="name_of_the_activity_inside_library>"
    android:exported="false|true"
    tools:node="merge" />

更新: 当针对 android S 并且检测到此问题时,清单合并任务似乎失败而没有生成清单,因此我的建议是使用低于 31 的 targetSdk 编译应用程序,然后手动或使用我链接的脚本检查生成的清单. (您可以在 build 文件夹或通过inspecting 生成的 apk 找到合并后的清单)

【讨论】:

我应该传递什么作为参数? 包含你的manifest的文件路径,你也可以直接把args[0]换成路径,把脚本当作草稿 能否分享一下如何获取manifest文件路径 此解决方案将不起作用,因为在更新库清单后,gradle 将在未来同步中删除本地更改,您必须再次编辑清单,因此谷歌现在建议的唯一解决方案是询问库开发人员更新他们的回购 :( 这里有更多关于如何设置的信息:developer.android.com/about/versions/12/…【参考方案3】:

检查您的build.gradle 文件是否有:

debugImplementation "androidx.fragment:fragment-testing:<version>"

如果存在,请将其更改为:

androidTestImplementation "androidx.fragment:fragment-testing:<version>"

它应该一直是androidTestImplementation,但之前存在一些依赖问题,因此有必要使用debugImplementation 作为解决方法。 IDE 实际上会提示您执行此操作。但显然它已针对 SDK 31 进行了修复,如果您将其保留为 debugImplementation,则会收到来自依赖包中的 manifest.xmlandroid:exported-missing 清单错误。

【讨论】:

解决了一个问题,但出现了一个新问题:我的测试然后以Unable to resolve activity for: Intent act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]... androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity (has extras) 失败 我无法多次投票。我花了几个小时寻找这个解决方案。进行了您建议的更改,我的应用立即启动。 确保升级到最新版本的fragment【参考方案4】:

对于插桩测试,如果您正在使用 compose 测试,请确保在 compose.ui 依赖项之外添加 androidx.test.ext:junit

androidTestImplementation "androidx.test.ext:junit:1.1.3"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.0.4"

【讨论】:

这与android:exported="true"一起工作,你也可以使用ktx版本androidx.test.ext:junit-ktx 就是这样!非常感谢! 这对我来说是正确的答案,谢谢。 我收到错误消息:“android:exported 需要为元素 明确指定”,更新 androidx.test.ext:junit: 1.1.3 确实修复了这个错误。谢谢!【参考方案5】:

构建失败后转到 AndroidManifest.xml 并在底部单击合并清单查看哪些活动具有 intent-filter 但没有 exported=true 属性。 或者您可以只获取给出错误的活动。

使用android:exported="true" 和app tools:node="merge" 将这些活动添加到您的应用清单中,这会将导出的属性添加到给出错误的活动中。 示例:

     <activity
                android:name="<activity which is giving error>"
                android:exported="true"
                tools:node="merge" />

您必须这样做一次,一旦库开发人员更新他们的库,您就可以将其删除。

【讨论】:

这个成功了。我不必添加 node=merge 行,只需添加exported=true。感谢 Build3r! @FedericoAlvarez 添加tools:node="merge" 将保留开发人员打算拥有的所有其他字段。没有它,您的更改将取代原来的。我强烈建议包括tools:node="merge" 更多细节在这里developer.android.com/studio/build/manifest-merge【参考方案6】:

作为目标 sdk 更新到 31 android 12,因此您必须在 manifest.xml 中的活动午餐器中执行 android 导出

 android:exported="true"

【讨论】:

【参考方案7】:

我的问题是 test:core:1.3.0(见屏幕截图)。

我必须重写此库的清单条目并声明 android:exported 属性:

<activity android:name="androidx.test.core.app.InstrumentationActivityInvoker$BootstrapActivity"
android:exported="true"
tools:node="merge"/>

<activity android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity"
android:exported="true"
tools:node="merge"/>

<activity android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyFloatingActivity"
android:exported="true"
tools:node="merge"/>

【讨论】:

给出了如何做的线索。谢谢。 这是我遇到问题的库。 这是我的情况!我通过将androidx.test.ext:junit 的版本切换为1.1.3 解决了这个问题。此解决方案不需要任何硬代码覆盖(以及任何其他库更新/文件修改),这种情况下,它更好 从版本 1.3.0 降级到 1.1.3 不是修复 imo。 这是我的情况!我通过将 androidx.test:core 的版本切换到最新版本 1.4.0 解决了这个问题。此解决方案不需要任何硬代码覆盖(以及任何其他库更新/文件修改),这种情况下,它更好【参考方案8】:

targetSdkVersion改回30 您可以在 31 离开 compileSdkVersion 然后点击运行

【讨论】:

Hey Eric,首先,感谢您成为新的贡献者,这是帮助他人的最佳方式。关于您的答案,如果您可以更详细一点,以便其他人可以理解答案的深度,那将是很好的。可能会解释一下,您是如何遇到同样问题的,以及您是如何设法解决的。 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。 它对我有用.. 谢谢,节省了我的时间。 这里,先生,你把这个丢了?。【参考方案9】:

我不确定你用什么来编码,但为了在 Android Studio 中设置它,打开你的项目清单并在“活动”部分下,输入 android:exported="true "(如果您喜欢,则为 false)。 I have attached an example.

【讨论】:

我已将它添加到所有活动中,但问题仍然存在。 谢谢,这个解决方案对我有用,更多信息请到这里developer.android.com/about/versions/12/…【参考方案10】:

我碰巧在 android 12 中特别知道这个问题。 Android SDK 中已经出现了一个错误。在您的问题的解决方案中,您可以在 android studio 中添加一个文件并运行该方法。

Enable android exported file

然后运行 ​​def 方法并尝试构建。 这是久经考验的工作方法。

【讨论】:

检查链接并仔细阅读评论会话,将解决您使用 Android 12 的问题。感谢 Raj。 不适用于我...我按照链接上的步骤操作 你现在遇到什么问题? 它对我也不起作用。 doAddAndroidExportedIfNecessary 和 doAddAndroidExportedForDependencies 都不会添加库活动。它仅向清单文件中已列出的活动/服务添加了导出属性。【参考方案11】:

如果您的应用面向 Android 12 或更高版本,您必须在应用的清单文件中声明这些归因标签。 如果应用组件包含 LAUNCHER 类别,请将 android:exported 设置为 true。

 <activity
        android:name="com.test.activity.SplashActivity"
        android:clearTaskOnLaunch="true"
        android:label="@string/app_name"
        android:launchMode="singleTop"
        android:noHistory="true"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.NoActionBar"
        android:exported="true">

还要检查 Androidmanifest 中的接收器或服务,如果您使用任何接收器或服务集 android:exported="true" 或根据要求设置为 false。

   <receiver
        android:name="com.test.receiver.ShareReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="com.test.fcm.android.action.broadcast" />
        </intent-filter>
    </receiver>

   <service
        android:name="com.google.android.gms.tagmanager.InstallReferrerService"
        android:exported="true" />

同时更新你所有的 gradle 依赖。

我已根据要求更新了以下依赖项。

testImplementation 'junit:junit:4.13.2' 
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.razorpay:checkout:1.6.15'

希望对你也有帮助。

【讨论】:

【参考方案12】:

如果您确定要向清单文件中的每个元素添加导出但仍然出现此错误,只需:

    切换到项目目录并打开 app\build\intermediates\merged_manifest 中的合并清单文件 搜索任何包含 intent-filter 且没有导出属性的组件 通过将其复制到主清单文件中来覆盖清单文件中的此组件

提示:如果您找不到合并文件,因为它已经无法生成它。临时降级到 targetSdkVersion 30 并编译 SdkVersion 30 并构建项目以生成此文件,然后按照上述步骤然后升级到 31(android 12)

【讨论】:

【参考方案13】:

找到这个解决方案here,对我有用。这是由官方 razorpay github 提供的。他们已经提到他们将在下一个版本中修复它。

<receiver
    android:name="com.razorpay.RzpTokenReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="rzp.device_token.share" />
    </intent-filter>
</receiver>

<activity
    android:name="com.razorpay.CheckoutActivity"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    android:exported="true"
    android:theme="@style/CheckoutTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <data
            android:host="rzp.io"
            android:scheme="io.rzp" />
    </intent-filter>
</activity>

【讨论】:

【参考方案14】:
<activity
     android:name=".MainActivity"
     android:exported="true" <** add this line on AndroidManifest.xml**
     android:launchMode="singleTop"
     android:theme="@style/LaunchTheme"
 </activity>

【讨论】:

【参考方案15】:

如果你使用flutter,升级flutter_local_notifications到最新版本(现在是9.3.2)可能会解决这个错误..

【讨论】:

这正是我的问题。非常感谢!【参考方案16】:

我收到这个错误,什么目标 sdk 31,发现解决方案在我的 build.gradle 文件中。我在撰写测试依赖项上使用了implementation,而不是testImplementation

我知道这似乎无关,但是当您查看带有滥用测试依赖项的合并清单时,您会看到为InstrumentedActivity 添加的标签将缺少exported=true 字段。

【讨论】:

【参考方案17】:

只需更新所有依赖项,它应该可以工作

【讨论】:

【参考方案18】:

引用official docs about this behavior change in android 12,您应该查找包含intent-filter 的活动,这些活动需要通过明确设置android:exported 的值来更新。

构建日志应该准确地指向带有未声明的导出标志的活动,该标志停止了您的构建。您应该在install gradle 命令的控制台输出的最后几行之间看到类似这样的内容:

> java.util.concurrent.ExecutionException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/xxxxx.tmp/base.apk (at Binary XML file line #129): YOUR.FULLY.QUALIFIED.NAME.FAILING.ACTIVITY: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present

YOUR.FULLY.QUALIFIED.NAME.FAILING.ACTIVITY 应该将您指向阻止您构建的特定活动。

这里也是设置android:exported的link to the implications。

【讨论】:

【参考方案19】:

我的问题是我们使用的是较旧的刀柄版本 2.38.1:

"com.google.dagger:hilt-android:2.38.1"
"com.google.dagger:hilt-android-gradle-plugin:2.38.1"
"com.google.dagger:hilt-android-compiler:2.38.1"
"com.google.dagger:hilt-android-testing:2.38.1"

"com.google.dagger:hilt-android-testing:2.38.1" 依赖于核心测试库 1.3.0,它确实设置了导出的属性。

要解决此问题,请确保您使用的是最新的匕首刀柄版本(2.40.5 有效):

"com.google.dagger:hilt-android:2.40.5"
"com.google.dagger:hilt-android-gradle-plugin:2.40.5"
"com.google.dagger:hilt-android-compiler:2.40.5"
"com.google.dagger:hilt-android-testing:2.40.5" 

【讨论】:

【参考方案20】:

案例 1:没有子模块或库

此问题始于 SDK 31。如果您没有任何库或子模块,请添加

android:exported="true" <!-- or false as required -->

您可以右键单击标签,Android Studio 会建议您。

案例 2:使用子模块或库

如果您有其他要导入的库或模块,您也必须覆盖它们。为此,请参阅“合并清单”选项卡。 或者你可以打开

/app/build/intermediates/merged_manifest//AndroidManifest.xml

在编辑器中。我更喜欢第二种方法,因为合并清单不允许从 Android Studio 搜索。

    复制 、 或任何其他导致构建错误的内容。 将它们粘贴到主清单 根据需要添加 android:exported="true" 或 android:exported="false" 重建

案例 3:如果以上都不起作用

如果以上方法都不起作用,您将不得不等到您的库提供商进行必要的更改。在他们做出更改之前,您可以将 SDK 版本恢复到 30 或更低版本。降低 sdk 应该可以暂时解决这个问题。

【讨论】:

【参考方案21】:

临时解决方案

将compileSdk、targetSdk改为

编译SDK 30 目标SDK 30

在 gradle 文件中

【讨论】:

如何解决问题? 其实这是目前唯一的解决方案 @MostafaKing 不,目前正确的解决方案是将第 3 方库的元素声明为已导出。

以上是关于android:exported 需要为 <activity> 显式指定。面向 Android 12 及更高版本的应用需要指定的主要内容,如果未能解决你的问题,请参考以下文章

清单合并失败:即使我的 AndroidManifest.xml 文件中没有服务,也需要为 <service> 显式指定 android:exported

android - 面向 Android 12 及更高版本的应用需要为 `android:exported` 指定显式值

AndroidManifest 中android:exported

Android 12 exported自动适配

以编程方式修改 android:exported

android:exported 属性详解