Google Map 기초
사전 작업
구글 플레이 서비스 SDK 설치하기
◽ Google Play services를 설치해준다.
Google Maps Activity로 시작하기
Google Map API 키 받기
✔ Google Map 액티비티로 프로젝트를 생성하면 google_maps_api.xml이 자동을 생성되는데 해당 파일에서 구글 맵을 사용하기 위한 API 키를 받을 수 있는 링크를 만들어준다.
✔ 별도로 접근하기 위해서는 Google Cloud Platform에서 프로젝트를 생성하고, 해당 프로젝트의 SHA-1 키를 등록한 후, 키를 받아야 한다.
코드 분석
build.gradle
implementation 'com.google.android.gms:play-services-location:17.0.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<!-- 정확한 위치 확보(네트워크 위치 + GPS 위치)-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 도시 블록 내에서의 정확한 위치(네트워크 위치)-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
|
cs |
activity_maps.xml
1
2
3
4
5
6
7
8
9
|
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity" />
|
cs |
◽ Google Maps API는 SupportMapFragment에 구글 지도를 표시한다.
BaseActivity.kt
✔ Permission 관련 코드들은 BaseActivity로 분리하여 설계
abstract class BaseActivity : AppCompatActivity() {
abstract fun permissionGranted(requestCode: Int)
abstract fun permissionDenied(requestCode: Int)
fun requirePermissions(permissions: Array<String>, requestCode: Int) {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
permissionGranted(requestCode)
} else {
val isAllPermissionsGranted = permissions.all {
checkSelfPermission(it) == PackageManager.PERMISSION_GRANTED }
if (isAllPermissionsGranted) {
permissionGranted(requestCode)
} else {
ActivityCompat.requestPermissions(this, permissions, requestCode)
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
permissionGranted(requestCode)
} else {
permissionDenied(requestCode)
}
}
}
MapsActivity.kt
class MapsActivity : BaseActivity(), OnMapReadyCallback {
val binding by lazy { ActivityMapsBinding.inflate(layoutInflater) }
private lateinit var mMap: GoogleMap
private lateinit var discriptor: BitmapDescriptor
private lateinit var fusedLocationClient: FusedLocationProviderClient // 위칫값 사용하기 위해
private lateinit var locationCallback: LocationCallback // 위칫값 요청에 대한 갱신 정보를 받기 위해
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
val permissions = arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION)
requirePermissions(permissions, 999)
}
override fun permissionGranted(requestCode: Int) {
startProcess()
}
override fun permissionDenied(requestCode: Int) {
Toast.makeText(this
, "권한 승인이 필요합니다."
, Toast.LENGTH_LONG)
.show()
}
}
fun startProcess() {
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this) // 구글 지도를 그려달라는 요청
}
override fun onMapReady(googleMap: GoogleMap) { // onMapReadyCallback 메서드 오버라이드
mMap = googleMap // 액티비티 전체에서 맵을 사용할 수 있도록
// 현재 위치를 검색하기 위해서 FusedLocationProviderClient 사용
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
updateLocation()
/* 마커 아이콘 설정 */
var bitmapDrawable: BitmapDrawable
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bitmapDrawable = getDrawable(R.drawable.icon_here) as BitmapDrawable
} else {
bitmapDrawable = resources.getDrawable(R.drawable.icon_here) as BitmapDrawable
}
discriptor = BitmapDescriptorFactory.fromBitmap(bitmapDrawable.bitmap)
}
@SuppressLint("MissingPermission")
fun updateLocation() {
/* 위치 정보를 요청할 locationRequest 생성하고 정확도와 주기를 설정 */
val locationRequest = LocationRequest.create()
locationRequest.run {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = 1000
}
locationCallback = object : LocationCallback() { // 해당 주기마다 반환받을 locationCallback
override fun onLocationResult(locationResult: LocationResult?) {
locationResult?.let {
for(location in it.locations) {
Log.d("Location", "${location.latitude} , ${location.longitude}")
setLastLocation(location)
}
}
}
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
}
◽ fusedLocationClient.requestLocationUpdates 코드는 권한 처리가 필요한데, 현재 코드에서는 확인할 수 없기 때문에 메서드 상단에 해당 코드에 대한 권한은 체크하지 않아도 된다는 의미로 @SuppressLint("MissingPermission")를 붙여준다.
◽ 해당 코드의 마지막 requestLocationUpdates을 실행하면 이제 1초마다 한 번씩 변화된 위치 정보가 LocationCallback의 onLocationResult()로 전달된다.
◽ onLocationResult()는 반환받은 정보에서 위치 정보를 setLastLocation()으로 전달한다.
fun setLastLocation(lastLocation: Location) {
val LATLNG = LatLng(lastLocation.latitude, lastLocation.longitude) // 전달받은 위치를 좌표로 마커를 생성
/* 마커 추가 및 옵션 */
val markerOptions = MarkerOptions() // 마커 추가
.position(LATLNG) // 마커의 좌표
.title("Here!") // 마커의 제목
.icon(discriptor)
// .snippet("정보창 추가")
/* 카메라 위치를 현재 위치로 세팅하고 마커와 함께 지도에 반영 */
val cameraPosition = CameraPosition.Builder()
.target(LATLNG) // 카메라의 목표 지점
.zoom(15.0f) // 카메라 줌
.build()
// bearing : 지도의 수직선이 북쪽을 기준으로 시계 방향 단위로 측정되는 방향
// tilt : 카메라의 기울기
mMap.clear() // 마커를 지도에 반영하기 전에 clear를 사용해서 이전에 그려진 마커가 있으면 지운다.
mMap.addMarker(markerOptions) // 지도에 마커를 추가
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
// CameraUpdateFactory.newCameraPosition(cameraPosition) : 카메라 포지션에 지도에서 사용할 수 있는 카메라 정보가 생성된다.
// mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) : 카메라 포지션을 기준으로 지도의 위치, 배율, 기울기 등이 변경돼서 표시된다.
}
'Android > Code' 카테고리의 다른 글
[Android] [Kotlin] 객체 인스턴스 (0) | 2021.11.05 |
---|---|
[Project] [Android] [Kotlin] Log Window (0) | 2021.10.18 |
[Android] [Kotlin] EditText 자동 포커싱 및 키보드 (0) | 2021.09.23 |
[Android] [Kotlin] Dialog로 액티비티 띄우기 (0) | 2021.09.15 |
[Android] [Kotlin] chooser Intent (카메라, 갤러리) (0) | 2021.09.12 |