Android

Android 12를 타겟팅(targetSdkVersion 31)하는 앱은 andorid:exported 설정이 필수!!(Manifest merger failed)

Android 12를 타겟팅하는경우 해야할 일

AndroidManifest.xml파일에서 activities, services, receivers 등에 android:exported를 설정해야합니다.  앱을 업데이트하기 위해 Android 12( API 31)로 SDK 버전을 높이고 빌드를 하게 되면 아래와 같은 오류가 발생합니다.

bulid.gradle(app)

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 31

    defaultConfig {
        applicationId "tools.test"
        minSdkVersion 23
        targetSdkVersion 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

빌드 프로세스 실패 내용

Execution failed for task ':app:processDebugMainManifest'.
> Manifest merger failed : Apps targeting Android 12 and higher are required to specify an 
explicit value for `android:exported` when the corresponding component has an intent filter 
defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported 
for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

android:exported

exported속성은 앱에서 활동, 서비스 또는 수신기에 액세스 할 수 있으며 외부 응용 프로그램에서 실행 될 수 있는지 정의하는 데 사용됩니다.

AndroidManifest 선언을 각각 확인하여 외부에서 사용할 수 있어야 하는지 여부를 확인하는 것은 정말 중요합니다. 그렇지 않으면 원치 않는 애플리케이션이 앱과 상호 작용하여 의도하지 않은 활동이나 서비스에 액세스할 수 있습니다.

이 요소는 다른 애플리케이션의 구성요소로 액티비티를 시작할 수 있는지 설정합니다. 할 수 있으면 “true”, 할 수 없으면 “false”입니다. “false”인 경우, 해당 액티비티는 같은 애플리케이션의 구성요소 또는 사용자 ID가 같은 애플리케이션으로만 시작할 수 있습니다.

인텐트 필터를 사용하는 경우 이 요소를 “false”로 설정하면 안 됩니다. 이렇게 설정하고 앱이 액티비티를 호출하려 하면 시스템이 ActivityNotFoundException을 발생시킵니다. 대신 이에 대한 인텐트 필터를 설정하지 않아 다른 앱이 이 액티비티를 호출하지 못하게 방지해야 합니다.

인텐트 필터가 없는 경우, 이 요소의 기본값은 “false”입니다. 이 요소를 “true”로 설정하면 이 액티비티는 액티비티의 정확한 클래스 이름을 아는 모든 앱에서 액세스할 수 있지만, 시스템이 암시적 인텐트를 일치시키려 할 때는 확인되지 않습니다.

이 특성 외에도 다른 애플리케이션에 액티비티 노출을 제한하는 방법이 있습니다. 액티비티를 호출할 수 있는 외부 엔터티를 제한하는 권한을 사용할 수도 있습니다(permission 특성 참조).

문제 해결 방법(Troubleshooting)

수정하는 방법은 매우 간단합니다. Manifest파일에 android:exported를 추가해 주고 true 혹은 false 값을 추가해주면 됩니다. 다른 애플리케이션 앱과 상호작용할 계획이 없다면 false를 저정합니다.  기존에는 이 값이 디폴트값으로 자동 적용되었으나 Android12부터는 명시적으로 지정해야합니다. service, recevier 등도 마찬가지로 적용해주면 됩니다.

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Test">
        <activity android:name=".SecondActivity"
            android:exported="false"/>
        <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>
    </application>

</manifest>
        <receiver
            android:name="com.test.BootStart"
            android:enabled="true"
            android:exported="false"
            android:label="bootStart">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <service
            android:name="com.test.BootService"
            android:enabled="true"
            android:exported="false"
            android:stopWithTask="false">
            <intent-filter>
                <action android:name="com.test.BootService" />
            </intent-filter>
        </service>

[REFERENCE]

https://developer.android.com/guide/topics/manifest/activity-element#exported

<액티비티>  |  Android 개발자  |  Android Developers

Declares an activity (an Activity subclass) that implements part of the application’s visual user interface. All activities must be represented by {@code } elements in the manifest file. Any that are not declared there will not be seen by the system…

developer.android.com

Leave a Reply

error: Content is protected !!