console.cloud.google.com에서 API 키를 발급받아야 하고, 라이브러리에서 Maps SDK for Android 를 사용 설정해야 한다.
// 그래들
implementation("com.google.android.gms:play-services-maps:18.2.0")
implementation("com.google.android.gms:play-services-location:21.0.1")
// 매니페스트 - 최상단 (어플리케이션 위)
<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" />
// 애플리케이션 하위 최상단
<uses-library
android:name="org.apache.http.legacy"
android:required="true" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="APIKEYHERE" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
// FragmentContainerView 혹은 fragment의 속성에
android:name="com.google.android.gms.maps.SupportMapFragment"
// 액티비티에
// OnMapReadyCallback 인터페이스 상속
private var googleMap: GoogleMap? = null
/*
getMapAsync는 OnMapReadyCallback 인터페이스를 파라미터로 받는데,
이 인터페이스의 onMapReady 메서드는 Google Map 객체가 준비되었을 때 호출된다.
즉, getMapAsync(this) 코드는 Google Map이 완전히 로드되었을 때
this 객체(즉, OnMapReadyCallback 인터페이스를 구현한 객체)의 onMapReady() 메서드를 호출하도록 지시한다.
따라서, 이 코드는 Google Map이 준비되면 this 객체의 onMapReady() 메서드를 호출하라는 의미이다.
onMapReady() 메서드 내에서는 Map 객체를 사용하여 원하는 동작(예: 마커 추가, 카메라 이동 등)을 수행할 수 있다.
*/
/** 권한 물어보고 프래그먼트에 지도 연결 */
private val locationPermissionsLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { results ->
if (results.all { it.value }) {
(supportFragmentManager.findFragmentById(binding.fcv1.id) as SupportMapFragment)
.getMapAsync(this) // 실패하면 터뜨려서 디버깅하게 엘비스 다 빼버림
} else { //문제가 발생했을 때
Toast.makeText(this, "권한 승인이 필요합니다.", Toast.LENGTH_LONG).show()
}
}
/** 위치 서비스가 gps를 사용해서 위치를 확인 */
private lateinit var fusedLocationClient: FusedLocationProviderClient
// onCreate에
locationPermissionsLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
// 아래에 함수 쭉
override fun onMapReady(p0: GoogleMap) {
googleMap = p0
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
// googleMap.mapType = GoogleMap.MAP_TYPE_HYBRID // default 노말 생략 가능
updateLocation()
// 서울 시청 마커 추가해보기
googleMap!!.addMarker(MarkerOptions().also {
it.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
it.position(LatLng(37.566610, 126.978403))
it.title("서울시청")
it.snippet("Tel:01-120")
})
}
private fun updateLocation() {
//권한 처리
if (ActivityCompat
.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat
.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) return
val locationRequest = LocationRequest.create().also {
it.interval = 1000L
it.fastestInterval = 500L
it.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
/** 위치 값 요청에 대한 갱신 정보를 받는 변수 */
val locationCallback = object : LocationCallback() {
//1초에 한번씩 변경된 위치 정보가 onLocationResult 으로 전달된다.
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations) {
Log.d("위치정보", "위도: ${location.latitude} 경도: ${location.longitude}")
setLastLocation(location) //계속 실시간으로 위치를 받아오고 있기 때문에 맵을 확대해도 다시 줄어든다
}
}
}
// 위에 만든 locationRequest랑 locationCallback을 등록?하는듯.
fusedLocationClient
.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper()!!)
}
/** 확인을 위해 현재 위치에 계속해서 마커를 찍고 보여주는 코드 */
fun setLastLocation(lastLocation: Location) {
val latLng = LatLng(lastLocation.latitude, lastLocation.longitude)
val markerOptions = MarkerOptions().position(latLng).title("나 여기 있어용~")
val cameraPosition = CameraPosition.Builder().target(latLng).zoom(15.0f).build()
googleMap?.addMarker(markerOptions)
googleMap?.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}