본문 바로가기
안드로이드(android)

Android(Kotlin) / 네이버 지도 현재 위치

by clean_h 2021. 4. 6.
728x90

네이버 지도 현재위치 표시

지도를 사용하는 앱은 사용자의 위치를 지도에 표현한다. 

네이버 지도 SDK는 이런 기능을 손쉽게 구현할 수 있도록 위치 오버레이와 위치 추적 기능을 제공한다.

 

위치 오버레이 - 사용자의 위치를 지도에 나타내고자 할 때 위치 오버레이를 사용하는 것이 권장된다.

 

 

1.  권한을 추가

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 위치정보 사용을 위해 권한을 추가-->

네이버 지도 SDK는 기본적으로 사용자의 위치 정보를 사용하지 않으므로 사용자에게 관련된 권한을 요구하지 않는다. 따라서 위치 추적 기능을 사용하고자 하는 앱은 AndroidManifest.xml에 'ACCESS_COARSE_LOCATION' 와 'ACCESS_FINE_LOCATION' 권한을명시해야한다.

 

 

FusedLocationSource를 사용하기 위해 앱 모듈의 build.gradle에 play-services-location 을 추가한다. 

implementation("com.google.android.gms:play-services-location:16.0.0")

네이버 지도 SDK는 Google Play 서비스의 FusedLocationProviderClient와 지자기, 가속도 센서를 활용해 최적의 위치를 반환하는 구현체인 FusedLocationSource를 제공한다. 

 

 

2. MainActivity 함수

권한을 가져오기 위해 다음과 같이 MainActivity에 추가한다. 

var permissions = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION)
//권한 가져오기

 

  • override fun onCreate()

    override fun onCreate(savedInstanceState: Bundle?) {
        //activity가 최초 실행 되면 이곳을 수행

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.

        if (isPermitted()) {
            startProcess()
        } else {
            ActivityCompat.requestPermissions(this, permissions, permission_request)
        }//권한 확인
    }

onCreate함수는 activity가 최초 실행되면 수행하는 함수이다.

activity_main을 실행하고 위치 권한을 확인해야한다.

앱을 처음 실행할 때 위치 권한을 묻는 메세지에 위치 권한을 허락해야한다. 

위치 권한이 없다면 현재위치를 받아오지 못한다. 

 

  • fun isPermitted()

    fun isPermitted(): Boolean {
        for (perm in permissions) {
            if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
                return false
            }
        }
        return true
    }//권한을 허락 받아야함

권한이 있는지 허락을 받아야한다. 

권한이 있다면 ture, 권한이 없다면 false이다. 

 

  • fun startProcess()

    fun startProcess(){
        val fm = supportFragmentManager
        val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
            ?: MapFragment.newInstance().also {
                fm.beginTransaction().add(R.id.map, it).commit()
            } //권한
        mapFragment.getMapAsync(this)
    } //권한이 있다면 onMapReady연결

권한이 있다면 startProcess함수를 실행한다.

권한이 있는것을 확인하고, callback으로 onMapReady에 연결한다. 

 

 

  • override fun onMapReady(naverMap: NaverMap)

    override fun onMapReady(naverMap: NaverMap){
        val cameraPosition = CameraPosition(
            LatLng(37.5666102, 126.9783881),  // 위치 지정
            16.0 // 줌 레벨
        )
        naverMap.cameraPosition = cameraPosition
        this.naverMap = naverMap

        fusedLocationProviderClient =
            LocationServices.getFusedLocationProviderClient(this) //gps 자동으로 받아오기
        setUpdateLocationListner() //내위치를 가져오는 코드
    }

GPS를 가져오는 코드이다.

카메라의 position을 정해준다. (여기서 이 좌표는 현재 gps로 이동할 것이므로 어느 좌표든 상관없다.)

 

 

  • fun setUpdateLocationListner()

    fun setUpdateLocationListner() {
        val locationRequest = LocationRequest.create()
        locationRequest.run {
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY //높은 정확도
            interval = 1000 //1초에 한번씩 GPS 요청
        }

        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                locationResult ?: return
                for ((i, location) in locationResult.locations.withIndex()) {
                    Log.d("location: ", "${location.latitude}, ${location.longitude}")
                    setLastLocation(location)
                }
            }
        }
        //location 요청 함수 호출 (locationRequest, locationCallback)

        fusedLocationProviderClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.myLooper()
        )
    }//좌표계를 주기적으로 갱신

 내 위치를 가져오는 코드이다. 

1초에 한번씩 GPS를 요청하고 GPS를 location에 저장한다. 

GPS를 요쳥하는 locationRequest과 callback하는 LocationCallback을 받아올 수 있다. 

 

 

  • fun setLastLocation(location: Location)

    fun setLastLocation(location: Location) {
        val myLocation = LatLng(location.latitude, location.longitude)
        val marker = Marker()
        marker.position = myLocation

        marker.map = naverMap
        //마커
        val cameraUpdate = CameraUpdate.scrollTo(myLocation)
        naverMap.moveCamera(cameraUpdate)
        naverMap.maxZoom = 18.0
        naverMap.minZoom = 5.0

        //marker.map = null
    }

setUpdateLocationListner함수에서 받아온 GPS 좌표를 입력받아 마커로 현재위치를 출력할 수 있다.

여기서 화면크기에 맞게 zoom을 설정해주었다. 

 

Main Activity 전체 코드

전체 코드는 다음과 같다.

package com.example.map_matching_realtime

import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.graphics.Color
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.annotation.UiThread
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import com.google.android.gms.location.*
import com.naver.maps.geometry.LatLng
import com.naver.maps.map.*
import com.naver.maps.map.overlay.Marker

class MainActivity : FragmentActivity(), OnMapReadyCallback {

    val permission_request = 99
    private lateinit var naverMap: NaverMap
    var permissions = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION)
    //권한 가져오기

    override fun onCreate(savedInstanceState: Bundle?) {
        //activity가 최초 실행 되면 이곳을 수행

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.

        if (isPermitted()) {
            startProcess()
        } else {
            ActivityCompat.requestPermissions(this, permissions, permission_request)
        }//권한 확인
    }

    fun isPermitted(): Boolean {
        for (perm in permissions) {
            if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
                return false
            }
        }
        return true
    }//권한을 허락 받아야함

    fun startProcess(){
        val fm = supportFragmentManager
        val mapFragment = fm.findFragmentById(R.id.map) as MapFragment?
            ?: MapFragment.newInstance().also {
                fm.beginTransaction().add(R.id.map, it).commit()
            } //권한
        mapFragment.getMapAsync(this)
    } //권한이 있다면 onMapReady연결


    @UiThread
    override fun onMapReady(naverMap: NaverMap){
    
        val cameraPosition = CameraPosition(
            LatLng(37.5666102, 126.9783881),  // 위치 지정
            16.0 // 줌 레벨
        )
        naverMap.cameraPosition = cameraPosition
        this.naverMap = naverMap
        
        fusedLocationProviderClient =
            LocationServices.getFusedLocationProviderClient(this) //gps 자동으로 받아오기
        setUpdateLocationListner() //내위치를 가져오는 코드
    }

    //내 위치를 가져오는 코드
    lateinit var fusedLocationProviderClient: FusedLocationProviderClient //자동으로 gps값을 받아온다.
    lateinit var locationCallback: LocationCallback //gps응답 값을 가져온다.
    //lateinit: 나중에 초기화 해주겠다는 의미

    @SuppressLint("MissingPermission")
    fun setUpdateLocationListner() {
        val locationRequest = LocationRequest.create()
        locationRequest.run {
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY //높은 정확도
            interval = 1000 //1초에 한번씩 GPS 요청
        }

        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                locationResult ?: return
                for ((i, location) in locationResult.locations.withIndex()) {
                    Log.d("location: ", "${location.latitude}, ${location.longitude}")
                    setLastLocation(location)
                }
            }
        }
        //location 요청 함수 호출 (locationRequest, locationCallback)

        fusedLocationProviderClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.myLooper()
        )
    }//좌표계를 주기적으로 갱신

    fun setLastLocation(location: Location) {
        val myLocation = LatLng(location.latitude, location.longitude)
        val marker = Marker()
        marker.position = myLocation

        marker.map = naverMap
        //마커
        val cameraUpdate = CameraUpdate.scrollTo(myLocation)
        naverMap.moveCamera(cameraUpdate)
        naverMap.maxZoom = 18.0
        naverMap.minZoom = 5.0

        //marker.map = null
    }

}

 

3. 화면

광운대 새빛관

현재 위치 광운대 새빛관이 출력되는것을 확인할 수 있다. 

 

 

 

참고 - navermaps.github.io/android-map-sdk/guide-ko/4-2.html 

 

위치 · 네이버 지도 안드로이드 SDK

No results matching ""

navermaps.github.io

 

728x90

댓글