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