인터넷 연결 없이 위치 기반으로 현재 시각 가져오기

Hue·2023년 10월 24일
0

Android/Kotlin

목록 보기
32/42

인터넷 접근을 막아둔 상태에서 현재 시각이 필요한 상황.
gps를 이용해 현재위치를 가져오고 현재위치의 경도 값으로 시간을 가져오기로 했다.

1. Manifest에 위치 기반 서비스를 이용하기 위한 permission 추가

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

2. FINE_LOCATION에 접근하기 위해 명시적 퍼미션

 var permissionLauncher = registerForActivityResult<String, Boolean>(ActivityResultContracts.RequestPermission(),
        object : ActivityResultCallback<Boolean?> {
            override fun onActivityResult(result: Boolean?) {
                result?.let {
                    // 위치 정보 제공 허용했을 경우
                    return
                }
                // 위치 정보 제공 거부했을 경우
            }
        })

위치 정보 퍼미션을 요청하고 그에 대한 결과를 받아오는 작업을 하는 permissionLauncher를 만든다.

val checkPermission = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
if (checkPermission == PackageManager.PERMISSION_DENIED) permissionLauncher.launch(android.Manifest.permission.ACCESS_FINE_LOCATION)

onCreate() 되었을때, 퍼미션이 거부되어있다면 permissionLauncher를 이용하여 퍼미션 작업을 한다.


3. 위치 정보 받아오는 메소드

위치 정보 관리자 역할을 하는 locationManager 객체를 생성한다.

locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

다른 메소드에서도 불러서 사용할 수 있도록 전역변수에 대입해주었다.

private fun findLocation() {

        if (ActivityCompat.checkSelfPermission(
                this, android.Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                this, android.Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) return

        locationManager!!.apply {
            when {
                isProviderEnabled("fused") -> location = getLastKnownLocation("fused")
                isProviderEnabled("gps") -> location = getLastKnownLocation("gps")
                isProviderEnabled("network") -> location = getLastKnownLocation("network")
            }
        }

        location?.let {
            latitude = location!!.latitude
            longitude = location!!.longitude
        }
        Toast.makeText(this@MainActivity, "$latitude, $longitude", Toast.LENGTH_SHORT).show()

    }

퍼미션을 체크해주고, 해당하는 provider로 대응하기위해 분기문으로 나누어 작업한다.(gps겠지만...)
받아온 location 값이 null이 아니라면 전역변수에 있는 위도/경도 변수에 대입해주고 토스트를 띄운다 🍞


4. 받아온 경도 값 이용하여 현재 시각 가져오기

private fun findTime() {
        location?.let {
            latitude = location!!.latitude
            longitude = location!!.longitude
        }
        val timeZone = getTimeZone(latitude, longitude)
        val currentTime = getCurrentTime(timeZone)
        Toast.makeText(this@MainActivity, currentTime, Toast.LENGTH_SHORT).show()
}

전역변수에 넣어둔 값을 가져와서 다음 메소드를 이용해 값을 찾아오면 된다.

private fun getTimeZone(latitude: Double, longitude: Double): TimeZone {
        return TimeZone.getTimeZone(
            TimeZone.getAvailableIDs((longitude * 10000).toInt()).firstOrNull { it.contains('/') }
                ?: TimeZone.getDefault().id)
}
private fun getCurrentTime(timeZone: TimeZone): String {
        val calendar: Calendar = Calendar.getInstance(timeZone)
        val hour: Int = calendar.get(Calendar.HOUR_OF_DAY)
        val minute: Int = calendar.get(Calendar.MINUTE)
        val second: Int = calendar.get(Calendar.SECOND)
        return String.format("%02d:%02d:%02d", hour, minute, second)
}

위도는 날씨, 경도는 시간이라고 배웠으니...
경도값을 기준으로 TimeZone을 리턴받고 여기서 리턴받은 TimeZone 객체를 이용하여 Calendar 객체에게 시/분/초 값을 원하는 포맷으로 받아온다. 끝!

0개의 댓글