개발을 하다가 흥미로운 오류를 하나 발견했다.
휴대폰으로 테스트를 하다가 핸드폰을 살짝 기울였는데 가로 회전이 되면서 앱이 끊기는 것이었다.
황당해서 로그를 먼저 확인해 보았는데
FATAL EXCEPTION: main
Process: com.kuit.conet, PID: 11653
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kuit.conet/com.kuit.conet.MainBottomNavigation.KonetMainActivity}: androidx.fragment.app.FragmentH.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInitInstantiationException: Unable to instantiate fragment com.kuit.conet.CalendarFragment: could not find Fragment constructor
at androidx.fragment.app.Fragment.instantiate(Fragment.java:628)
at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
at androidx.fragment.app.FragmentManager3.instantiate(FragmentManager.java:483) at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85) at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728) at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198) at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149) at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99) at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:362) at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273) at com.kuit.conet.MainBottomNavigation.KonetMainActivity.onCreate(KonetMainActivity.kt:24) at android.app.Activity.performCreate(Activity.java:8290) at android.app.Activity.performCreate(Activity.java:8270) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4085) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4277) at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:6429) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:6294) at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:71) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThreadH.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInitMethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135) Caused by: java.lang.NoSuchMethodException: com.kuit.conet.CalendarFragment.<init> [] at java.lang.Class.getConstructor0(Class.java:2363) at java.lang.Class.getConstructor(Class.java:1759) at androidx.fragment.app.Fragment.instantiate(Fragment.java:613) at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57) at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483) at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85) at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728) at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198) at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149) at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99) at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:362) at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273) at com.kuit.conet.MainBottomNavigation.KonetMainActivity.onCreate(KonetMainActivity.kt:24) at android.app.Activity.performCreate(Activity.java:8290) at android.app.Activity.performCreate(Activity.java:8270) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4085) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4277) at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:6429) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:6294) at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:71) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThreadH.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
2023-07-22 02:51:30.110 9683-14537 Finsky com.android.vending E [6277] VerifyV31SignatureInstallTask.d(34): VerifyApps V31SignatureVerification: Successful verification for the package: com.kuit.conet using APK Signature Scheme v3
2023-07-22 02:52:03.840 14772-14772 USNET pid-14772 E USNET: appName: com.kuit.conet
이런 듣도 보도 못한 오류들이 발생한 것이다.
사실 calendarView 프래그먼트 클래스에를 약속 목록, 대기 중 약속 목록과 같은 데이터들이 인자로 전달되게 구현을 하였는데 화면을 가로로 돌려서 oncreate가 자동으로 재호출되어서 인자들이 제대로 전달되지 못해서 오류가 나타난 것으로 보인다.
실제로 chatgpt에서도 인자가 없는 기본 생성자를 구현하라고 뜨던데 gpt가 준 코드를 사용해봐도 안된다. (오류가 나고 계속 이 상태로 질문했다가 코드가 더 기괴해지고, 길어질 것 같아서 pass...)
화면이 회전되었을 때 oncreate가 재호출 되지 않게 하는 방법도 있다고 하지만 activity가 복잡하면 이 방법도 안먹힌다길래 휴대폰을 돌려도 화면이 가로로 전환되지 않게끔 구현할 수 밖에 없었다.(아니면 calendarView를 뜯어고치던지 (데이터가 전달이 안되었을 때 예외처리 라던가, 전달인자가 없는 생성자를 선언을 하던가....)
방법은 간단했다. AndroidMenifest.xml파일에 들어가서 각 액티비티 태그 마다
android:screenOrientation="portrait" 구문을 추가해주면 끝이다.
반대로 화면을 가로고정하고 싶을 때에는
android:screenOrientation="landscape"구문을 추가해주면 된다고 한다.
내 핸드폰으로 빌드를 하니 가상기기에서 찾기 힘든 오류들을 발견할 수 있었던 것 같다.
실제 핸드폰으로 빌드를 하는게 빠르고, 숨은 오류를 찾기 수월한 것 같다.