-
Android Fused LocationAndroid/LBS 2019. 7. 26. 17:56
유저 디바이스의 위치를 획득하기 위해서는 API는 표준 라이브러리에 있는 LocationManager를 이용하여 LocationProvider 지정을 통해 getLastKnownLocation 함수를 이용해서 위치 획득이 가능하다.
하지만 LocationProvider를 지정하는 부분이 실제 작업 시 여러 가지를 고려하다 보니 개발자 코드 양이 비대해진다.
이런 작업을 쉽게 하기 위해 Google Play Service에서 제공하는 Fused Location을 사용하면 된다.
Fused Location의 목적은
- Reduce Power ( 저전력 )
- Improve accuracy ( 정확도 향상 )
- Simplify the APIs ( API 간소화 )
- Expose cool new features ( 새로운 기능 )
- and make it available on most Android devices ( Android 기기의 범용화 )
휴대폰에서 활용되는 기존 Location Provider의 종류와 각 Provider의 특징을 살펴보자면 ( 숫자가 높을수록 나쁨 )
GPS WIFI CELL SENSORS 배터리 소모율 3 2 1 2 정확성 1 2 3 2 범위 3 2 1 1
Gradle Dependency
implementation 'com.google.android.gms:play-services-location:17.0.0'
1. 필수 인터페이스 상속받기
GoogleApiClient.ConnectionCallbacks : 위치 정보 제공자가 사용여부에 따른 인터페이스
GoogleApiClient.OnConnectionFailedListener : 위치 정보 제공자 흭득 실패 인터페이스class MainActivity : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { @RequiresApi(Build.VERSION_CODES.P) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) TedPermission.with(this) .setPermissionListener(permissionListener) .setRationaleConfirmText("권한 필요") .setDeniedMessage("권한 거절") .setPermissions(Manifest.permission.ACCESS_FINE_LOCATION) .check() } /** * 위치 정보 제공자가 사용 가능 상태가 되었을때 호출 */ override fun onConnected(bundle: Bundle?) { } /** * 함수와 사용 불가능 상태가 되었을 때 호출 */ override fun onConnectionSuspended(p0: Int) { } /** * 위치 정보 제공자를 얻지 못할때 호출 */ override fun onConnectionFailed(p0: ConnectionResult) { } private val permissionListener = object : PermissionListener { override fun onPermissionGranted() { Toast.makeText(this@MainActivity, "권한 허가", Toast.LENGTH_SHORT).show() } override fun onPermissionDenied(deniedPermissions: ArrayList<String>?) { Toast.makeText(this@MainActivity, "권한 거부", Toast.LENGTH_SHORT).show() } } }
2. 필요 객체 생성
class MainActivity : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { lateinit var providerClient: FusedLocationProviderClient lateinit var googleApiClient: GoogleApiClient @RequiresApi(Build.VERSION_CODES.P) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) TedPermission.with(this) .setPermissionListener(permissionListener) .setRationaleConfirmText("권한 필요") .setDeniedMessage("권한 거절") .setPermissions(Manifest.permission.ACCESS_FINE_LOCATION) .check() googleApiClient = GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build() providerClient = LocationServices.getFusedLocationProviderClient(this) googleApiClient.connect() } /** * 위치 정보 제공자가 사용 가능 상태가 되었을때 호출 */ override fun onConnected(bundle: Bundle?) { } /** * 함수와 사용 불가능 상태가 되었을 때 호출 */ override fun onConnectionSuspended(p0: Int) { } /** * 위치 정보 제공자를 얻지 못할때 호출 */ override fun onConnectionFailed(p0: ConnectionResult) { } private val permissionListener = object : PermissionListener { override fun onPermissionGranted() { Toast.makeText(this@MainActivity, "권한 허가", Toast.LENGTH_SHORT).show() } override fun onPermissionDenied(deniedPermissions: ArrayList<String>?) { Toast.makeText(this@MainActivity, "권한 거부", Toast.LENGTH_SHORT).show() } } }
3. 필요 정보 추출
/** * 위치 정보 제공자가 사용 가능 상태가 되었을때 호출 */ override fun onConnected(bundle: Bundle?) { providerClient.lastLocation.addOnSuccessListener { it?.let { "위도 : ${it.latitude} 경도 : ${it.longitude}".log() } } }
4. 결과
위도 : 37.5602866 경도 : 126.9728302
실제 앞서 소개한 LocationManager와 비교 하였을때, 실제 프로젝트에서 사용해본적은 없어 차이는 느끼지 못하지만 좀더 인터페이스의 함수들이 명확하다고 해야하나? 애매한느낌은 없어진거 같다는 생각이 든다.
위의 코드상으로는 최초 1회만 좌표를 불러오지만 지속적으로 위치 획득하기 위해서는 LocationListener와 LocationRequest 필요하다
5. 지속적인 좌표값 얻어오기
val listener = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult?) { locationResult?.let { "위도 : ${it.lastLocation.latitude} 경도 : ${it.lastLocation.longitude}".log() } } } /** * 위치 정보 제공자가 사용 가능 상태가 되었을때 호출 */ override fun onConnected(bundle: Bundle?) { val locationRequest = LocationRequest.create() locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY locationRequest.interval = 3000 providerClient.requestLocationUpdates(locationRequest, listener, null) }
기존에는 LocationServices.FusedLocationApi 방식으로 가져와 사용하였지만 deprecated가 되어서 위와 같은 방법으로 처리한다.
6. 결과
D: 위도 : 37.5602895 경도 : 126.9728369 D: 위도 : 37.5603001 경도 : 126.9728374 D: 위도 : 37.5602958 경도 : 126.972811
'Android > LBS' 카테고리의 다른 글
Marker로 지도에 표시를 해보자 (0) 2019.07.29 Geocoder 도분초를 주소로, 주소를 도분초로! (0) 2019.07.29 Android Google Map 등록하기 ( API Key ) (0) 2019.07.29 Android Google Map 구현하기 (0) 2019.07.26 Android Location Manager (0) 2019.07.26