Android : LocationManager 및 Google Play 서비스


151

사용자의 현재 위치를 얻는 데 중점을 둔 앱을 만들고 Google Places API 를 통해 자신과 가까운 관심 지점 (예 : 바, 레스토랑 등)을 찾고 싶습니다 .

웹을 시작할 장소를 검색 할 때 LocationManager수업 을 사용하는 일부 자습서 와 사용자 위치를 찾기 위해 Google Play 서비스 를 사용하는 일부 자습서를 보았습니다.

첫눈에 두 사람 모두 같은 일을하지만, 이것에 익숙하지 않아서 약간 혼란 스러웠으며 어떤 방법이 내 요구에 가장 적합한 지 알 수 없습니다. 그래서 나는 당신에게 묻고 싶습니다 :

위치를 찾는 두 가지 방법의 차이점은 무엇입니까?


답변:


320

Android의 사용자 위치

안드로이드에서 사용자의 위치를 ​​얻는 것은 iOS보다 덜 간단합니다. 혼란을 시작하기 위해 완전히 다른 두 가지 방법이 있습니다. 첫 번째는의 Android API를 사용 android.location.LocationListener하고 두 번째는 Google Play Services API를 사용하는 것 com.google.android.gms.location.LocationListener입니다. 두 가지를 모두 살펴 보자.

  1. 안드로이드의 위치 API

    Android의 위치 API는 세 가지 다른 제공 업체를 사용하여 위치를 얻습니다.

    • LocationManager.GPS_PROVIDER—이 공급자는 위성을 사용하여 위치를 결정합니다. 조건에 따라이 공급자는 위치 수정을 반환하는 데 시간이 걸릴 수 있습니다.
    • LocationManager.NETWORK_PROVIDER—이 공급자는 셀 타워 및 WiFi 액세스 포인트의 가용성에 따라 위치를 결정합니다. 결과는 네트워크 조회를 통해 검색됩니다.
    • LocationManager.PASSIVE_PROVIDER—이 제공자는 다른 제공자가 생성 한 위치를 반환합니다. 다른 응용 프로그램이나 서비스가 실제로 위치를 직접 요청하지 않고 요청하면 위치 업데이트를 수동으로받습니다.

요점은 LocationManager시스템에서 객체를 가져 와서 구현 LocationListener하고를 호출한다는 requestLocationUpdatesLocationManager입니다.

다음은 코드 스 니펫입니다.

    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

위치 전략에 대한 Google API 가이드코드를 꽤 잘 설명합니다. 그러나 대부분의 경우 Google 위치 서비스 API를 대신 사용하면 배터리 성능이 향상되고 정확성이 향상 됩니다. 이제 혼란이 시작됩니다!

  1. Google의 위치 서비스 API

Google의 위치 서비스 API는 Google Play 서비스 APK의 일부입니다 ( 설정 방법 ). 그것들은 Android API 위에 구축되었습니다. 이 API는 위에서 언급 한 공급자 대신 "퓨즈 위치 공급자"를 제공합니다. 이 공급자는 정확도, 배터리 사용량 등을 기준으로 사용할 기본 공급자를 자동으로 선택합니다. 시스템 전체 서비스에서 위치를 지속적으로 업데이트하여 업데이트하므로 속도가 빠릅니다. 지오 펜싱과 같은 고급 기능을 사용할 수 있습니다.

Google의 위치 서비스를 사용하려면 앱이에 연결되어 있어야합니다 GooglePlayServicesClient. 클라이언트에 연결하려면 활동 (또는 조각 등)을 구현 GooglePlayServicesClient.ConnectionCallbacks하고 GooglePlayServicesClient.OnConnectionFailedListener인터페이스 해야합니다 . 샘플 코드는 다음과 같습니다.

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        locationClient = new LocationClient(this, this, this);
    }

    @Override
    public void onConnected(Bundle bundle) {
    Location location = locationClient.getLastLocation() ;
        Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDisconnected() {
    Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // code to handle failed connection
        // this code can be found here — http://developer.android.com/training/location/retrieve-current.html 
    }
  • locationClient.getLastLocation()null입니까?

locationClient.getLastLocation()클라이언트에서 마지막으로 알려진 위치를 가져옵니다. 그러나 Fused Location Provider는 하나 이상의 클라이언트가 연결된 경우에만 백그라운드 위치를 유지합니다. 첫 번째 클라이언트가 연결되면 즉시 위치를 가져 오려고 시도합니다. 당신의 활동이 연결하는 첫 번째 클라이언트이며 호출하면 getLastLocation()즉시에서 onConnected()첫 번째 위치에 올 수있는 충분한 시간이되지 않을 수도.이 발생합니다 location되고 null.

이 문제를 해결하려면 공급자가 위치 getLastLocation()를 파악할 때까지 (불확실하게) 기다렸다가을 호출 해야합니다. 또 다른 (더 나은) 옵션은 com.google.android.gms.location.LocationListener주기적 위치 업데이트를 수신 하도록 인터페이스 를 구현하는 것입니다 (첫 번째 업데이트를 받으면 끄십시오).

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    // . . . . . . . . more stuff here 
    LocationRequest locationRequest;
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // . . . . other initialization code
        locationClient = new LocationClient(this, this, this);
    locationRequest = new LocationRequest();
    // Use high accuracy
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the update interval to 5 seconds
    locationRequest.setInterval(UPDATE_INTERVAL);
        // Set the fastest update interval to 1 second
    locationRequest.setFastestInterval(FASTEST_INTERVAL);
    }
    // . . . . . . . . other methods 
    @Override
    public void onConnected(Bundle bundle) {
        Location location = locationClient.getLastLocation();
        if (location == null)
            locationClient.requestLocationUpdates(locationRequest, this);
        else
            Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
    }
    // . . . . . . . . other methods
    @Override
    public void onLocationChanged(Location location) {
        locationClient.removeLocationUpdates(this);
        // Use the location here!!!
    }

이 코드에서는 클라이언트에 이미 마지막 위치 ( onConnected) 가 있는지 확인합니다 . 그렇지 않은 경우 위치 업데이트를 요청하고 업데이트를 받으면 onLocationChanged()즉시 콜백으로 요청을 끕니다 .

(가) 참고 locationClient.requestLocationUpdates(locationRequest, this);가이 안에 있어야하는 onConnected콜백, 그렇지 않으면 당신은 얻을 것이다 IllegalStateException당신은 구글 플레이 서비스 클라이언트에 연결하지 않고 위치에 대한 요청하려고 할 것이기 때문에.

  • 사용자가 위치 서비스를 사용 중지했습니다

많은 경우 사용자는 배터리를 절약하거나 개인 정보 보호를 위해 위치 서비스를 비활성화했습니다. 이 경우 위의 코드는 여전히 위치 업데이트를 요청하지만 onLocationChanged호출되지는 않습니다. 사용자가 위치 서비스를 비활성화했는지 확인하여 요청을 중지 할 수 있습니다.

앱에서 위치 서비스를 활성화해야하는 경우 메시지 또는 토스트를 표시하려고합니다. 안타깝게도 사용자가 Google의 위치 서비스 API에서 위치 서비스를 사용 중지했는지 확인하는 방법은 없습니다. 이를 위해서는 Android API를 사용해야합니다.

당신의 onCreate방법에서 :

    LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
    locationEnabled = false;
    Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;

그리고 메소드 locationEnabled에서 다음 onConnected과 같이 플래그를 사용하십시오 .

    if (location != null) {
    Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
    locationClient.requestLocationUpdates(locationRequest, this);
}

최신 정보

대화 상자에서 한 번의 클릭으로 문서가 업데이트되고 LocationClient가 제거되고 API가 GPS를 활성화하도록 지원합니다.

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

링크 https://developer.android.com/training/location/change-location-settings#prompt

새로운 위치 클라이언트 : FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

위치 작업을 수행하기 전에 https://developer.android.com/training/location 을 방문하는 것이 좋습니다 .


9
SettingsApi.checkLocationSettings()사용자가 위치 서비스를 사용 설정했는지 확인 하는 데 사용할 수 있습니다 ( developers.google.com/android/reference/com/google/android/gms/… 참조 ).
kaolick

3
LocationClient가 더 이상 존재하지 않습니다. 위치에 대한 업데이트 된 명확한 안내서는 다음 기사를 확인하십시오. blog.teamtreehouse.com/beginners-guide-location-android
lm2a

1
그리고 SettingsApi 예제가있는 교육 페이지 : developer.android.com/training/location/…
androidguy

2
LocationManager!를 사용하여 지오 펜스를 만들 수도 있습니다 . 통합 위치 API는 Google Play 서비스가없는 기기에서 작동하나요?
Muhammad Babar

이 GPS 활성화 / 비활성화 상태를 확인하는 또 다른 더 좋은 방법이 될 수있다 fun isLocationEnabled(context: Context): Boolean { val locationMode: Int try { locationMode = Settings.Secure.getInt( context.contentResolver, Settings.Secure.LOCATION_MODE ) } catch (e: SettingNotFoundException) { e.printStackTrace() return false } return locationMode != Settings.Secure.LOCATION_MODE_OFF }
Wahib UL 하크

32

내 경험상 "적절한 정확도"가 더 좋은 의미는 아닙니다. 내가 빠진 것이 아니라면 GPS를 사용하고 싶다면 LocationManager가 유일한 방법입니다. 우리는 앱으로 차량을 추적하며, 누락 된 부분이없는 한 Google Play 서비스는 매우 부정확 한 위치를 제공합니다.


2
예, 내 경험상 Google Play 서비스에서 가끔 부정확 한 위치를 제공합니다.
VY

2
예, Google Play 서비스 위치 서비스 API는 매우 잘못된 위치 정보를 제공 할 수 있습니다. WiFi 모뎀이 이동하고 WiFi 모뎀이 잘못된 위치 정보로 업데이트됩니다 (예 : WiFi 모뎀의 위치를 ​​업데이트하는 Android 장치에 의해 위치가 스푸핑 된 경우) WiFi 모뎀 삼각 측량에서 잘못된 위치 데이터를 초래할 수있는 다른 상황이 많이 있습니다. 정확한 위치가 필수 인 모든 앱에서 GPS 만 사용합니다.
user1608385

27

LocationManager 대신 Google Play 서비스 위치 API를 사용해야합니다. 문서에 따르면 :

Google Play 서비스 위치 API는 앱에 위치 인식을 추가하는 방법으로 Android 프레임 워크 위치 API (android.location)보다 선호됩니다. 현재 Android 프레임 워크 위치 API를 사용중인 경우 가능한 빨리 Google Play 서비스 위치 API로 전환하는 것이 좋습니다.

전환해야하는 이유에 대해 Google은 다음과 같이 말합니다.

Google Play 서비스의 일부인 Google 위치 서비스 API는 위치 제공 업체, 사용자 이동 및 위치 정확도를 자동으로 처리하는보다 강력한 고급 프레임 워크를 제공합니다. 또한 제공하는 전력 소비 매개 변수를 기반으로 위치 업데이트 예약을 처리합니다. 대부분의 경우 위치 서비스 API를 사용하면 배터리 성능이 향상되고 정확도가 향상됩니다.


2
이 인용문의 해당 문서에 대한 링크가 있습니까? Google이 지금 다른 말을하고 있는지 확인하는 것이 흥미로울 것입니다.
Edward Brey

3
물론 그들은 위치 데이터를 원하기 때문에 이것을 말합니다!
Flyview

앱에 Google Play 서비스를 추가 할 때 사용자가 앱을 설치하면 앱을 사용하기 위해 Google Play 서비스를 "업데이트"하라는 메시지가 표시됩니다. 그의 / 그녀의 전화가 거의 찼거나 (whatsapp 밈과 물건으로) 사용자가 데이터를 가지고 있지 않은 경우, 내 친구 죄송합니다
Dr Deo

2
@Flyview Yep! 롤, 그들이 말한 방식은 마치 마법의 해결책 인 것처럼 들립니다! 가장 큰 단점은 기기에서 Google Play 서비스가 필요하다는 것입니다 !!!
varun

25

꽤 오랫동안 Google 위치 서비스 API를 사용하고 있습니다. 위치 결정을위한 여러 소스를 갖는 복잡성을 캡슐화하기 때문에 장점이 있습니다. 그러나 그것은 너무 무겁게 캡슐화 되어 이상한 위치를 얻을 때 그 이상한 위치가 어디에서 왔는지 결정할 방법이 없습니다.

실생활에서 나는 실제 위치에서 10 킬로미터 떨어진 몇 가지 괴물 값이 나타났습니다. 유일한 설명은 이러한 미친 위치는 Google Wi-Fi 또는 NWK 데이터베이스의 오류에서 비롯된다는 것입니다. Wi-Fi 및 네트워크 토폴로지는 매일 바뀌기 때문에 항상 존재하는 오류입니다. 그러나 불행히도 (그리고 놀랍게도) API는 개별 위치가 어떻게 도출되었는지에 대한 정보를 제공하지 않습니다.

여기에 이미지 설명을 입력하십시오

속도, 가속도, 베어링 등의 타당성 검사를 기반으로 괴물 값을 필터링 해야하는 문제가 있습니다.

... 또는 좋은 오래된 프레임 워크 API로 돌아가서 GPS 만 사용하십시오 .Google이 융합 API를 개선 할 때까지하기로 결정했습니다.


7

Google Play 서비스의 일부인 Google 위치 서비스 API 위치 제공 업체 , 사용자 이동 위치 정확도 를 자동으로 처리하는보다 강력한 고급 프레임 워크를 제공 합니다 . 또한 제공하는 전력 소비 매개 변수를 기반으로 위치 업데이트 예약을 처리합니다. 대부분의 경우위치 서비스 API를 사용하면 배터리 성능이 향상 되고 정확도가 향상됩니다.

두 가지 API Google Play 서비스 위치 APIAndroid 프레임 워크 위치 API의 자세한 차이점은 여기에서 확인할 수 있습니다 .


괜찮다면 내 질문에 대답하기 위해 답을 사용했습니다. 고마워요! stackoverflow.com/questions/39852955/…
Leniaal

@Leniaal 그래서 내 대답은 공감할 가치가 있다고 생각하지 않습니까?
Dhruvam Gupta

3 년 된 문서입니다. 그러나 여기에 플러스 1이 있습니다
Drew

5

예, Google Play 서비스 위치 서비스 API는 매우 잘못된 위치 정보를 제공 할 수 있습니다. WiFi 모뎀이 이동하고 WiFi 모뎀이 잘못된 위치 정보로 업데이트됩니다 (예 : WiFi 모뎀의 위치를 ​​업데이트하는 Android 장치에 의해 위치가 스푸핑 된 경우) WiFi 모뎀 삼각 측량에서 잘못된 위치 데이터를 초래할 수있는 다른 상황이 많이 있습니다. 정확한 위치가 필수 인 모든 앱에서 GPS 만 사용합니다.


3

GPS 서비스를 기반으로하는 두 가지 API Google Play 서비스 위치 API와 Android 프레임 워크 위치 API의 차이점

FusedLocationProviderClient

  1. 첫 번째 가져 오기의 경우 위치는 null이 아니어야합니다 (예 : 일부 다른 앱은 GoogleplayService 데이터베이스에서 Lastknown 위치를 업데이트해야합니다. null 인 경우 해결해야 함)
  2. 다음 순차 Fetch의 경우 requestLocationUpdates()메소드를 사용 하여 위치를 페치합니다.
  3. 위치 가져 오기에만 기반으로 locationRequest.setInterval(milliseconds)하고 setFastestInterval(milliseconds)기반으로하지, 사용자 위치 변경
  4. 리턴 값 LatLng를 포함 갖는다 단지 7 진수 값 : (11.9557996, 79.8234599 예) 정확하지 등을
  5. 앱 요구 사항에서 현재 위치 거리를 무시할 수있는 정확도 (50-100 미터)를 사용하는 경우 권장
  6. 배터리 사용에 효과적입니다.

위치 관리자 API

  1. locationManager.requestLocationUpdates ()를 사용하여 사용자 위치 가져 오기가 호출됩니다.
  2. 사용자 위치 변경시간 간격을 기반으로 한 위치 가져 오기 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. 반환 된 LatLng 값에는 소수점 이하 14 개의 값 (예 : 11.94574594963342 79.81166719458997)이 있습니다.

  4. 미터 단위의 정확도가 더 필요한 위치 기반 앱에 권장 됩니다.
  5. 배터리 사용량은 가져 오기 간격과 가져 오기 거리를 기준으로합니다.

야! 1 °는 최대 111_111 미터 (20_000_000 / 180)입니다. 따라서 0.0000001 °는 0.011m = 1cm입니다. 더 나은 GPS 해상도가 필요한 곳을 모르겠습니다. 그리고 어떻게 더 나은 GPS 해상도를 달성 할 수 있는지 모르겠습니다.
babay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.