이번 강좌에서는 코틀린을 이용하여 안드로이드 앱에서 사용자의 위치를 얻는 방법을 자세히 알아보겠습니다. GPS와 기술을 활용한 위치 추적은 현대 모바일 앱에서 매우 중요한 기능입니다. 사용자 위치 정보를 활용하여 보다 개인화된 서비스를 제공할 수 있습니다.
1. 안드로이드 위치 서비스 개요
안드로이드에서는 위치 정보를 수집하기 위해 Google Play 서비스의 FusedLocationProviderClient
를 사용합니다. 이 API는 위치 요청을 보다 효율적으로 처리하며, GPS, Wi-Fi 및 셀룰러 네트워크를 활용해 사용자의 위치를 신속하게 결정합니다.
2. 프로젝트 설정
직접적인 코드를 작성하기 전에 필요한 라이브러리를 프로젝트에 추가해야 합니다. 아래 단계를 따라주세요.
2.1. Gradle 의존성 추가
확인할 사항은 프로젝트의 build.gradle
파일입니다. 먼저 다음 의존성을 추가해야 합니다:
implementation 'com.google.android.gms:play-services-location:21.0.1'
2.2. 권한 설정
위치 정보를 얻기 위해서는 앱에서 위치 권한을 요청해야 합니다. AndroidManifest.xml 파일에 다음 권한을 추가합니다:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
3. 사용자 위치 얻기
이제 위치를 요청하는 코드를 작성하겠습니다. 이를 위해 FusedLocationProviderClient
인스턴스를 생성하고, 위치 요청을 설정합니다.
3.1. FusedLocationProviderClient 설정
다음 코드는 MainActivity.kt
파일에서 사용자의 위치를 요청하는 과정을 보여줍니다:
import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.tasks.OnSuccessListener
class MainActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
getLastLocation()
}
private fun getLastLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
return
}
fusedLocationClient.lastLocation.addOnSuccessListener(this, OnSuccessListener { location ->
if (location != null) {
Toast.makeText(this, "위도: ${location.latitude}, 경도: ${location.longitude}", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(this, "위치를 가져올 수 없습니다.", Toast.LENGTH_LONG).show()
}
})
}
}
3.2. 권한 요청 처리
위치 권한 요청을 처리하기 위해 onRequestPermissionsResult
메소드를 추가합니다:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1000) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation()
} else {
Toast.makeText(this, "위치 권한이 거부되었습니다.", Toast.LENGTH_LONG).show()
}
}
}
4. 실시간 위치 업데이트
이제 사용자의 위치를 실시간으로 업데이트하는 방법을 살펴보겠습니다. 이를 위해 LocationRequest
객체를 사용하여 위치 요청을 설정합니다.
4.1. LocationRequest 설정
아래 코드를 통해 실시간 위치 업데이트를 요청할 수 있습니다:
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
createLocationRequest()
createLocationCallback()
}
private fun createLocationRequest() {
locationRequest = LocationRequest.create().apply {
interval = 10000 // 위치 업데이트 주기 (10초)
fastestInterval = 5000 // 가장 빠른 업데이트 주기 (5초)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
}
private fun createLocationCallback() {
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: com.google.android.gms.location.LocationResult?) {
locationResult ?: return
for (location in locationResult.locations) {
Toast.makeText(this@MainActivity, "현재 위치: ${location.latitude}, ${location.longitude}", Toast.LENGTH_LONG).show()
}
}
}
}
4.2. 위치 업데이트 요청
위치 요청은 다음 메소드를 통해 시작할 수 있습니다:
private fun startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
4.3. 위치 업데이트 정지
위치 업데이트가 더 이상 필요하지 않은 경우 아래 메소드로 업데이트를 중지할 수 있습니다:
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
5. 통합 코드
지금까지 작성한 코드를 통합하여 최종 코드 예제를 제공하겠습니다:
import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.location.*
class MainActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
createLocationRequest()
createLocationCallback()
getLastLocation()
}
private fun createLocationRequest() {
locationRequest = LocationRequest.create().apply {
interval = 10000 // 10초
fastestInterval = 5000 // 5초
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
}
private fun createLocationCallback() {
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
for (location in locationResult.locations) {
Toast.makeText(this@MainActivity, "현재 위치: ${location.latitude}, ${location.longitude}", Toast.LENGTH_LONG).show()
}
}
}
}
private fun getLastLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
return
}
fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
if (location != null) {
Toast.makeText(this, "위도: ${location.latitude}, 경도: ${location.longitude}", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(this, "위치를 가져올 수 없습니다.", Toast.LENGTH_LONG).show()
}
}
}
private fun startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1000)
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1000) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation()
} else {
Toast.makeText(this, "위치 권한이 거부되었습니다.", Toast.LENGTH_LONG).show()
}
}
}
}
6. 결론
이번 강좌에서는 코틀린을 사용하여 안드로이드에서 사용자 위치를 얻는 방법에 대해 배웠습니다. GPS 및 위치 서비스 API를 활용하여 개인화된 서비스를 제공하는 방법을 알아보았습니다. 이 기초를 통해 여러분은 보다 복잡한 위치 기반 서비스로 나아갈 수 있습니다.
7. 다음 단계
다음 단계로는 위치를 지도에 표시하거나, 특정 위치에 대한 반경 탐색을 구현해 볼 수 있습니다. 이를 통해 더욱 풍부한 사용자 경험을 제공할 수 있습니다.