1. GoogleCloud에서 사용자 인증키 만들기
환영합니다 – donlate – Google Cloud Console
Google 클라우드 플랫폼
로그인 Google 클라우드 플랫폼으로 이동
accounts.google.com
- GoogleCloud 접속
- 새 프로젝트 생성
- 사용자 인증정보 만들기 > API키 > API 키 생성
2. 지도 사용 설정하기
- build.gradle
implementation ("com.google.android.gms:play-services-maps:18.1.0")
implementation ("com.google.android.gms:play-services-location:21.0.1")
- manifest > 권한 및 구글 지도 API를 이용하는 키를 등록
...
<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="### 구글 지도 API 키 등록 ###"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
3. 지도 제어하기
- 지도의 중심 이동하기 : 지도를 출력하는 뷰 객체를 얻어야 함
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
var googleMap: GoogleMap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment)!!.getMapAsync(this)
// 지도 객체를 이용할 수 있는 상황이 될 때
override fun onMapReady(p0: GoogleMap?) {
googleMap = p0
}
}
- 지도의 중심을 이동
val latLng = LatLng(37.566610, 126.978403)
val position = CameraPosition.Builder()
.target(latLng)
.zoom(18f)
.build()
googleMap?.moveCamera(CameraUpdateFactory.newCameraPosition(position))
- 마커 표시하기
val markerOptions = MarkerOptions()
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
markerOptions.position(latLng)
markerOptions.title("서울시청")
markerOptions.snippet("Tel:01-120")
googleMap?.addMarker(markerOptions)
- 위치 요청
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}")
}
}
}
}
- 지도에서 사용자 이벤트 처리
- GoogleMap.OnMapClickListener: 지도 클릭 이벤트
- GoogleMap.OnMapLongClickListener: 지도 롱 클릭 이벤트
- GoogleMap.OnMarkerClickListener: 마커 클릭 이벤트
- GoogleMap.OnMarkerDragListener: 마커 드래그 이벤트
- GoogleMap.OnInfoWindowClickListener: 정보 창 클릭 이벤트
- GoogleMap.OnCameraIdleListener: 지도 화면 변경 이벤트
googleMap?.setOnMapClickListener { latLng ->
Log.d("map_test", "click : ${latLng.latitude} , ${latLng.longitude}")
}
googleMap?.setOnMapLongClickListener { latLng ->
Log.d("map_test", "long click : ${latLng.latitude} , ${latLng.longitude}")
}
googleMap?.setOnCameraIdleListener {
val position = googleMap!!.cameraPosition
val zoom = position.zoom
val latitude = position.target.latitude
val longitude = position.target.longitude
Log.d("map_test", "User change : $zoom $latitude , $longitude")
}
googleMap?.setOnMarkerClickListener { marker ->
true
}
googleMap?.setOnInfoWindowClickListener { marker ->
}
4. 구현
- 예제에선 Activity에서 구현하였지만 Fragment에서 구현해보기로 함
더보기
- fragment_search_place.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".searchPlace.SearchPlaceFragment">
<fragment
android:id="@+id/mv_searchResultMapView"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="350dp"
android:layout_height="550dp"
android:layout_marginTop="50dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_placeSeachBox" />
</androidx.constraintlayout.widget.ConstraintLayout>
- SearchPlaceFragment.kt
package com.example.donotlate.searchPlace
import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import com.example.donotlate.R
import com.example.donotlate.databinding.FragmentSearchPlaceBinding
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
class SearchPlaceFragment : Fragment(), OnMapReadyCallback {
private lateinit var mGoogleMap: GoogleMap
//위치 서비스가 gps를 사용해서 위치를 확인
lateinit var fusedLocationClient: FusedLocationProviderClient
//위치 값 요청에 대한 갱신 정보를 받는 변수
lateinit var locationCallback: LocationCallback
lateinit var locationPermission: ActivityResultLauncher<Array<String>>
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_search_place, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
locationPermission = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { results ->
if (results.all { it.value }) {
(childFragmentManager.findFragmentById(R.id.mv_searchResultMapView) as SupportMapFragment)!!.getMapAsync(
this
)//fragment안의 fragment를 찾기 때문에 childFragmentManager
// (parentFragmentManager.findFragmentById(R.id.mv_searchResultMapView) as SupportMapFragment)!!.getMapAsync(
// this
// )//name="com.google.android.gms.maps.SupportMapFragment" 지정했기 때문에 .SupportMapFragment로 타입캐스팅
} else { //문제가 발생했을 때
}
}
//권한 요청
locationPermission.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
// 지도 객체를 이용할 수 있는 상황이 될 때
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(requireActivity())
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(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
requireContext(),
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))
}
}
'Android' 카테고리의 다른 글
Android Studio_ 12. Google Places(New) API 사용하기 (1) | 2024.06.06 |
---|---|
Android Studio_ 11. Mapping 처리 방법 (0) | 2024.06.01 |
Android Studio_ 0-3. Guideline, Barrier, ViewGroup (0) | 2024.04.30 |
Android Studio_ 9. Figma(피그마)에서 이미지 추출해서 사용하기 (0) | 2024.04.24 |
Android Studio_ 8-1. Fragment (프래그먼트) 데이터 전달 (1) | 2024.04.19 |