안드로이드/개발관련(Kotlin)

안드로이드 GPS로 현재 내 위치좌표 구하는법(Kotlin)

닉네임못짓는사람 2023. 2. 27. 20:07
반응형

이번 글에서는 안드로이드에서 현재 내 위치좌표를 알아보는 방법을 알아보자.

먼저, 내 좌표를 구하기 위해서는 ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION권한이필요하다.

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Manifest파일에 위와 같이 추가해주도록 하자.

 

다음으로 좌표를 불러올 때 사용할 버튼 하나를 액티비티에 추가해주자

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
</LinearLayout>

사전 준비가 끝낫다면 본격적으로 좌표를 구해보기 위해 MainActivity로 이동하자.

 

먼저, 현재 위치를 다른 함수로부터 받아와 Log에 남겨주는 getLocation함수를 만들어보자.

    private fun getLocation(){
        locatioNManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager?
        var userLocation: Location = getLatLng()
        if(userLocation != null){
            latitude = userLocation.latitude
            longitude = userLocation.longitude
            Log.d("CheckCurrentLocation", "현재 내 위치 값: ${latitude}, ${longitude}")

            var mGeoCoder =  Geocoder(applicationContext, Locale.KOREAN)
            var mResultList: List<Address>? = null
            try{
                mResultList = mGeoCoder.getFromLocation(
                        latitude!!, longitude!!, 1
                )
            }catch(e: IOException){
                e.printStackTrace()
            }
            if(mResultList != null){
                Log.d("CheckCurrentLocation", mResultList[0].getAddressLine(0))
            }
        }
    }

여기서 latitude는 위도, longitude는 경도를 의미한다.

위도와 경도값을 받아오면, 이를 사용해 현재 우리가 위치한 주소를 Log로 출력할 것이다.

이는 GeoCoder를 사용해서 위도, 경도를 실제 주소로 변환해주는 과정을 거칠 것이다.

 

다음으로는 실제로 우리의 좌표를 구하는 함수인 getLatLng함수를 구현해보자.

    private fun getLatLng(): Location{
        var currentLatLng: Location? = null
        var hasFineLocationPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
        var hasCoarseLocationPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION)
                
        if(hasFineLocationPermission == PackageManager.PERMISSION_GRANTED &&
                hasCoarseLocationPermission == PackageManager.PERMISSION_GRANTED){
            val locatioNProvider = LocationManager.GPS_PROVIDER
            currentLatLng = locatioNManager?.getLastKnownLocation(locatioNProvider)
        }else{
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[0])){
                Toast.makeText(this, "앱을 실행하려면 위치 접근 권한이 필요합니다.", Toast.LENGTH_SHORT).show()
                ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSIONS_REQUEST_CODE)
            }else{
                ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSIONS_REQUEST_CODE)
            }
            currentLatLng = getLatLng()
        }
        return currentLatLng!!
    }

위에서 말했듯이 gps좌표를 구하기 위해서는 권한이 필요한데, getLatLng함수에서 실제로 위치 정보를

가져오기 전에 반드시 Permission을 체크해주어야 한다.

 

위의 코드는 ACCESS_COARSE_LOCATION권한과 ACCESS_FINE_LOCATION권한이 허용되어 있을 경우

좌표를 구하고, 허용되있지 않을 경우  권한을 요청한 뒤, 다시 getLatLng함수를 호출하도록 하는 코드이다.

 

중요한 점은 위에서 좌표를 구할 때 GPS_PROVIDER를 사용하는데, 실내에서는 GPS로 위치정보를 구할 수 없다.

때문에 실내에 있을 경우 NETWORK_PROVIDER를 사용해서 위치 정보를 구해야 한다.

다만, NETWORK_PROVIDER는 GPS에 비해 정확도가 떨어진다는 단점이 있다.

 

실제로 위치 정보를 구해서 사용할 때에는 GPS_PROVIDER와 NETWORK_PROVIDER를 둘 다 사용하여

정확도가 더 높은 쪽을 사용하거나, GPS로 위치를 구할 수 없으면 NETWORK로 위치를 구하는 방식을 사용하는게 좋다.

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if(requestCode == PERMISSIONS_REQUEST_CODE && grantResults.size == REQUIRED_PERMISSIONS.size){
            var check_result = true
            for(result in grantResults){
                if(result != PackageManager.PERMISSION_GRANTED){
                    check_result = false;
                    break;
                }
            }
            if(check_result){
            }else{
                if(ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[0])
                        || ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[1])){
                    Toast.makeText(this, "권한 설정이 거부되었습니다.\n앱을 사용하시려면 다시 실행해주세요.", Toast.LENGTH_SHORT).show()
                    finish()
                }else{
                    Toast.makeText(this, "권한 설정이 거부되었습니다.\n설정에서 권한을 허용해야 합니다..", Toast.LENGTH_SHORT).show()
                }
            }
        }

권한 요청 시의 onRequestPermissionResult함수이다.

if(check_result)부분이 권한을 허용했을 경우 실행하는 부분이고, else는 그 반대이다.

 

이렇게 모든 코드를 작성하고 실행시키면 다음과 같이 결과가 나온다.

반응형