gps 구글 - Android:LocationManager와 Google Play 서비스




구글플레이서비스 종류 (5)

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

두 apis Google Play 서비스 위치 APIAndroid 프레임 위치 API 간의 자세한 차이점은 here 확인할 수 있습니다 here

사용자의 현재 위치를 파악하고 Google Places API 를 통해 관심있는 장소 (바, 레스토랑 등)를 찾을 수있는 앱을 만들고 싶습니다.

시작 장소를 웹에서 검색 할 때 LocationManager 클래스와 Google Play 서비스 를 사용하는 일부 자습서를 통해 사용자 위치를 찾았습니다.

첫눈에 그들 둘 다 똑같은 일을하지만, 나는 이것에 익숙하지 않아 조금 혼란스러워하고 어떤 방법이 나의 필요에 가장 잘 맞는지 모른다. 그래서 나는 너에게 묻고 싶다.

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


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

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

속도, 가속도, 베어링 등에 대한 타당성 검사를 기반으로 괴물 값을 걸러 내야하는 문제가 생깁니다.

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


내 경험에 비추어 볼 때, "더 적절한 정확성"이 어떤 의미에서는 더 나은 의미는 아닙니다. 내가 놓친 게 아니라면, GPS를 사용하고 싶다면 LocationManager 만 갈 수 있습니다. 앱으로 차량을 추적하고 뭔가를 놓치지 않는 한 Google Play 서비스는 아주 부정확 한 위치를 제공합니다.


Android에서의 사용자 위치

Android에서 사용자의 위치를 ​​얻는 것이 iOS에서보다 덜 간단합니다. 혼란을 시작하려면 완전히 다른 두 가지 방법이 있습니다. 첫 번째는 android.location.LocationListener Android API를 사용하고 두 번째는 Google Play 서비스 API 인 com.google.android.gms.location.LocationListener 있습니다. 둘 다 통과합시다.

  1. Android의 위치 API

    안드로이드의 위치 API는 세 가지 다른 공급자를 사용하여 위치 정보를 얻습니다.

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

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

코드 스 니펫은 다음과 같습니다.

    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.ConnectionCallbacksGooglePlayServicesClient.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() 은 클라이언트에서 마지막으로 알려진 위치를 가져옵니다. 그러나 적어도 하나의 클라이언트가 연결된 경우 융합 위치 공급자는 백그라운드 위치 만 유지합니다. 첫 번째 클라이언트가 연결되면 즉시 위치를 얻으려고 시도합니다. 액티비티가 연결하는 첫 번째 클라이언트이고 onConnected() 에서 getLastLocation() 바로 호출하면 첫 번째 위치가 올 시간이 충분하지 않을 수 있습니다. 이로 인해 locationnull 됩니다.

이 문제를 해결하려면 공급자가 위치를 얻고 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 콜백 안에 있어야합니다. 그렇지 않으면 Google Play 서비스 클라이언트에 연결하지 않고 위치를 요청하려고하기 때문에 IllegalStateException 이 발생합니다.

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

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

앱에서 위치 서비스를 사용하도록 설정 한 경우 메시지 나 축배를 보여주고 싶을 것입니다. 안타깝게도 사용자가 Google 위치 서비스 API에서 위치 서비스를 사용 중지했는지 확인할 방법이 없습니다. 이를 위해 안드로이드 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;

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

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

Rahul Jiresal 덕택입니다.


동료는 활동주기 및 상태 정보, 상태 정보 저장 방법, State BundleSharedPreferences 저장 방법과 같은 Android 장치의 응용 프로그램 상태를 설명하는 기사를 작성하여 여기에서 살펴보십시오 .

이 기사에서는 세 가지 방법을 다룹니다.

Instance State Bundle을 사용하여 응용 프로그램 수명 (즉, 일시적으로)에 대한 로컬 가변 / UI 제어 데이터 저장

[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

공유 환경 설정을 사용하여 응용 프로그램 인스턴스간에 영구적으로 로컬 변수 / UI 제어 데이터 저장

[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store    
  // Commit to storage
  editor.commit();
}

Retained Non-Configuration Instance를 사용하여 응용 프로그램 수명 내의 활동간에 메모리에 객체 인스턴스를 유지

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;// Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}




android gps geolocation