Android 13에서 'Access blocked: ComponentInfo' 에러 해결

Android 13에서 startActivity()로 다른 앱의 액티비티를 실행하려고 했는데, 아래와 같은 Exception이 발생하면서 앱이 종료되었습니다.

10-23 05:43:05.891   608  1743 W PackageManager: Access blocked: ComponentInfo{com.example.memorynotes/com.example.memorynotes.MainActivity}

10-23 05:43:05.893  8669  8669 D AndroidRuntime: Shutting down VM
10-23 05:43:05.895  8669  8669 E AndroidRuntime: FATAL EXCEPTION: main
10-23 05:43:05.895  8669  8669 E AndroidRuntime: Process: com.example.myapplication, PID: 8669
10-23 05:43:05.895  8669  8669 E AndroidRuntime: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.memorynotes/com.example.memorynotes.MainActivity}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared <intent-filter>?

원인은 인텐트를 실행할 때 Access blocked라는 로그가 출력되면서 실행되어야하는 액티비티가 block되었기 때문인데요, Android 13에서 추가된 새로운 변경사항 때문에 block되어 실행이 안되었습니다.

이 글에서 Intent에 대한 Android 13의 변경사항과 해결방법에 대해서 알아보겠습니다.

1. Android 13 변경사항: IntentFilter와 일치하지 않는 Intent를 차단

Android Developer에 인텐트 필터가 일치하지 않는 인텐트를 차단함라는 제목으로 Android 13의 변경사항이 소개되었습니다.

Android 13에서는 Intent로 Activity나 Service 등의 Component를 실행할 때, 인텐트가 Component에 정의된 IntentFilter와 일치하지 않으면 실행하지 않는다는 것입니다.

1.1 Android 12와 Android 13의 동작 차이

보통 암시적 인텐트(target이 지정되지 않은)는 IntentFilter와 일치할 때만 실행되기 때문에, 이 변경사항에 대해서 "당연한거 아닌가요?", "원래 이렇게 동작했었는데요?" 라고 생각하실 수 있습니다.

하지만 명시적 인텐트(target이 지정된)는 Android 13과 Android 12의 차이가 있습니다.

아래와 같은 코드로, 아래 Manifest에 정의된 com.example.memorynotesMainActivity를 실행한다고 생각해보세요. Android 12는 실행이 되지만, Android 13에서는 실행되지 않을 수 있습니다.

val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.component = ComponentName("com.example.memorynotes",
    "com.example.memorynotes.MainActivity")
startActivity(intent)

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

    <application ... />

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

2. 변경사항이 적용되는 대상

Android 13에서 이 변경사항은 Target SDK API 33인 앱의 Component를 실행하는 경우에만 적용됩니다. 즉, startActivity()를 실행하는 App의 Target SDK API는 중요하지 않고, 실행이 되는 Activity를 갖고 있는 앱의 Target API에 따라서 변경사항 적용 여부가 달라집니다.

다시 말하면,

  • 실행하려는 Component를 갖고 있는 App의 Target API가 33 이상일 때, 이 변경사항이 적용됨
  • 실행하려는 Component를 갖고 있는 App의 Target API가 32 이하일 때, 이 변경사항이 적용되지 않음

3. 문제 해결 방법

이 변경사항이 적용되는 상황에서, Activity 실행이 block되지 않게 하려면 아래와 같이 변경하시면 됩니다.

  1. Intent와 IntentFilter가 일치하도록 만들기
  2. Intent에 Component 외에 Action, Catagory 같은 정보는 모두 삭제

3.1 Intent와 IntentFilter가 일치하도록 만들기

아래와 같이 인텐트와 인텐트필터가 일치하도록 하면 Activity가 실행됩니다.

val intent = Intent()
intent.action = Intent.ACTION_MAIN
intent.addCategory(Intent.CATEGORY_LAUNCHER)
intent.component = ComponentName("com.example.memorynotes",
    "com.example.memorynotes.MainActivity")
startActivity(intent)

3.2 Intent에 Component 외에 Action, Catagory 같은 정보는 모두 삭제

아래와 같이 인텐트에 component 외에 다른 정보가 없는 인텐트를 실행하면, Action 등이 IntentFilter와 일치하지 않아도 Activity가 실행됩니다.

val intent = Intent()
intent.component = ComponentName("com.example.memorynotes",
    "com.example.memorynotes.MainActivity")
startActivity(intent)

4. 정리

적용 대상은 아래와 같이 Target이 API 33 이상인 앱입니다.

  1. Caller(API 33 이하 또는 이상) -> Target(API 32 이하) : Android 12처럼 동작함, block 안됨
  2. Caller(API 33 이하 또는 이상) -> Target(API 33 이상) : Android 13 변경사항 적용됨, block될 수 있음

암시적 인텐트의 경우 Android 12부터 인텐트와 일치해야 실행되었기 때문에 Android 13에서 특별히 고려할 것은 없고, 명시적 인텐트의 경우 Android 13에서는 Component가 설정되어도 Action 등의 정보가 IntentFilter와 일치하지 않으면 실행되지 않도록 변경되었습니다.

Component가 실행되도록 수정하려면, 아래와 같이 변경해야 합니다.

  1. 명시적 인텐트에서 Component를 제외한 Action 등의 다른 정보를 모두 제거
  2. 명시적 인텐트에서 Action 등의 정보를 IntentFilter와 일치하도록 변경
Loading script...
codechachaCopyright ©2019 codechacha