안드로이드 19) GeoLocation

밍나·2022년 1월 28일
1

Android

목록 보기
19/36

Concepts of GeoLocation

1. GeoLocation

  • 유저의 위치를 이용한 서비스
  • 퍼미션 종류
    • android.permission.ACCESS_COARSE_LOCATION : WiFi 또는 모바일 데이터(또는 둘 다)를 사용하여 기기의 위치 획득, 정확도는 도시 블록 1개 정도의 오차 수준
    • android.permission.ACCESS_FINE_LOCATION : 위성, WiFi 및 모바일 데이터 등 이용 가능한 위치 제공자를 사용하여 최대한 정확하게 위치를 결정
    • android.permission.ACCESS_BACKGROUND_LOCATION : Android 10(API 수준 29) 이상에서 백그라운드 상태에서 위치 정보 액세스시 필요
  • 위치 제공자(Location Provider)
    • GPS : GPS 위성을 이용하여 위치 정보 획득(정확도 Good, 건물 내에서는 불가)
    • Network : 이동통신사 망 정보를 이용하여 위치 정보 획득(오차범위는 GPS 보다 떨어지지만 건물 안에서 가능)
    • Wifi : 와이파이의 AP 정보를 이용하여 위치 정보 획득
    • Passive : 다른 앱에서 이용한 마지막 위치 정보 획득
  • 위치 정보 값
    • 기본적으로 위/경도는 도/분/초로 표시되는데 일반적인 시스템에서는 실수로 사용
      • 37도 30분 30초 → 37.5··· (보통 소수점 6번째 자리까지만 사용)
    • 위도 : 90도 ~ 0도(적도) ~ -90도
    • 경도 : 180도 ~ 0도(그리니치 천문대) ~ -180도
  • 위치 정보 추적 방법
    • LocationManager : 사스템 서비스, 플랫폼에서 제공하는 API(표준 API)
    • Fused API : 구글에서 제공하는 API, 몇몇 프로그램을 보다 간단하게 만들 수 있음

LocationManager

1. GeoLocation
1) 플랫폼 API에서 제공되는 시스템 서비스

val manager = getSystemService(LOCATION_SERVICE) as LocationManager

2) 폰에 어떤 위치정보 제공자(Location Provider)가 있는지 파악

// allProviders로 핸드폰의 모든 위치정보 제공자 목록을 받아옴
val providers = manager.allProviders
for (provider in providers) {
    result += "$provider",
}
// getProviders(true)로 현재 이용 가능한 위치정보 제공자 목록을 받아옴
val enabledProviders = manager.getProviders(true)
for (provider in enabledProviders) {
    result += "$provider",
}

3) 위치 정보 획득은 LocationManager의 getLastKnownLocation() 함수를 이용

val location: Location? = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
  • getLastKnownLocation()의 매개변수에 Location Provider 지정
  • 결과값은 VO 객체인 Location 객체로, 정보가 들어가 있는 객체임
    • getAccuracy() : 정확도(m 단위)
    • getLatitude() : 위도(실수값)
    • getLongitude() : 경도(실수값)
    • getTime() : 획득 시간
      4) 지속적으로 위치를 획득해야 한다면 LocationListener를 이용
// LocationListener를 구현한 객체를 준비
val listener: LocationListener = object : LocationListener {
    // 위치값 전달 위해 반복 콜 되는 함수
    override fun onLocationChanged(location: Location) {
    	TODO("Not yet implemented")
    }
    // 프로바이더가 이용 불가능한 상황에 호출
    override fun onProviderDisabled(provider: String) {
    	super.onProviderDisabled(provider)
    }
    // 프로바이더가 다시 이용 가능한 상황에 호출
    override fun onProviderEnabled(provider: String) {
    	super.onProviderEnabled(provider)
    }
}

// LocationManager에게 아래 함수의 매개변수로 위의 리스너 객체를 전달
// 매개변수인 리스너에게 반복적으로 함수를 호출하면서 위치 값을 제공
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10_000L, 10f, listener)

// 더이상 위치 값이 필요하지 않은 경우
manager.removeUpdates(listner)

Fused API

1. Fused API

implementation 'com.google.android.gms:play-services:12.0.1'
  • 위치 정보를 획득할 때 여러가지 상황(전력 소모율, 정확도 향상, 간단한 APIs)과 관련된 코드의 복잡함을 줄이기 위해 구글에서 제공하는 API가 Fused Location Provider

2. Fused Location Provider
1) Fused Location Provider의 핵심 클래스

val connectionCallback = objedt: GoogleApiClient.ConnectionCallbacks {
    override fun onConnected(p0: Bundle?) {
    	// 위치 정보 제공자가 사용 가능 상황이 된 순간
        // 위치 정보 획득
    }
    override fun onConnectionSuspended(p0: Int) {
    	// 위치 정보 제공자가 어느 순간 사용 불가능 상황이 될때
    }
}

val onConnectionFailedCallback = object: GoogleApiClient.OnConnectionFailedListener {
    override fun onConnectionFailed(p0 : ConnectionResult) {
    	// 가용한 위치 제공자가 없는 경우
    }
}

val apiClient: GoogleApiClient = GoogleApiClient.Builder(this)
    .addApi(LocationServices.API)
    // 위에서 구현한 객체들을 함수에 등록하면 프로바이더의 이용 여부를 콜백함수로 호출
    .addConnectionCallbacks(connectionCallback)
    .addOnConnectionFailedListener(onConnectionFailedCallback)
    .build()
  • FusedLocationProviderClient : 위치 정보 획득
  • GoogleApiClient : 위치 정보 제공자 이용 준비, 다양한 콜백 제공
    • GoogleApiClient에는 GoogleApiClient.ConnectionsCallbacks와 GoogleApiClient.OnConnectionFailedListener 인터페이스를 구현한 객체를 지정
    • 이렇게 해서 어떤 Provider를 써야할지, Provider가 계속 이용 가능한지를 알 수 있음

2) GoogleApiClient 객체에 위치 제공자를 판단

apiClient.connect()

3) 위치 획득

providerClient.getLastLocation().addOnSuccessListener(
    this@FusedActivity,
    object: OnSuccessListener<Location> {
    	override fun onSuccess(location: Location?) {
        	val latitude = location?.latitude
            val longitude = location?.longitude
        }
    })
  • FusedLocationProviderClient의 getLastLocation() 함수를 이용해 위치 획득
  • 결과값은 addOnSuccessListener() 함수에 등록한 OnSuccessListener 구현 객체의 OnSuccess() 함수가 호출되며 전달

GoogleMap

1. AndroidManifest.xml 설정

implementation 'com.google.android.gms:play-services:12.0.1'
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
// 개발자 사이트에서 얻어낸 맵키를 등록
<meta-data android:name="com.google.android.maps.v2.API_KEY"
    android:value="~~~~"/>
<meta-data android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version"/>

2. 지도 layout 설정

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mapView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.SupportMapFragment" />

3. 지도 출력

override fun onCreate(savedInstanceState: Bundle?){
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    (supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment?)!!.getMapAsync(this)
}

override fun onMapReady(p0: GoogleMap?){
    googleMap=p0
}
  • GoogleMap 클래스가 지도를 출력
profile
🤗🤗🤗

0개의 댓글