[Android/Kotlin] Google Map API 사용해서 구글 지도맵 만들기
# GoogleCloud에서 사용자 인증키 만들기
GoogleCloud에 접속하여 구글 계정으로 로그인한다
프로젝트가 생성되어있지 않다면 새프로젝트를 눌러서, 이름을 적고 새 프로젝트를 생성해준다
API 및 서비스 -> 사용자 인증정보 클릭
사용자 인증정보 만들기 -> API 키 클릭
API 키가 생성되었다 (지금은 API키 제한을 안걸어두었지만, 제한을 걸어서 사용해줄 수도 있다)
https://developers.google.com/maps/documentation/android-sdk/start?hl=ko#enable-api-sdk
Android용 Maps SDK 빠른 시작 | Google for Developers
지금 바로 Android 앱용 Google 지도 프로젝트를 새로 시작해 보세요. 다음과 같이 SDK 설치부터 앱 빌드 및 실행에 이르기까지 필요한 모든 것을 찾을 수 있습니다.
developers.google.com
요기 링크 들어가서 2단계부분을 누르면 위와같은 화면이 뜰텐데 사용설정을 눌러서 정보들을 입력해준다 (주소, 카드번호 등 입력해야함)
# 구글 지도맵 만들기
build.gradle - 모듈버전에 아래와 같이 추가
plugins {
...
alias(libs.plugins.playMap)
}
dependencies {
...
implementation (libs.play.services.maps)
implementation (libs.play.services.location)
}
build.gradle.kt - module
build.gradle - 프로젝트 버전에도 아래와같이 추가
plugins {
...
alias(libs.plugins.playMap) apply false
}
build.gradle.kt - project
libs.versions.toml 에 들어가서 아래와같이 추가
[versions]
...
playMaps = "2.0.1"
playServicesLocation = "21.2.0"
playServicesMaps = "18.2.0"
[libraries]
...
play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "playServicesLocation" }
play-services-maps = { module = "com.google.android.gms:play-services-maps", version.ref = "playServicesMaps" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
playMap = {id = 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin', version.ref = "playMaps"}
libs.versions.toml
매니페스트 파일에도 permission과 google-map api 추가
android: value 부분에는 아까 생성했던 API키를 복사해서 붙여넣어준다
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!--지도 사용설정을 위한 permission등록-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
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.MapExample"
tools:targetApi="31">
<!--구글 지도 API를 이용하는 키를 등록-->
<uses-library android:name="org.apache.http.legacy" android:required="true"/>
<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="== Google Cloud에서 생성한 API키 입력!! ==="/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
activity_main.xml
// OnMapReadyCallback를 상속받으면 onMapReady를 필수적으로 오버라이딩 해줘야함
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mGoogleMap: GoogleMap
// 위치 서비스가 gps를 사용해서 위치를 확인
lateinit var fusedLocationClient: FusedLocationProviderClient
// 위치 값 요청에 대한 갱신 정보를 받는 변수
lateinit var locationCallback: LocationCallback
// 권한요청
lateinit var locationPermission: ActivityResultLauncher<Array<String>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 권한 체크
locationPermission = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()){ results ->
// 권한이 있다면
if(results.all{it.value}){
// mapView에 연결
// SupportMapFragment 를 찾은 후 getMapAsync() 를 호출해서 안드로이드에 구글 지도를 그려달라는 요청함
(supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment)!!.getMapAsync(this)
}else{ //문제가 발생했을 때
Toast.makeText(this,"권한 승인이 필요합니다.",Toast.LENGTH_LONG).show()
}
}
//권한 요청
locationPermission.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
// 지도 객체를 이용할 수 있는 상황이 될 때 호출 (Map이 준비가되면 OnMapReadyCallback에 의해서 이 함수가 바로 콜백됨)
// 파라미터로 준비된 GoogleMap 을 전달
// 메서드 안에서 미리 선언된 mMap 프로퍼티에 GoogleMap 을 저장해두면 액티비티 전체에서 맵을 사용할 수 있음
override fun onMapReady(p0: GoogleMap) {
val seoul = LatLng(37.566610, 126.978403)
mGoogleMap = p0
mGoogleMap.mapType = GoogleMap.MAP_TYPE_NORMAL // default 노말 생략 가능
mGoogleMap.apply {
val markerOptions = MarkerOptions()
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
markerOptions.position(seoul)
markerOptions.title("서울시청")
markerOptions.snippet("Tel:01-120")
addMarker(markerOptions)
}
// 위치정보 받아옴
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
updateLocation()
}
fun updateLocation(){
val locationRequest = LocationRequest.create().apply {
interval = 1000
fastestInterval = 500
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
locationCallback = object : LocationCallback(){
//1초에 한번씩 변경된 위치 정보가 onLocationResult 으로 전달된다.
override fun onLocationResult(locationResult: LocationResult) {
locationResult?.let{
for (location in it.locations){
Log.d("위치정보", "위도: ${location.latitude} 경도: ${location.longitude}")
setLastLocation(location) //계속 실시간으로 위치를 받아오고 있기 때문에 맵을 확대해도 다시 줄어든다.
}
}
}
}
//권한 처리
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback,
Looper.myLooper()!!
)
}
fun setLastLocation(lastLocation: Location){
val LATLNG = LatLng(lastLocation.latitude,lastLocation.longitude)
val makerOptions = MarkerOptions().position(LATLNG).title("나 여기 있어용~")
val cameraPosition = CameraPosition.Builder().target(LATLNG).zoom(15.0f).build()
mGoogleMap.addMarker(makerOptions)
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
MainActivity.kt
# 실행 결과
# 참고자료
https://developers.google.com/maps/documentation/android-sdk/start?hl=ko#enable-api-sdk
https://eonhwa-theme.tistory.com/90
https://velog.io/@krrong/Android-%EA%B5%AC%EA%B8%80-%EB%A7%B5-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0
https://developers.google.com/maps/documentation/android-sdk/marker?hl=ko