W1 D2: 사용자의 현재 위치 가져오기 및 저장 👤📍

그래서 지난 글에서는 안드로이드 앱에 구글맵을 추가했습니다. 이것은 그 기사의 연속입니다. 이제 사용자의 현재 위치를 가져오고 카메라 위치와 함께 지도 상태를 저장해 보겠습니다.

1주차 🗺️



이번 주에 우리는 Android에서 지도에 관한 모든 것을 할 것입니다. 지도에 마커를 추가하고, 지도 스타일을 지정하고, 지오펜스를 추가하고, 사용자의 마지막으로 알려진 위치를 가져오는 등의 스턴트를 수행할 수 있는 것은 이 영역에 대한 지식에 필수적입니다(말장난 의도). 이러한 것들은 위치 공유, 사용자 위치에 따라 알림 전송 등과 같은 기능을 추가하는 방법을 알고 싶다면 매우 유용하고 매우 중요합니다.

📍 👍.

  • 추가 위치 권한
  • EasyPermissions 라이브러리를 사용한 증분 위치 권한
  • Firebase를 사용하여 위치 데이터 공유
  • 실시간 위치 추적/공유
  • 길게 클릭하면 지도에 마커 추가 및 표시된 위치/POI 저장

  • 2일차: 사용자의 현재 위치 가져오기 및 저장



    이 스턴트는 세 부분으로 나뉩니다.
  • 사용자의 장치 위치를 가져오기 위한 준비(권한 가져오기, UI 설정 등)
  • 사용자의 현재 장치 위치 가져오기
  • 지도 상태 및 카메라 위치 저장

  • 알겠습니다. 방해 요소를 모두 차단하고 수분을 섭취하세요. 이제 이 부분을 완료하겠습니다.


    사용자의 기기 위치 확인 준비


  • 방금 생성한 Google Cloud 프로젝트에서 Places SDK를 활성화합니다.
  • Google Cloud Console -> 프로젝트 선택 -> API -> Places SDK -> 활성화

  • 위치 종속성 추가(앱: build.gradle)
  • 'com.google.android.libraries.places:places:2.4.0' 구현


  • Places API 클라이언트 인스턴스화
  • PlacesClient 객체 및 FusedLocationProviderClient 객체를 만듭니다.

        // MapsActivity.kt
    
        private lateinit var placesClient: PlacesClient
        private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    
        override fun onCreate(savedInstanceState: Bundle?) {
                ...
    
                // Create PlacesClient
            Places.initialize(applicationContext, getString(R.string.maps_api_key))
            placesClient = Places.createClient(this)
    
            // Create FusedLocationProviderClient
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        }
    





  • 위치 권한 요청

  • FINE_LOCATION용 앱에 정밀 위치 권한 추가

        // AndroidManifest.xml
    
        <!--
             The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
             Google Maps Android API v2, but you must specify either coarse or fine
             location permissions for the "MyLocation" functionality.
        -->
        <uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION" />
    




  • FINE_LOCATION에 대한 런타임 권한 요청

                // MapsActivity.kt
    
                    private var locationPermissionGranted = false
    
                    private fun getLocationPermission() {
                    /*
                     * Request location permission, so that we can get the location of the
                     * device. The result of the permission request is handled by a callback,
                     * onRequestPermissionsResult.
                     */
                    if (ContextCompat.checkSelfPermission(this.applicationContext, 
                            android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        locationPermissionGranted = true
                    } else {
                        ActivityCompat.requestPermissions(this, 
                            arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 
                            PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
                        )
                    }
                }
    
                    companion object {
                        private const val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 111
                    }
    




  • 권한 요청 결과 처리

                    // MapsActivity.kt      
    
                    override fun onRequestPermissionsResult(requestCode: Int,
                                                        permissions: Array<String>,
                                                        grantResults: IntArray) {
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
                    locationPermissionGranted = false
                    when (requestCode) {
                        PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> {
    
                            // If request is cancelled, the result arrays are empty. But if the user has now
                            // granted the permission (after we requested), the result array contains that permission.
                            if (grantResults.isNotEmpty() &&
                                grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                                locationPermissionGranted = true
                            }
                        }
                    }
                }
    




  • UI 업데이트

  • 사용자가 권한을 부여한 경우 UI 업데이트

        // mAPSaCTIVITY.KT
        private var lastKnownLocation = null
    
        override fun onMapReady(googleMap: GoogleMap) {
            ...
            // Turn on the My Location layer and the related control on the map.
            updateLocationUI()
        }
    
        override fun onRequestPermissionsResult(...) {
            ...
            updateLocationUI()
        }       
    
        private fun updateLocationUI() {
            /**
             * If the user has granted the FINE_LOCATION permission, update the UI else don't
             */
            if (mMap == null) {
                return
            }
            try {
                if (locationPermissionGranted) {
                    mMap.isMyLocationEnabled = true
                    mMap.uiSettings.isMyLocationButtonEnabled = true
                } else {
                    mMap.isMyLocationEnabled = false
                    mMap.uiSettings.isMyLocationButtonEnabled = false
                    lastKnownLocation = null
                    getLocationPermission()
                }
            } catch (e: SecurityException) {
                Log.e("Exception: %s", e.message, e)
            }
        }
    



  • Android 기기의 위치 확인 및 지도 위치 지정



  • 장치 위치 확인

            // MapsActivity.kt
    
                private var lastKnownLocation: Location? = null
                private val defaultLocation = LatLng(-34.0, 151.0)      // Sydney       
    
                override fun onMapReady(googleMap: GoogleMap) {
                        ...
                    // Get the current location of the device and set the position of the map.
                    getDeviceLocation()
                }
    
                private fun getDeviceLocation() {
                /*
                 * Get the best and most recent location of the device, which may be null in rare
                 * cases when a location is not available.
                 */
                try {
                    if (locationPermissionGranted) {
                        val locationResult = fusedLocationProviderClient.lastLocation
                        locationResult.addOnCompleteListener(this) { task ->
                            if (task.isSuccessful) {
                                // Set the map's camera position to the current location of the device.
                                lastKnownLocation = task.result
                                if (lastKnownLocation != null) {
                                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                                        LatLng(lastKnownLocation!!.latitude,
                                            lastKnownLocation!!.longitude), DEFAULT_ZOOM))
                                }
                            } else {
                                Log.d(TAG, "Current location is null. Using defaults.")
                                Log.e(TAG, "Exception: %s", task.exception)
                                mMap.moveCamera(CameraUpdateFactory
                                    .newLatLngZoom(defaultLocation, DEFAULT_ZOOM))
                                mMap.uiSettings.isMyLocationButtonEnabled = false
                            }
                        }
                    }
                } catch (e: SecurityException) {
                    Log.e("Exception: %s", e.message, e)
                }
            }
    
            companion object {
                 private const val DEFAULT_ZOOM = 50F
             }
    
        ```
    {% endraw %}
    
    Now run the app. After allowing the app to get your location, you'll see that the map zooms in to your current location, displaying a blue circle at your precise latitude & longitude. Great! 🍻
    ![55.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631373417221/GE0fvfGUg.png)
    ![44.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631373423561/r2MR9A-Ry.png)
    

  • 맵 상태 저장



  • 지도의 상태 및 카메라 위치 저장
  • 저장할 값을 설정합니다
  • .
  • 상태 저장

  • onCreate()에서 저장된 상태 검색
    {% 날것의 %}
    // MapsActivity.kt      
    
    private var cameraPosition: CameraPosition? = CameraPosition(defaultLocation, DEFAULT_ZOOM, 0.0F, 0.0F)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            // Retrieve the user's saved map state & camera position
            if (savedInstanceState != null) {
                lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION)
                cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION)
            }
        }
    
        override fun onSaveInstanceState(outState: Bundle) {
            /**
             * Save the map's state & camera position when the activity is destroyed
             * (like in a configuration change)
             */
            mMap.let { map ->
                outState.putParcelable(KEY_CAMERA_POSITION, map.cameraPosition)
                outState.putParcelable(KEY_LOCATION, lastKnownLocation)
            }
            super.onSaveInstanceState(outState)
        }
    
        companion object {
            ...
            private const val KEY_CAMERA_POSITION = "camera_position"
            private const val KEY_LOCATION = "location"
        }
    



  • 이거 야. 이제 앱을 실행하고 회전합니다. 마커가 지속되는 것을 볼 수 있습니다. 이제 앱 사용자의 현재 위치를 성공적으로 가져오고 저장했습니다! 🎊

    좋은 웹페이지 즐겨찾기