Android: LocationManager ve Google Play Hizmetleri


151

Kullanıcının mevcut konumunu elde etme üzerine odaklanan bir uygulama oluşturmak ve ardından Google Rehber API'sı aracılığıyla kendisine yakın olan ilgi çekici noktaları (barlar, restoranlar vb.) Bulmak istiyorum .

Web'de başlayacak bir yer araması üzerine, LocationManagersınıfı kullanan bazı öğreticilerle ve kullanıcıların yerini bulmak için Google Play Hizmetleri'ni kullanan bazı eğiticilerle karşılaştım .

İlk bakışta her ikisi de aynı şeyi yapıyor, ama ben yeni olduğum için biraz kafam karıştı ve hangi yöntemin ihtiyaçlarına en uygun olduğunu bilmiyorum. Size sormak istiyorum:

Bu iki konum bulma yöntemi (varsa) arasındaki farklar nelerdir?


Yanıtlar:


320

Android'de Kullanıcı Konumu

Kullanıcının Android'de yerini almak, iOS'a göre biraz daha basittir. Karışıklık başlatmak için, bunu yapmanın iki farklı yolu vardır. Birincisi Android API'larını android.location.LocationListenerve ikincisi Google Play Hizmetleri API'larını kullanıyor com.google.android.gms.location.LocationListener. İkisini de gözden geçirelim.

  1. Android'in Konum API'sı

    Android'in konum API'ları, konum almak için üç farklı sağlayıcı kullanır -

    • LocationManager.GPS_PROVIDER- Bu sağlayıcı uydu kullanarak konumu belirler. Koşullara bağlı olarak, bu sağlayıcının konum düzeltmesini geri alması biraz zaman alabilir.
    • LocationManager.NETWORK_PROVIDER- Bu sağlayıcı, baz istasyonu ve WiFi erişim noktalarının kullanılabilirliğine göre konumu belirler. Sonuçlar bir ağ araması yoluyla alınır.
    • LocationManager.PASSIVE_PROVIDER- Bu sağlayıcı, diğer sağlayıcılar tarafından oluşturulan konumları döndürecektir. Diğer uygulamalar veya hizmetler istediklerinde, konumları kendiniz istemeden pasif olarak konum güncellemeleri alırsınız.

Bunun özü size bir nesne elde ediyoruz LocationManagersistemden uygulamak LocationListenerve çağrı requestLocationUpdatesüzerine LocationManager.

İşte bir kod snippet'i:

    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'ın Konum Stratejileri API Kılavuzukodu oldukça güzel açıklıyor. Ancak, çoğu durumda, bunun yerine Google Konum Hizmetleri API'sını kullanarak daha iyi pil performansı ve daha uygun doğruluk elde edeceğinizi de belirtmişlerdir . Şimdi karışıklık başlıyor!

  1. Google'ın Konum Hizmetleri API'sı

Google'ın Konum Hizmetleri API'sı Google Play Hizmetleri APK'sının bir parçasıdır ( nasıl ayarlanacağı aşağıda açıklanmıştır ). Android API'sı üzerine inşa edilmiştir. Bu API'ler, yukarıda belirtilen sağlayıcılar yerine "Kaynaşmış Konum Sağlayıcı" sağlar. Bu sağlayıcı, doğruluğu, pil kullanımını vb. Temel alarak hangi sağlayıcıyı kullanacağını otomatik olarak seçer. Hızlıdır, çünkü güncellemeye devam eden sistem çapında bir hizmetten konum alırsınız. Ayrıca, coğrafi eskrim gibi daha gelişmiş özellikleri kullanabilirsiniz.

Google'ın Konum Hizmetlerini kullanmak için, uygulamanızın GooglePlayServicesClient. İstemciye bağlanmak için, etkinliğinizin (veya fragmanınızın vb.) Uygulanması GooglePlayServicesClient.ConnectionCallbacksve GooglePlayServicesClient.OnConnectionFailedListenerarayüzleri gerekir. İşte bir örnek kod:

    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 
    }
  • Neden locationClient.getLastLocation()boş?

En locationClient.getLastLocation()son bilinen konum istemciden alınır. Ancak, Kaynaşmış Konum Sağlayıcı arka plan konumunu yalnızca en az bir istemci bağlıysa koruyacaktır. İlk istemci bağlandığında, hemen bir konum almaya çalışacaktır. Etkinlik bağlamak için ilk müşteri olduğunu ve çağırırsanız getLastLocation()hemen içinde onConnected()ilk konum gelmek için yeterli zaman olmayabilir ki. Bu sonuçlanacaktır locationolmak null.

Bu sorunu çözmek için, sağlayıcı konumu getLastLocation()alana kadar beklemeniz gerekir (belirsiz bir şekilde) ve sonra aramak imkansızdır. Başka bir (daha iyi) seçenek, com.google.android.gms.location.LocationListenerperiyodik konum güncellemelerini almak için arabirimi uygulamaktır (ve ilk güncellemeyi aldıktan sonra kapatmaktır).

    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!!!
    }

Bu kodda, istemcinin zaten en son konuma (in onConnected) sahip olup olmadığını kontrol edersiniz . Değilse, konum güncellemeleri talep edersiniz ve güncelleme alır almaz istekleri ( onLocationChanged()geri aramada) kapatırsınız .

Bunun geri aramanın locationClient.requestLocationUpdates(locationRequest, this);içinde olması gerektiğini onConnected, aksi IllegalStateExceptiontakdirde Google Play Hizmetleri İstemcisi'ne bağlı olmayan konumlar için istekte bulunmaya çalışacağınızı unutmayın.

  • Kullanıcı Konum Hizmetlerini devre dışı bıraktı

Çoğu zaman, kullanıcının konum hizmetlerini devre dışı bırakması gerekir (pilden tasarruf etmek veya gizlilik nedenleriyle). Böyle bir durumda, yukarıdaki kod yine de konum güncellemeleri ister, ancak onLocationChangedhiçbir zaman çağrılmaz. Kullanıcının konum hizmetlerini devre dışı bırakıp bırakmadığını kontrol ederek istekleri durdurabilirsiniz.

Uygulamanız konum hizmetlerini etkinleştirmelerini gerektiriyorsa, bir mesaj veya tost göstermek istersiniz. Ne yazık ki, kullanıcının Google'ın Konum Hizmetleri API'sında konum hizmetlerini devre dışı bırakıp bırakmadığını kontrol etmenin bir yolu yoktur. Bunun için Android'in API'sına başvurmanız gerekir.

Senin içinde onCreateyöntemle:

    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;

Ve yönteminizdeki locationEnabledbayrağı onConnectedşu şekilde kullanın:

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

GÜNCELLEME

Belge güncellenir, LocationClient kaldırılır ve API, iletişim kutusundan tek bir tıklama ile GPS'i etkinleştirmeyi destekler:

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.
            }
        }
    }
});

Bağlantı https://developer.android.com/training/location/change-location-settings#prompt

Yeni konum istemcisi: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

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

Herhangi bir konum görevi gerçekleştirmeden önce https://developer.android.com/training/location adresinden geçmeniz önerilir .


9
SettingsApi.checkLocationSettings()Kullanıcının Konum Hizmetlerini etkinleştirip etkinleştirmediğini kontrol etmek için kullanabilirsiniz (buraya bakın: developers.google.com/android/reference/com/google/android/gms/… ).
13'te kaolick

3
LocationClient artık mevcut değil. Konumla ilgili
lm2a

1
Ve SettingsApi örneğiyle eğitim sayfası: developer.android.com/training/location/…
androidguy

2
Ayrıca kullanarak bir coğrafi çit oluşturabilirsiniz LocationManager! Kaynaşmış konum API'si, Google Play Hizmetleri olmayan cihazlarda çalışıyor mu?
Muhammed Babar

Bu GPS etkinleştirmek / devre dışı durumunu kontrol etmek başka daha iyi bir yol olabilir 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 Haq

32

Deneyimlerime göre, "daha uygun doğruluk" hiçbir şekilde daha iyi anlamına gelmez. Bir şeyi kaçırmadıkça, GPS'in kullanıldığından emin olmak istiyorsanız, LocationManager tek yoludur. Araçları uygulamamızla izliyoruz ve bir şey eksik olmadıkça Google Play Hizmetleri oldukça sık bazı yanlış yerler sağlıyor.


2
Evet, deneyimlerime göre Google Play Hizmetleri bazen yanlış konum sağlıyor.
VY

2
Evet, Google Play Hizmetleri Konum Hizmetleri API'sı çok yanıltıcı Konum bilgisi verebilir. WiFi modemler taşınır, WiFi modemler yanlış konum bilgileriyle güncellenir (yani konum, WiFi modeminin konumunu güncelleyen bir Android cihaz tarafından aldatıldıysa) ve WiFi modem üçgenlemesinden yanlış Konum verilerine neden olabilecek bir dizi başka durum vardır. Kesin Konumun zorunlu olduğu tüm uygulamalarımızda yalnızca GPS kullanırız.
user1608385

27

LocationManager yerine Google Play Hizmetleri konum api'sini kullanmalısınız. Dokümanlara göre:

Google Play hizmetleri konum API'ları, uygulamanıza konum farkındalığı eklemenin bir yolu olarak Android çerçeve konum API'larına (android.location) tercih edilir. Şu anda Android çerçeve konum API'larını kullanıyorsanız, Google Play hizmetleri konum API'larına mümkün olan en kısa sürede geçmeniz önemle tavsiye edilir.

Neden geçiş yapılacağı konusunda Google şunları söylüyor:

Google Play Hizmetleri'nin bir parçası olan Google Konum Hizmetleri API'sı, konum sağlayıcılarını, kullanıcı hareketini ve konum doğruluğunu otomatik olarak işleyen daha güçlü, yüksek düzeyli bir çerçeve sağlar. Ayrıca, sağladığınız güç tüketimi parametrelerine dayalı olarak konum güncelleme zamanlamasını da işler. Çoğu durumda, Konum Hizmetleri API'sını kullanarak daha iyi pil performansı ve daha uygun doğruluk elde edersiniz.


2
Bu tekliflerin alındığı belgelere bağlantılarınız var mı? Google'ın şimdi farklı bir şey söylediğini görmek ilginç olurdu.
Edward Brey

3
Tabii bunu söylüyorlar, çünkü konum verilerinizi istiyorlar!
Flyview

Google play hizmetlerini uygulamanıza eklediğinizde, bir kullanıcı uygulamanızı yüklerse, uygulamanızı kullanmak için google play hizmetlerini "güncellemesi" istenir. Telefonunun neredeyse doluysa (whatsapp memleri ve eşyaları ile) veya kullanıcının verileri yoksa, sizin için üzgünüm arkadaşım
Dr Deo

2
@Flyview Yep! Lol, sözlerini sihirli bir çözüm gibi seslendiriyor! En büyük dezavantajı, cihazda Google Play Hizmetleri'ne ihtiyacınız var !!!
varun

25

Google Konum Hizmetleri API'sini uzun süredir kullanıyorum. Pozisyonları belirlemek için çeşitli kaynaklara sahip olmanın karmaşıklığını kapsadığı için avantajları vardır. Bununla birlikte, çok ağır bir şekilde kapsüllenir , böylece garip bir pozisyon aldığınızda, bu garip pozisyonun nereden geldiğini belirleyemezsiniz.

Gerçek hayatta, gerçek konumdan 10 kilometre uzakta olan birkaç ucube değeri ortaya çıktı. Tek açıklama, bu çılgın konumların Googles Wi-Fi veya NWK veritabanlarındaki hatalardan kaynaklandığıdır - Wi-Fi ve Ağ topolojileri her gün değiştiği için her zaman orada olacak hatalar. Ancak ne yazık ki (ve şaşırtıcı bir şekilde) API size bireysel bir pozisyonun nasıl türetildiği hakkında hiçbir bilgi vermez.

resim açıklamasını buraya girin

Bu, hız, hızlanma, rulman vb. Üzerinde güvenilirlik kontrolüne dayanarak ucube değerlerini filtrelemek zorunda kalmanıza neden olur.

... veya eski eski API API'sine geri dönün ve yalnızca GPS'i kullanın; Google, sigortalı API'yı geliştirene kadar yapmaya karar verdim.


7

Google Play Hizmetleri'nin bir parçası olan Google Konum Hizmetleri API'sı , konum sağlayıcılarını , kullanıcı hareketini ve konum doğruluğunu otomatik olarak işleyen daha güçlü, yüksek düzeyli bir çerçeve sağlar. Ayrıca, sağladığınız güç tüketimi parametrelerine dayalı olarak konum güncelleme zamanlamasını da işler. Çoğu durumda,Konum Hizmetleri API'sını kullanarak daha iyi pil performansı ve daha uygun doğrulukelde edersiniz.

İki apis arasındaki Daha detaylı diffferences tarihinde Servis Yeri API Çal ve Android Çerçeve Yeri API bulunabilir burada


Cevabınızı, sorunum varsa kendi sorumu cevaplamak için kullandım. Çok teşekkürler! stackoverflow.com/questions/39852955/…
Leniaal

@Leniaal, cevabımın oylamayı hak ettiğini düşünmüyor musunuz?
Dhruvam Gupta

Bu 3 yıllık eski bir belge. Ama işte artı 1
Drew

5

Evet, Google Play Hizmetleri Konum Hizmetleri API'sı çok yanıltıcı Konum bilgisi verebilir. WiFi modemler taşınır, WiFi modemler yanlış konum bilgileriyle güncellenir (yani konum, WiFi modeminin konumunu güncelleyen bir Android cihaz tarafından aldatıldıysa) ve WiFi modem üçgenlemesinden yanlış Konum verilerine neden olabilecek bir dizi başka durum vardır. Kesin Konumun zorunlu olduğu tüm uygulamalarımızda yalnızca GPS kullanırız.


3

GPS hizmetine dayalı iki apis Google Play Hizmet Konumu API'sı ile Android Framework Konum API'sı arasındaki farklar

FusedLocationProviderClient

  1. 1. getirme için konum boş olmamalıdır (başka bir deyişle, başka bir uygulamanın GoogleplayService veritabanındaki Son Bilinen konumu güncellemesi gerekir. Boşsa, geçici çözüm bulunması gerekir)
  2. Bir sonraki sıralı Getirme requestLocationUpdates()için, konumu getirme yöntemini kullanır .
  3. Konumu getirme sadece dayanmaktadır locationRequest.setInterval(milliseconds)ve setFastestInterval(milliseconds)dayanmadığı, kullanıcı konumu değişikliği
  4. Döndürülen LatLng değeri yalnızca 7 ondalık değer içeriyor (örn: 11.9557996, 79.8234599), doğru değil
  5. Uygulama gereksiniminiz mevcut konum mesafesini ihmal edilebilir olduğunda (50 - 100 metre doğruluk) önerilir
  6. Pil kullanımında etkilidir.

Konum Yöneticisi Api

  1. Kullanıcı konumu getirme locationManager.requestLocationUpdates () kullanılarak çağrılır
  2. Kullanıcı konum değişikliği ve zaman aralıklarına dayalı konum getirme locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. Döndürülen LatLng değeri 14 ondalık değer içeriyor (örneğin: 11.94574594963342 79.81166719458997) doğru konum değerleri

  4. Metre cinsinden daha fazla doğruluk gerektiğinde konum tabanlı uygulama için önerilir .
  5. Pil kullanımı getirme aralığına ve getirme mesafesine bağlıdır.

Hey! 1 ° en fazla 111_111 metredir (20_000_000 / 180). Böylece, 0.0000001 ° 0.011m = 1 cm'dir. Nerede daha iyi GPS çözünürlüğüne ihtiyacınız olduğunu bilmiyorum. Ve bilmiyorum bile, nasıl daha iyi GPS çözünürlüğü elde edebilirsiniz.
babay
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.