Android Naver Map 현재 위치 적용하기

pass·2023년 8월 24일
1

Android

목록 보기
28/41

🔥 Android 에서 Naver Map 에 현재 위치를 적용해보자.

공식 문서


지난 글에서 Android 에 Naver Map API 를 사용하여 지도를 띄우는 과정을 살펴보았다.
이어서 지도에 현재 위치를 적용하여 지도가 현재 위치 기준으로 띄워지도록 추가해보자.



🗾 지도 객체 가져오기

하나의 지도는 뷰 요소와 인터페이스 요소로 구성됩니다. 뷰 요소는 화면에 지도를 나타내는 역할을 하며, MapFragment와 MapView가 여기에 해당합니다. 지도를 다루는 인터페이스 역할을 하는 인터페이스 요소는 NaverMap 클래스가 담당하며, 오버레이를 추가하고 상호작용하는 등 지도와 관련된 기능 대부분을 이 클래스에서 제공합니다. MapFragment 및 MapView는 개발자가 직접 생성할 수 있으나 NaverMap 객체는 오직 콜백 메서드를 이용해서 얻어올 수 있습니다.

위의 내용은 공식 문서의 내용이다. 지난 글에서 MapFragment 를 이용하여 지도를 나타내었으므로, 지도를 다루기 위해 API 에서 제공해주는 NaverMap 객체를 가져오도록 하자.


class MainActivity : AppCompatActivity(), OnMapReadyCallback {
	private lateinit var naverMap: NaverMap
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.map_fragment_activity)

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

    @UiThread
    override fun onMapReady(naverMap: NaverMap) {
        this.naverMap = naverMap
    }
}

Naver Map 은 MapFragment 또는 MapView의 getMapAsync() 메서드로 OnMapReadyCallback을 등록하면 비동기로 NaverMap 객체를 얻을 수 있다고 나와있다. NaverMap 객체가 준비되면 onMapReady() 콜백 메서드가 호출된다. 위의 내용은 NaverMap 객체를 가져오는 예제이다.

  • OnMapReadyCallBack implement
  • onMapReady override



📍 현재 위치 정보 등록하기

✓ Manifest.xml 에 권한 추가

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • Android 에서 위치 권한 획득을 위해 Manifest.xml 에 선언한다.
  • 런타임 권한이기 때문에 사용자에게 추가로 권한 요청을 해야 한다.

✓ FusedLocationSource

공식 문서에 따르면 네이버 지도 SDK 는 Google Play 서비스의 FusedLocationProviderClient와 지자기, 가속도 센서를 활용해 최적의 위치를 반환하는 구현체인 FusedLocationSource를 제공한다고 한다. 위치 정보를 사용할 때, FusedLocationSource를 사용하길 권장하고 있으므로 사용해보도록 하자.

build.gradle

implementation 'com.google.android.gms:play-services-location:21.0.1'

위치 권한 요청

override fun onCreate(savedInstanceState: Bundle?) {
		//...

        // 위치 권한 요청
        locationPermissionRequest.launch(arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION))
}


private val locationPermissionRequest = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
    when {
        permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
            // Precise location access granted.
        }
        permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
            // Only approximate location access granted.
        } else -> {
            // No location access granted
            Toast.makeText(this, "위치 권한을 허용해주세요.", Toast.LENGTH_SHORT)
            finish()
        }
    }
}

FusedLocationSource 에 위치 정보 전달

private lateinit var locationSource: FusedLocationSource

override fun onCreate(savedInstanceState: Bundle?) {
		//...

		locationSource = FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE)
        //...
}

override fun onMapReady(naverMap: NaverMap) {
    this.naverMap = naverMap
    naverMap.locationSource = locationSource
    naverMap.locationTrackingMode = LocationTrackingMode.Follow
}

companion object {
    private const val LOCATION_PERMISSION_REQUEST_CODE = 1000
}



🏁 최종 결과

class MainActivity : AppCompatActivity(), OnMapReadyCallback {
	companion object {
    	private const val LOCATION_PERMISSION_REQUEST_CODE = 1000
	}
    
	private lateinit var locationSource: FusedLocationSource
	private lateinit var naverMap: NaverMap
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.map_fragment_activity)
        
        // 위치 권한 요청
        locationPermissionRequest.launch(arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION))
            
        // FusedLocation
        locationSource = FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE)

		// naverMap 객체 획득을 위한 getMapAsync() 수행
        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)
    }

    @UiThread
    override fun onMapReady(naverMap: NaverMap) {
    	// naverMap 객체 획득
        this.naverMap = naverMap
        
        // naverMap locationSource 에 FusedLocationSource 적용
        naverMap.locationSource = locationSource
        naverMap.locationTrackingMode = LocationTrackingMode.Follow
    }
    
    private val locationPermissionRequest = registerForActivityResult(
    	ActivityResultContracts.RequestMultiplePermissions()
	) { permissions ->
    	when {
       	 	permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
	            // Precise location access granted.
    	    }
       	 	permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
	            // Only approximate location access granted.
    	    } else -> {
        	    // No location access granted
            	Toast.makeText(this, "위치 권한을 허용해주세요.", Toast.LENGTH_SHORT)
	            finish()
    	    }
	    }
	}
}
위치 설정결과
profile
안드로이드 개발자 지망생

0개의 댓글