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.memorynotes
의 MainActivity
를 실행한다고 생각해보세요.
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되지 않게 하려면 아래와 같이 변경하시면 됩니다.
- Intent와 IntentFilter가 일치하도록 만들기
- 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 이상인 앱입니다.
- Caller(API 33 이하 또는 이상) -> Target(API 32 이하) : Android 12처럼 동작함, block 안됨
- Caller(API 33 이하 또는 이상) -> Target(API 33 이상) : Android 13 변경사항 적용됨, block될 수 있음
암시적 인텐트의 경우 Android 12부터 인텐트와 일치해야 실행되었기 때문에 Android 13에서 특별히 고려할 것은 없고, 명시적 인텐트의 경우 Android 13에서는 Component가 설정되어도 Action 등의 정보가 IntentFilter와 일치하지 않으면 실행되지 않도록 변경되었습니다.
Component가 실행되도록 수정하려면, 아래와 같이 변경해야 합니다.
- 명시적 인텐트에서 Component를 제외한 Action 등의 다른 정보를 모두 제거
- 명시적 인텐트에서 Action 등의 정보를 IntentFilter와 일치하도록 변경
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력