[Android] 안드로이드 14 타켓팅시 발생하는 One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn’t being registered exclusively for system broadcasts 리시버 등록 오류 해결하기
안드로이드 스튜디오에서 build.gradle(:app) 파일 설정에서 targetSdkVersion을 33에서 34로 상향 후 테스트 폰을 연결 후 실행하였다.
android {
compileSdk 34
defaultConfig {
applicationId "com.test"
minSdkVersion 19
targetSdkVersion 34
versionCode 836
versionName "8.1.6"
.....이하생략
이전까지는 발생하지 않았던 오류가 발생되었다. 오류내용은 다음과 같다.
FATAL EXCEPTION: main
Process: com.test, PID: 18923
java.lang.RuntimeException: Unable to start service com.test.TestService@ec532b3 with Intent { cmp=com.test/.TestService }: java.lang.SecurityException: com.test: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5286)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2531)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8893)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.SecurityException: com.test: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
at android.os.Parcel.createExceptionOrNull(Parcel.java:3069)
at android.os.Parcel.createException(Parcel.java:3053)
at android.os.Parcel.readException(Parcel.java:3036)
at android.os.Parcel.readException(Parcel.java:2978)
at android.app.IActivityManager$Stub$Proxy.registerReceiverWithFeature(IActivityManager.java:6137)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1913)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1853)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1841)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:772)
at com.test.TestService.regisiterReceiver(TestService.java:272)
at com.test.TestService.onStartCommand(TestService.java:196)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5268)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2531)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8893)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ActivityManagerService.registerReceiverWithFeature(ActivityManagerService.java:16580)
at android.app.IActivityManager$Stub.onTransact$registerReceiverWithFeature$(IActivityManager.java:11530)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2928)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3195)
at android.os.Binder.execTransactInternal(Binder.java:1375)
오류가 발생한 코드의 위치는 다음과 같다.
registerReceiver(testReceiver, intentFilter);
Android 14 이상(U+)에서 실행되는 앱의 경우 리시버 등록시 반드시 RECEIVER_EXPORTED / RECEIVER_NOT_EXPORTED 플래그 중에 하나를 지정해주어야한다. 만약 다른 앱의 송신을 수신할수 있도록 하려면 RECEIVER_EXPORTED 플래그를 사용하면 되고, 다른 앱의 송신을 수신하지 않는 리시버를 등록하려면 RECEIVER_NOT_EXPORTED 플래그를 설정하여 사용하면 된다.
오류가 해결된 코드는 다음과 같다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(testReceiver, intentFilter, RECEIVER_NOT_EXPORTED); //다른 앱의 송신을 수신 하지 않음
}else{
registerReceiver(testReceiver, intentFilter);
}
ContextCompat을 사용하면 Android 버전에 대해 분기하지 않고 Broadcast Receiver를 등록할 수 있다.
ContextCompat.registerReceiver(getApplicationContext(), testReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED);
reference : https://stackoverflow.com/questions/77235063/one-of-receiver-exported-or-receiver-not-exported-should-be-specified-when-a-rec