다음을 통해 공유


Android의 위치 서비스

이 가이드에서는 Android 애플리케이션의 위치 인식 기능을 소개하고, Android Location Service API를 사용하여 사용자의 위치를 가져오는 방법과 Google Location Services API에서 사용할 수 있는 융합 위치 공급자를 보여줍니다.

Android 공급자는 셀 타워 위치, Wi-Fi, GPS 등의 다양한 위치 기술을 사용합니다. 각 위치 기술에 대한 자세한 내용이 위치 공급자를 통해 추상화되므로 애플리케이션에서는 사용하는 공급자에 관계없이 동일한 방법으로 위치 정보를 가져올 수 있습니다. 이 가이드에서는 사용 가능한 공급자와 디바이스가 사용되는 방식에 따라 디바이스 위치 정보를 가져오는 가장 좋은 방법을 지능적으로 결정하는 Google Play 서비스의 일부인 융합 위치 공급자를 소개합니다. Android Location Service API는 LocationManager를 사용하여 시스템 위치 서비스와 통신하는 방법을 보여줍니다. 이 가이드의 두 번째 파트에서는 LocationManager를 사용하여 Android Location Services API를 살펴봅니다.

일반적으로 경험에 비추어볼 때, 애플리케이션에서 융합 위치 공급자를 사용하고, 꼭 필요한 경우에만 이전 Android Location Service API API를 사용하는 것이 좋습니다.

위치 기본 사항

Android에서는 위치 데이터에 사용할 API로 무엇을 선택하든, 여러 개념이 동일하게 유지됩니다. 이 섹션에서는 위치 공급자 및 위치 관련 권한을 소개합니다.

위치 공급자

사용자의 위치를 정확하게 파악하기 위해 내부적으로 여러 기술이 사용됩니다. 사용되는 하드웨어는 데이터 수집 작업을 위해 선택하는 위치 공급자 유형에 따라 달라집니다. Android는 다음 세 가지 위치 공급자를 사용합니다.

  • GPS 공급자 – GPS는 가장 정확한 위치를 제공하고, 가장 강력한 기능을 사용하며, 야외에서 가장 잘 작동합니다. 이 공급자는 GPS과 보조 GPS(aGPS)의 조합을 사용하며, 셀룰러 타워에서 수집한 GPS 데이터를 반환합니다.

  • 네트워크 공급자 – 셀 타워에서 수집한 aGPS 데이터를 포함하여 WiFi 및 셀룰러 데이터의 조합을 제공합니다. GPS 공급자보다 전력 소모가 적지만, 반환하는 위치 데이터의 정확도가 일정하지 않습니다.

  • 수동 공급자 – 애플리케이션에서 위치 데이터를 생성하기 위해 다른 애플리케이션 또는 서비스에서 요청한 공급자를 사용하는 "piggyback" 옵션입니다. 안정적이지는 않지만 전력 소모가 적어 위치 업데이트를 지속적으로 할 필요가 없는 애플리케이션에 이상적입니다.

위치 공급자를 항상 사용할 수 있는 것은 아닙니다. 예를 들어 애플리케이션에 GPS를 사용하고 싶지만, 설정에서 GPS가 꺼져 있거나 디바이스에 GPS가 아예 없는 경우도 있습니다. 특정 공급자를 사용할 수 없는 경우 해당 공급자를 선택하면 null이 반환될 수 있습니다.

위치 권한

위치 인식 애플리케이션은 GPS, Wi-Fi 및 셀룰러 데이터를 수신하기 위해 디바이스의 하드웨어 센서에 액세스해야 합니다. 액세스는 애플리케이션의 Android 매니페스트에서 적절한 권한을 통해 제어됩니다. 사용 가능한 두 가지 권한이 있습니다. 애플리케이션의 요구 사항 및 선택한 API에 따라 다음을 허용하려고 합니다.

  • ACCESS_FINE_LOCATION – 애플리케이션이 GPS에 액세스할 수 있도록 허용합니다. GPS 공급자수동 공급자 옵션에 필요합니다(수동 공급자는 다른 애플리케이션 또는 서비스에서 수집한 GPS 데이터에 액세스할 수 있는 권한이 필요함). 네트워크 공급자의 선택적 권한입니다.

  • ACCESS_COARSE_LOCATION – 셀룰러 및 Wi-Fi 위치에 대한 애플리케이션 액세스를 허용합니다. ACCESS_FINE_LOCATION를 설정하지 않은 경우 네트워크 공급자에 필요합니다.

API 버전 21(Android 5.0 롤리팝) 이상을 대상으로 하는 앱의 경우 ACCESS_FINE_LOCATION을 사용하도록 설정하고 GPS 하드웨어가 없는 디바이스에서 계속 실행할 수 있습니다. 앱에 GPS 하드웨어가 필요한 경우 Android 매니페스트에 요소를 명시적으로 추가 android.hardware.location.gpsuses-feature 해야 합니다. 자세한 내용은 Android uses-feature 요소 참조를 확인하세요.

권한을 설정하려면 Solution Pad에서 Properties 폴더를 확장하고 AndroidManifest.xml 파일을 두 번 클릭합니다. 필요한 권한에 권한이 나열됩니다.

Android 매니페스트 필요한 권한 설정의 스크린샷

이러한 두 권한 중 하나를 설정하면 애플리케이션에서 위치 공급자에 액세스하려면 사용자의 권한이 필요하다는 것을 Android에 알리게 됩니다. API 레벨 22(Android 5.1) 이하를 실행하는 디바이스는 앱이 설치될 때마다 사용자에게 이러한 권한을 부여해 달라고 요청합니다. API 레벨 23(Android 6.0) 이상을 실행하는 디바이스에서는 앱이 위치 공급자를 요청하기 전에 런타임 권한 검사를 수행해야 합니다.

참고 항목

참고: 설정 ACCESS_FINE_LOCATION 은 거친 위치 데이터와 미세한 위치 데이터에 대한 액세스를 의미합니다. 두 권한을 모두 설정하면 안 되고, 앱이 작동하는 데 필요한 최소 권한만 설정해야 합니다.

이 코드 조각은 앱에 ACCESS_FINE_LOCATION 권한이 있는지 확인하는 방법의 예입니다.

 if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == Permission.Granted)
{
    StartRequestingLocationUpdates();
    isRequestingLocationUpdates = true;
}
else
{
    // The app does not have permission ACCESS_FINE_LOCATION 
}

앱은 사용자가 권한을 부여하지 않아도(또는 권한을 취소해도) 상황을 정상적으로 처리할 수 있는 시나리오를 허용해야 합니다. Xamarin.Android에서 런타임 권한 검사를 구현하는 방법에 대한 자세한 내용은 권한 가이드를 참조하세요.

융합 위치 공급자 사용

융합 위치 공급자는 Android 애플리케이션에서 디바이스의 위치 업데이트를 수신할 때 선호하는 방법입니다. 런타임 중에 위치 공급자를 효율적으로 선택하여 배터리 효율적인 방식으로 최적의 위치 정보를 제공하기 때문입니다. 예를 들어 야외에서 활동하는 사용자는 GPS를 사용하여 가장 정확한 위치 정보를 얻습니다. 이 사용자가 실내로 들어와서 GPS가 제대로(또는 전혀) 작동하지 않는 경우 융합 위치 공급자는 자동으로 실내에서 잘 작동하는 WiFi로 전환할 수 있습니다.

융합 위치 공급자 API는 지오펜싱 및 작업 모니터링을 포함하여 위치 인식 애플리케이션의 성능을 강화하는 다양한 기타 도구를 제공합니다. 이 섹션에서는 LocationClient를 설정하고, 공급자를 설정하고, 사용자의 위치를 가져오기 위한 기본 사항을 집중적으로 살펴보겠습니다.

융합 위치 공급자는 Google Play 서비스의 일부입니다. 융합 위치 공급자 API가 작동하려면 애플리케이션에 Google Play 서비스 패키지를 설치하고 올바르게 구성해야 하며, 디바이스에 Google Play 서비스 APK가 설치되어 있어야 합니다.

Xamarin.Android 애플리케이션에서 융합 위치 공급자를 사용하려면 먼저 Xamarin.GooglePlayServices.Location 패키지를 프로젝트에 추가해야 합니다. 또한 아래에 설명된 클래스를 참조하는 원본 파일에 다음 using 문을 추가해야 합니다.

using Android.Gms.Common;
using Android.Gms.Location;

Google Play 서비스가 설치되었는지 확인

Google Play 서비스가 설치되지 않았거나 만료된 상태에서 Xamarin.Android가 융합 위치 공급자를 사용하려고 시도하면 충돌이 발생한 후 런타임 예외가 발생합니다. Google Play 서비스가 설치되지 않은 경우 애플리케이션에서는 위에서 설명한 Android 위치 서비스를 대신 사용해야 합니다. Google Play 서비스가 만료된 경우 앱에서 사용자에게 설치된 Google Play 서비스 버전을 업데이트하라는 메시지를 표시할 수 있습니다.

이 코드 조각은 Android 작업에서 프로그래밍 방식으로 Google Play 서비스의 설치 여부를 확인 수 있는 방법의 예입니다.

bool IsGooglePlayServicesInstalled()
{
    var queryResult = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
    if (queryResult == ConnectionResult.Success)
    {
        Log.Info("MainActivity", "Google Play Services is installed on this device.");
        return true;
    }

    if (GoogleApiAvailability.Instance.IsUserResolvableError(queryResult))
    {
        // Check if there is a way the user can resolve the issue
        var errorString = GoogleApiAvailability.Instance.GetErrorString(queryResult);
        Log.Error("MainActivity", "There is a problem with Google Play Services on this device: {0} - {1}",
                  queryResult, errorString);

        // Alternately, display the error to the user.
    }

    return false;
}

FusedLocationProviderClient

융합 위치 공급자와 상호 작용하려면 Xamarin.Android 애플리케이션에 FusedLocationProviderClient 인스턴스가 있어야 합니다. 이 클래스는 위치 업데이트를 구독하고 디바이스의 마지막으로 알려진 위치를 검색하는 데 필요한 메서드를 노출합니다.

작업의 OnCreate 메서드는 다음 코드 조각에서 보여드리는 것처럼 FusedLocationProviderClient에 대한 참조를 가져오기에 적합한 위치입니다.

public class MainActivity: AppCompatActivity
{
    FusedLocationProviderClient fusedLocationProviderClient;

    protected override void OnCreate(Bundle bundle) 
    {
        fusedLocationProviderClient = LocationServices.GetFusedLocationProviderClient(this);
    }
}

마지막으로 알려진 위치 가져오기

FusedLocationProviderClient.GetLastLocationAsync() 메서드는 Xamarin.Android 애플리케이션에서 최소한의 코딩 오버헤드로 디바이스의 마지막으로 알려진 위치를 신속하게 가져올 수 있는 간단한 비차단식 방법을 제공합니다.

이 코드 조각에서는 GetLastLocationAsync 메서드를 사용하여 디바이스의 위치를 검색하는 방법을 보여줍니다.

async Task GetLastLocationFromDevice()
{
    // This method assumes that the necessary run-time permission checks have succeeded.
    getLastLocationButton.SetText(Resource.String.getting_last_location);
    Android.Locations.Location location = await fusedLocationProviderClient.GetLastLocationAsync();

    if (location == null)
    {
        // Seldom happens, but should code that handles this scenario
    }
    else
    {
        // Do something with the location 
        Log.Debug("Sample", "The latitude is " + location.Latitude);
    }
}

위치 업데이트 구독

Xamarin.Android 애플리케이션은 다음 코드 조각과 같이 메서드를 사용하여 FusedLocationProviderClient.RequestLocationUpdatesAsync 융합된 위치 공급자의 위치 업데이트를 구독할 수도 있습니다.

await fusedLocationProviderClient.RequestLocationUpdatesAsync(locationRequest, locationCallback);

이 메서드는 다음 두 매개 변수를 사용합니다.

  • Android.Gms.Location.LocationRequestLocationRequest– 개체는 Xamarin.Android 애플리케이션이 융합된 위치 공급자의 작동 방식에 대한 매개 변수를 전달하는 방법입니다. LocationRequest는 요청 빈도 또는 정확한 위치 업데이트의 중요도와 같은 정보를 포함합니다. 예를 들어 중요한 위치 요청은 디바이스에서 GPS를 사용하게 만들고, 따라서 위치를 결정할 때 더 많은 전력을 사용하게 됩니다. 이 코드 조각은 정확도가 높은 위치의 LocationRequest를 만들고, 약 5분마다(하지만 요청 사이의 시간은 2분 이상) 위치 업데이트를 확인하는 방법을 보여줍니다. 융합 위치 공급자는 디바이스 위치를 확인하려고 할 때 사용할 위치 공급자에 대한 지침으로 LocationRequest를 사용합니다.

    LocationRequest locationRequest = new LocationRequest()
                                      .SetPriority(LocationRequest.PriorityHighAccuracy)
                                      .SetInterval(60 * 1000 * 5)
                                      .SetFastestInterval(60 * 1000 * 2);
    
  • Android.Gms.Location.LocationCallback – 위치 업데이트를 받으려면 Xamarin.Android 애플리케이션이 추상 클래스를 LocationProvider 서브클래스해야 합니다. 이 클래스는 융합 위치 공급자가 위치 정보를 사용하여 앱을 업데이트하기 위해 호출할 수 있는 두 개의 메서드를 노출했습니다. 이 내용은 아래에서 자세히 설명합니다.

Xamarin.Android 애플리케이션에 위치 업데이트를 알리기 위해 융합 위치 공급자는 LocationCallBack.OnLocationResult(LocationResult result)를 호출합니다. Android.Gms.Location.LocationResult 매개 변수에는 업데이트 위치 정보가 포함됩니다.

융합 위치 공급자는 위치 데이터의 가용성 변화를 감지하면 LocationProvider.OnLocationAvailability(LocationAvailability locationAvailability) 메서드를 호출합니다. LocationAvailability.IsLocationAvailable 속성이 true를 반환하면 OnLocationResult에서 보고한 디바이스 위치 결과가 정확하고 LocationRequest에서 요구하는 최신 상태인 것으로 간주할 수 있습니다. IsLocationAvailable이 false이면 OnLocationResult에서 위치 결과를 반환하지 않습니다.

이 코드 조각은 LocationCallback 개체의 구현 샘플입니다.

public class FusedLocationProviderCallback : LocationCallback
{
    readonly MainActivity activity;

    public FusedLocationProviderCallback(MainActivity activity)
    {
        this.activity = activity;
    }

    public override void OnLocationAvailability(LocationAvailability locationAvailability)
    {
        Log.Debug("FusedLocationProviderSample", "IsLocationAvailable: {0}",locationAvailability.IsLocationAvailable);
    }

    public override void OnLocationResult(LocationResult result)
    {
        if (result.Locations.Any())
        {
            var location = result.Locations.First();
            Log.Debug("Sample", "The latitude is :" + location.Latitude);
        }
        else
        {
            // No locations to work with.
        }
    }
}

Android Location Service API 사용

Android Location Service는 Android에서 위치 정보를 사용하기 위한 용도의 이전 API입니다. 위치 데이터는 하드웨어 센서와 시스템 서비스를 통해 수집되고, 이후에 애플리케이션에서LocationManager 클래스 및 ILocationListener에 의해 액세스됩니다.

위치 서비스는 Google Play 서비스가 설치되지 않은 디바이스에서 실행해야 하는 애플리케이션에 가장 적합합니다.

위치 서비스는 시스템에서 관리하는 특별한 유형의 서비스입니다. 시스템 서비스는 디바이스 하드웨어와 상호 작용하며 항상 실행됩니다. 애플리케이션에서 위치 업데이트를 사용하기 위해 LocationManagerRequestLocationUpdates 호출을 사용하여 시스템 위치 서비스에서 위치 업데이트를 구독하겠습니다.

Android Location Service를 사용하여 사용자의 위치를 얻으려면 다음과 같은 여러 단계를 수행해야 합니다.

  1. LocationManager 서비스의 참조를 가져옵니다.
  2. ILocationListener 인터페이스를 구현하고 위치가 변경될 때 이벤트를 처리합니다.
  3. LocationManager를 사용하여 지정된 공급자의 위치 업데이트를 요청합니다. 이전 단계의 ILocationListenerLocationManager에서 콜백을 수신하는 데 사용됩니다.
  4. 애플리케이션이 업데이트를 수신하는 데 더 이상 적절하지 않은 경우 위치 업데이트를 중지합니다.

위치 관리자

LocationManager 클래스의 인스턴스를 사용하여 시스템 위치 서비스에 액세스할 수 있습니다. LocationManager는 시스템 위치 서비스와 상호 작용하고 시스템 위치 서비스에서 메서드를 호출할 수 있는 특수 클래스입니다. 애플리케이션에서 아래와 같이 GetSystemService를 호출하고 서비스 유형을 전달하여 LocationManager의 참조를 가져올 수 있습니다.

LocationManager locationManager = (LocationManager) GetSystemService(Context.LocationService);

OnCreateLocationManager의 참조를 가져올 수 있는 좋은 장소입니다. 작업 수명 주기의 다양한 지점에서 호출할 수 있도록 LocationManager를 클래스 변수로 유지하는 것이 좋습니다.

LocationManager에 위치 업데이트 요청

애플리케이션에서 LocationManager의 참조를 가져온 후에는 필요한 위치 정보 유형과 해당 정보의 업데이트 빈도를 LocationManager에 알려야 합니다. 이렇게 하려면 LocationManager 개체에서 RequestLocationUpdates를 호출하고, 업데이트의 몇 가지 조건과 위치 업데이트를 수신할 콜백을 전달합니다. 이 콜백은 ILocationListener 인터페이스를 구현해야 하는 형식입니다(이 가이드의 뒷부분에서 자세히 설명).

RequestLocationUpdates 메서드는 애플리케이션에서 위치 업데이트 수신을 시작하려 한다는 것을 시스템 위치 서비스에 알립니다. 이 메서드를 사용하면 공급자를 지정하고, 시간 및 거리 임계값을 지정하여 업데이트 빈도를 제어할 수 있습니다. 예를 들어 아래 메서드는 2000밀리초마다(단, 위치가 1미터 이상으로 변하는 경우에만) GPS 위치 공급자에게 위치 업데이트를 요청합니다.

// For this example, this method is part of a class that implements ILocationListener, described below
locationManager.RequestLocationUpdates(LocationManager.GpsProvider, 2000, 1, this);

애플리케이션의 원활한 작동에 필요한 만큼만 위치 업데이트를 요청해야 합니다. 이렇게 하면 배터리 수명이 유지되고 사용자에게 보다 나은 환경이 제공됩니다.

LocationManager의 위치 업데이트에 응답

애플리케이션에서 LocationManager의 업데이트를 요청한 후에는 ILocationListener 인터페이스를 구현하여 서비스로부터 정보를 받을 수 있습니다. 이 인터페이스는 위치 서비스 및 위치 공급자를 수신 대기하는 네 가지 메서드 OnLocationChanged를 제공합니다. 위치 업데이트를 요청할 때 설정된 조건에 따라 위치 변경으로 간주하기에 충분할 정도로 사용자의 위치가 변경되면 시스템에서 OnLocationChanged를 호출합니다.

다음 코드는 인터페이스의 메서드를 보여 줍니다 ILocationListener .

public class MainActivity : AppCompatActivity, ILocationListener
{
    TextView latitude;
    TextView longitude;
    
    public void OnLocationChanged (Location location)
    {
        // called when the location has been updated.
    }
    
    public OnProviderDisabled(string locationProvider)
    {
        // called when the user disables the provider
    }
    
    public OnProviderEnabled(string locationProvider)
    {
        // called when the user enables the provider
    }
    
    public OnStatusChanged(string locationProvider, Availability status, Bundle extras)
    {
        // called when the status of the provider changes (there are a variety of reasons for this)
    }
}

LocationManager 업데이트 구독 취소

시스템 리소스를 절약하려면 애플리케이션에서 가능하면 빨리 위치 업데이트를 구독 취소해야 합니다. RemoveUpdates 메서드는 애플리케이션에 업데이트 전송을 중지하라고 LocationManager에 알립니다. 예를 들어 활동이 화면에 없는 동안 애플리케이션에 OnPause 위치 업데이트가 필요하지 않은 경우 전원을 절약할 수 있도록 메서드에서 활동을 호출 RemoveUpdates 할 수 있습니다.

protected override void OnPause ()
{
    base.OnPause ();
    locationManager.RemoveUpdates (this);
}

애플리케이션이 백그라운드에 있는 동안 위치 업데이트를 가져와야 하는 경우 시스템 위치 서비스를 구독하는 사용자 지정 서비스를 만들면 됩니다. 자세한 내용은 Android 서비스에서 백그라운딩 가이드를 참조하세요.

LocationManager에 가장 적합한 위치 공급자 결정

위의 애플리케이션은 GPS를 위치 공급자로 설정합니다. 그러나 디바이스가 실내에 있거나 GPS 수신기가 없는 경우처럼 GPS를 사용할 수 없는 경우가 있습니다. 이 경우 공급자가 null을 반환합니다.

GPS를 사용할 수 없을 때 앱이 작동할 수 있도록, 애플리케이션을 시작할 때 GetBestProvider 메서드를 사용하여 최적의(디바이스 지원 및 사용자 지원) 위치 공급자를 요청합니다. 특정 공급자를 전달하는 대신, Criteria 개체를 사용하여 정확도, 전력 등의 공급자 요구 사항을 GetBestProvider에게 알려줄 수 있습니다. GetBestProvider는 지정된 조건에 가장 적합한 공급자를 반환합니다.

다음 코드는 최적의 공급자를 가져와서 위치 업데이트를 요청할 때 사용하는 방법을 보여줍니다.

Criteria locationCriteria = new Criteria();   
locationCriteria.Accuracy = Accuracy.Coarse;
locationCriteria.PowerRequirement = Power.Medium;

locationProvider = locationManager.GetBestProvider(locationCriteria, true);

if(locationProvider != null)
{
    locationManager.RequestLocationUpdates (locationProvider, 2000, 1, this);
}
else
{
    Log.Info(tag, "No location providers available");
}

참고 항목

사용자가 모든 위치 공급자를 사용하지 않도록 설정하면 GetBestProvidernull을 반환합니다. 이 코드가 실제 디바이스에서 작동하는 방식을 확인하려면 다음 스크린샷과 같이 Google 설정 > 위치 > 모드에서 GPS, Wi-Fi 및 셀룰러 네트워크를 사용하도록 설정해야 합니다.

Android 휴대폰의 위치 모드 설정 화면

아래 스크린샷은 GetBestProvider를 사용하여 실행되는 위치 애플리케이션을 보여줍니다.

위도, 경도 및 공급자를 표시하는 GetBestProvider 앱

GetBestProvider는 공급자를 동적으로 변경하지 않습니다. 그 대신 작업 수명 주기 중에 사용 가능한 최적의 공급자를 결정합니다. 공급자가 설정된 후 상태 변경되는 경우 애플리케이션은 공급자 스위치와 관련된 모든 가능성을 처리하기 위해 메서드OnProviderEnabledOnProviderDisabled에 추가 코드ILocationListener(및 OnStatusChanged )가 필요합니다.

요약

이 가이드에서는 Google Location Services API의 Android 위치 서비스와 융합 위치 공급자를 모두 사용하여 사용자의 위치를 가져오는 방법을 설명했습니다.