Programming/Android

[이슈 기록] TagetSdk 30 -> 31 올리는 과정에서 까다로웠던 이슈 기록 android:exported needs to be explicitly specified for <activity> 이슈

YK Choi 2022. 5. 30. 02:19

배경

TargetSdk 31부터는 Activity나 Service, broadcast receiver에서 인텐트 필터를 사용하지만 명시적으로 선언된 android:exported 값이 없으면 Android 12 이상을 실행하는 기기에 앱을 설치할 수 없다.

( Reference : https://developer.android.com/about/versions/12/behavior-changes-12?hl=ko#exported )

 

하지만 나는 Manifest 파일을 잘 작성 했음에도 

android:exported needs to be explicitly specified for <activity>. 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.  

의 에러가 빌드할 때 발생하였다. 

 

원인

아래 사진과 같이 Manifest 파일에서 (1번 동그라미) Merged Manifest를 클릭하면 자세한 에러 메세지가 나온다.

잘 읽어보니 androidx.test.core.app.InstrumentationActivityInvoker$BootstrapActivity 클래스와, androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity 클래스와, androidx.test.core.app.InstrumentationActivityInvoker$EmptyFloatingActivity 클래스에서 

android:exported 설정을 하지않았기 때문에 발생했다는 것을 알 수 있었다.(2번 동그라미)

 

빌드하면서 dependency에서 추가한 라이브러리들의 Manifest를 통합하는 과정이 있고, targetSdk 31에서 맞지 않는 부분이 있기 때문에 발생하는 것이었다.

 

해결 방법

방법 1)

문제가 되었던 위의 3가지 클래스를 app단의 Manifest에서 overriding 하여 export 값을 설정해주는 것이다. 아래와 같이 말이다.

        <activity
            android:name="androidx.test.core.app.InstrumentationActivityInvoker$BootstrapActivity"
            android:exported="false" />
        <activity
            android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity"
            android:exported="false" />
        <activity
            android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyFloatingActivity"
            android:exported="false" />

 

어떻게보면 근본적인 해결책은 아니지만 빠르게 해결할 수 있는 방법인 것 같다.(Merged Manifest에서 문제가 되는 클래스를 명시적으로 알려주니까!)

 

방법 2)

사용하는 라이브러리 중 낡은 라이브러리가 있거나 해당 라이브러리에서 targetSdk 31을 고려하지 않았기 때문이다. 나의 경우에는 결론적으로는 fragment를 낡은 버전을 쓰고 있었기 때문이었다. 

 

아래와 같이 문제가 되었던 세 Activity들은 아래의 라이브러리 들 중 하나에서 찾을 수 있었는데, 파란색 텍스트를 클릭하면 해당 Manifest로 이동할 수 있었다.

 

전부 다 하나하나 클릭해서 들어가보니 test:core:1.2.0 에서 아래의 Manifest가 있었고, 모든 원인은 test:core:1.2.0 때문임을 알 수 있었다. 세 Activity가 intent-filter를 갖고 있지만 android:export 값이 없었다. 이것은 외부 라이브러리이기 때문에 직접 수정할 수는 없었다. 따라서 이 라이브러리를 dependency추가했던 것을 최신버전으로 업데이트하는 것이 솔루션이었다.(다만 최신버전에서 targetSdk 31 대응을 했다는 것을 전제로 하고있다.)

https://stackoverflow.com/a/69650626/18140287 에 의하면

아래와 같이 fragment-testing을 1.4.0-alpha03 이상으로 업데이트해야 한다고 한다. 나 또한 1.4.0-alpha03 으로 버전을 올렸다. (기존에는 1.2.0-rc04 이었다.)

// fragment
def fragment_version = '1.4.0-alpha03'
implementation "androidx.fragment:fragment-ktx:$fragment_version"
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"

이 방법이 더 본질적인 해결 방법이라 생각하고 가급적 권장되는 것 같다.

하지만 문제가 되었던 클래스들을 통해 버전을 올려야하는 라이브러리가 무엇인지 찾는 과정에서 시간이 조금 더 소요될 수 있다는 단점은 있는 것 같다.