Kotlin/TIL

Android -GoogleMap 사용 (TIL 05.01)

내손은개발 🐾 2024. 5. 1. 20:58

아주 이전에 naverMap을 사용해서 정리한 적이 있다.

 

 

이번 강의에서 googleMap을 사용해서 구글 지도에 현재 위치와 특정위치에 마커를 띄우는 학습을 진행했다.

 

사용 방법

1. gradle

dependencies {
		
		...

    implementation ("com.google.android.gms:play-services-maps:18.1.0")
    implementation ("com.google.android.gms:play-services-location:21.0.1")
}

 

2. manifests

//permissions
<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 { [1]

    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}){
                (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
            )
        )
    }


    // 지도 객체를 이용할 수 있는 상황이 될 때
    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() [2]
            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(){ [4]

        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){ [3]
        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))
    }
}

코드 분석

 

[1] OnMapReadyCallback

  • 지도 객체를 얻으려면 OnMapReadyCallback 인터페이스를 구현한 클래스를 getMapAsync()함수를 이용하여 등록한다.
    • 이렇게 하면 지도 객체를 사용할 수 있을때 onMapReady() 함수가 지동으로 호출되면서 매개변수로 GoogleMap 객체가 전달된다.
    • 필수로 onMapReady를 오버라이드 해야한다.

[2] 마커 찍기

[3] 현재 위치 마커

  • 지도 내에 특정 위치는 LatLng으로 위도와 경도를 준다.
  • 지도의 중심 위치를 target() 함수로, 지도의 확대 수준을 zoom()함수로 지정한다.
  • CameraPosition을 GoogleMap의 moveCamera()함수의 매개변수로 지정하면 CameraPosition 정보대로 지도에 표시된다.
    • 현재 코드에서는 현재위치의 위경도 자리에 뜬다.

[4] 현재 위치 갱신

 

 

 

 

 

지도 추가  |  Android용 Maps SDK  |  Google for Developers

의견 보내기 지도 추가 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 플랫폼 선택: Android iOS JavaScript 이 주제에서는 Android용 Maps SDK를 사용하도록 프로젝트

developers.google.com

naverMap과 마찬가지로 공식문서에 정말 자세히 나와있다.

예제에서는 간단히 현재위치와 특정위치 마커를 찍는 부분을 진행했는데

더 찾아볼 필요없이 구글 공식문서만 사용해도 기존 지도앱 기능 절반 이상 사용방법이 있는 것 같다.

'Kotlin > TIL' 카테고리의 다른 글

TIL (05.07)  (0) 2024.05.07
Postman 사용하기 (TIL 05.02)  (0) 2024.05.02
SharedPreference (TIL 04.30)  (0) 2024.04.30
TIL (04.29) - LiveData 실습  (0) 2024.04.29
TIL (04.23)  (0) 2024.04.23