@HiltAndroidApp
class ExpoApplication : Application() {
@Inject
@Named("NATIVE_APP_KEY")
lateinit var nativeAppKey: String
override fun onCreate() {
super.onCreate()
KakaoMapSdk.init(this, nativeAppKey) // 카카오맵 초기화 코드 및 nativeAppKey(local.properties에 저장된 값 사용)
}
}
// Application
@Module
@InstallIn(SingletonComponent::class)
object AppConfigModule {
@Provides
@Named("NATIVE_APP_KEY")
fun provideNativeAppKey(): String = BuildConfig.NATIVE_APP_KEY
}
// hilt 의존성 연결을 하기위한 코드
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".ExpoApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App.Starting"
tools:targetApi="31">
<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="@string/navigation_app_key" />
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.App.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
// Android App Module Manifest File
@Composable
internal fun HomeKakaoMap(
modifier: Modifier = Modifier,
locationX: Double, // 서버에서 제공하는 X 값 (경도)
locationY: Double, // 서버에서 제공하는 Y 값 (위도)
) {
val context = LocalContext.current
val mapView = remember { MapView(context) }
AndroidView(
modifier = modifier.height(200.dp), // AndroidView의 높이 임의 설정
factory = { context ->
mapView.apply {
mapView.start(
object : MapLifeCycleCallback() {
// 지도 생명 주기 콜백: 지도가 파괴될 때 호출
override fun onMapDestroy() {
// 필자가 직접 만든 Toast생성 함수
makeToast(context = context, toastMessage = "지도를 불러오는데 실패하였습니다")
}
// 지도 생명 주기 콜백: 지도 로딩 중 에러가 발생했을 때 호출
override fun onMapError(exception: Exception?) {
// 필자가 직접 만든 Toast생성 함수
makeToast(context = context, toastMessage = "지도를 불러오는 중 알 수 없는 에러가 발생했습니다.\n onMapError: $exception")
}
},
object : KakaoMapReadyCallback() {
// KakaoMap이 준비되었을 때 호출
override fun onMapReady(kakaoMap: KakaoMap) {
// 카메라를 (locationY, locationX) 위치로 이동시키는 업데이트 생성
val cameraUpdate = CameraUpdateFactory.newCenterPosition(LatLng.from(locationY, locationX))
// 지도에 표시할 라벨의 스타일 설정
val style = kakaoMap.labelManager?.addLabelStyles(LabelStyles.from(LabelStyle.from(R.string.location_icon_description)))
// 라벨 옵션을 설정하고 위치와 스타일을 적용
val options = LabelOptions.from(LatLng.from(locationY, locationX)).setStyles(style)
// KakaoMap의 labelManager에서 레이어를 가져옴
val layer = kakaoMap.labelManager?.layer
// 카메라를 지정된 위치로 이동
kakaoMap.moveCamera(cameraUpdate)
// 지도에 라벨을 추가
layer?.addLabel(options)
}
override fun getPosition(): LatLng {
// 현재 위치를 반환
return LatLng.from(locationY, locationX)
}
},
)
}
},
)
}
// Kakao MapView
이러한 형태로 KakaoMap 구현을 하였는데 init이 잘 되어있는 거 같은데 앱을 확인하려고 돌려보면
java.lang.RuntimeException: KakaoMapSdk is not initialized. (Ask Gemini)
at com.kakao.vectormap.MapView.checkKakaoMapSdk(MapView.java:254)
at com.kakao.vectormap.MapView.start(MapView.java:55)
at com.school_of_company.home.component.HomeKakaoMapComponentKt$HomeKakaoMap$1.invoke(HomeKakaoMapComponent.kt:36)
at com.school_of_company.home.component.HomeKakaoMapComponentKt$HomeKakaoMap$1.invoke(HomeKakaoMapComponent.kt:32)
at androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:344)
at androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1$1.invoke(AndroidView.android.kt:275)
at androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1$1.invoke(AndroidView.android.kt:274)
at androidx.compose.runtime.changelist.Operation$InsertNodeFixup.execute(Operation.kt:585)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:310)
at androidx.compose.runtime.changelist.FixupList.executeAndFlushAllPendingFixups(FixupList.kt:50)
at androidx.compose.runtime.changelist.Operation$InsertSlotsWithFixups.execute(Operation.kt:552)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:310)
at androidx.compose.runtime.changelist.ChangeList.executeAndFlushAllPendingChanges(ChangeList.kt:81)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:984)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1013)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1150)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124)
at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1626)
at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:124)
at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:180)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:124)
at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1707)
at android.view.View.dispatchAttachedToWindow(View.java:22889)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3504)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3504)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3504)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3504)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3373)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2847)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10190)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1406)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
at android.view.Choreographer.doFrame(Choreographer.java:945)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.app.ActivityThread.main(ActivityThread.java:8699)
2024-11-05 08:23:37.640 12432-12432 K3fAApi com.school_of_company.home.test E at java.lang.reflect.Method.invoke(Native Method) (Ask Gemini)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
위와 같은 init 에러가 나옵니다…
어떤게 문제인지 알려주실분있나요??