Jetpack Compose를 사용한 UI 코드를 기반으로 Kakao Maps를 적용하고 싶었으나 마땅한 자료가 없어 내가 직접 작성해 보겠다.
참고로 필자의 프로젝트의 구조는 SAA / Convention Plugin / Version Catalog를 사용하여 구성됐다.
일단 먼저 Kakao Maps 공식 문서에 들어가서 SDK를 설치해야 할 것이다.
이 글이 작성된 날을 기준으로 한 공식문서에 의하면 SDK는 아래의 요구사항을 공지하고 있다.
- 안드로이드 플랫폼 버전 6.0(API level 23) 이상 지원
- armeabi-v7a, arm64-v8a 아키텍쳐 지원
- OpenGL ES 2.0 이상 지원
- 인터넷 권한 필요 (Manifest에서 INTERNET을 열어주는 것)
이제부터 세팅부터 구현까지 차근차근 설명해 보겠다.
settings.gradle.kts 파일 repositories내에 다음과 같은 코드를 추가한다. (주석 참고)
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
// 카카오 맵 저장소 URL 지정
maven("https://devrepo.kakao.com/nexus/repository/kakaomap-releases/")
}
}
필자는 Version Catalog로그를 통해 버전 관리를 진행하고 있으니 toml에 아래와 같이 라이브러리를 추가해 줬다.
[versions]
. . .
kakaoMaps = "2.9.5"
[libraries]
. . .
kakao-maps = { group = "com.kakao.maps.open", name = "android", version.ref = "kakaoMaps" }
만약 Version Catalog를 사용하고 있지 않는다면 내가 추가하고자 하는 모듈의 gradle의 dependencies 블록 내에 아래의 코드를 추가하여 사용하면 될 것이다.
implementation 'com.kakao.maps.open:android:2.11.9'
이제 기본적인 라이브러리 설정은 끝났다. 이제 Kakao SDK를 사용하는데 필요한 네이티브 앱 키를 발급받아보겠다.
네이티브 앱 키를 발급받기 위해서 먼저 카카오 개발자 사이트를 접속해 로그인 후 내 애플리케이션을 클릭하여 본인의 앱 플랫폼을 등록해야 한다.
이후 나오는 내 애플리케이션 페이지에서 애플리케이션 추가하기 버튼을 눌러 아래의 조건에 따라 애플리케이션을 추가한다.
생성한 애플리케이션을 클릭해 좌측 상단의 메뉴를 클릭한다.
이후 메뉴의 플랫폼을 클릭하여 본인의 프로젝트의 새로운 플랫폼을 등록해 준다.
플랫폼 등록 버튼을 누르면 아래와 같은 화면이 나올 텐데 필자가 작성한 내용을 참고해 채우면 된다.
패키지명 : Android 앱의 패키지명을 찾아 작성한다.
마켓 URL : 앱이 배포된 상태라면 작성하면 된다. 없다면 없음을 선택한다.
키 해시 : MainActivity 파일에 다음 코드를 추가 후, 앱을 실행해 키 해시를 확인한다. 이때 키 해시를 추가할 때 디버그용, 릴리즈용, 구글 플레이용 여러 키해시가 있으니 개발자의 상황에 맞게 추가하자
import com.kakao.sdk.common.util.Utility
Log.d("KeyHash", "${Utility.getKeyHash(this)}")
위의 과정을 통해 발급받은 네이티브 앱 키를 LocalProperties에 추가하거나 단순 문자열 삽입 등 개발자가 원하는 방식으로 여러분의 프로젝트의 추가한 이
후 Application 위치에 네이티브 앱 키를 init을 해주어야 한다.
필자는 app모듈의 gradle에서 불필요한 LocalProperties조회를 하지 않기 위해 네이티브 앱 키를 Hilt를 이용해 Provide 하여 아래와 같이 init 했다.
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
@Named("NATIVE_APP_KEY")
lateinit var nativeAppKey: String
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
. . .
}
KakaoMapSdk.init(this@MainActivity, nativeAppKey)
}
}
이후 AndroidManifest.xml 파일에 권한과 앱키를 추가해 준다.
<?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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
. . . >
<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="@string/app_key" />
<activity
android:name=".MainActivity"
. . . >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
이제 기본적인 프로젝트의 설정은 모두 끝났다. 아래는 필자가 Jetpack Compose를 이용해 구현한 코드이다.
@Composable
fun LectureKakaoMap(
modifier: Modifier = Modifier,
locationX: Double, // 서버에서 제공하는 X 값 (경도)
locationY: Double, // 서버에서 제공하는 Y 값 (위도)
) {
val context = LocalContext.current
val mapView = remember { MapView(context) } // KakaoMapView를 기억하여 재사용할 수 있도록 설정
AndroidView(
modifier = modifier.height(200.dp), // AndroidView의 높이 임의 설정
factory = { context ->
mapView.apply {
mapView.start(
object : MapLifeCycleCallback() {
// 지도 생명 주기 콜백: 지도가 파괴될 때 호출
override fun onMapDestroy() {
// 필자가 직접 만든 Toast생성 함수
makeToast(context = context, message = "지도를 불러오는데 실패했습니다.")
}
// 지도 생명 주기 콜백: 지도 로딩 중 에러가 발생했을 때 호출
override fun onMapError(exception: Exception?) {
// 필자가 직접 만든 Toast생성 함수
makeToast(context = context, message = "지도를 불러오는 중 알 수 없는 에러가 발생했습니다.\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(원하는 라벨 drawble파일을 적용)))
// 라벨 옵션을 설정하고 위치와 스타일을 적용
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 Map SDK는 XML형태의 MapView를 기준으로 구성되어 있기에 Jetpack Compose에서 지원하지 않는 형태인 하위 View를 그리기 위해 AndroidView를 사용했다.
아래는 구현 결과 화면이다.
필자가 글이 쓰는 능력이 좋지 않아 이해하기 어려울 수 있다.
궁금한 점이 생긴다면 댓글로 질문해 주길 바란다.
'Android > Library' 카테고리의 다른 글
[Library] Retrofit이 뭔데? (0) | 2024.08.13 |
---|