Szukaj…


Wprowadzenie

Interfejsy API lokalizacji Androida są używane w wielu aplikacjach do różnych celów, takich jak znajdowanie lokalizacji użytkownika, powiadamianie, kiedy użytkownik opuścił obszar ogólny (Geofencing) i pomagają interpretować aktywność użytkownika (chodzenie, bieganie, prowadzenie samochodu itp.).

Interfejsy API lokalizacji Androida nie są jednak jedynym sposobem na pozyskanie lokalizacji użytkownika. Poniżej podano przykłady korzystania z menedżera LocationManager Android i innych popularnych bibliotek lokalizacji.

Uwagi

Do tworzenia aplikacji rozpoznających lokalizację w systemie Android istnieją dwie ścieżki:

Menedżer lokalizacji

Plusy

  • Bardziej szczegółowa kontrola
  • Dostępne we wszystkich urządzeniach
  • Część systemu Android

Cons

  • Rozładowanie baterii stanowi problem, jeśli nie jest właściwie zarządzany
  • Wymaga logiki do zmiany dostawcy lokalizacji, jeśli urządzenie nie może znaleźć lokalizacji (np. Słaby GPS wewnątrz budynku)

cechy

  • NMEA Listener
  • Odbiornik statusu GPS
  • Słuchaj zmian statusu dostawcy (np. GPS jest wyłączany przez użytkownika)
  • Lista dostawców, z których można wybrać źródło lokalizacji

Dostawcy

GPS

  • Wymagane uprawnienia:
  • Dokładność: 10m - 100m
  • Wymagania dotyczące zasilania: WYSOKA
  • Dostępność: na całym świecie (z wyraźnym widokiem nieba)
  • UWAGI :
    • Aktualizacje lokalizacji zwykle pojawiają się co sekundę, ale w sytuacjach, gdy GPS nie był używany przez pewien czas, a A-GPS jest niedostępny, uzyskanie lokalizacji może potrwać kilka minut.
    • W przypadkach, w których wyraźny widok nieba jest zasłonięty, punkty GPS nie będą się dobrze grupować (punkty lokalizacji „skaczą”), a dokładność może wprowadzać w błąd w niektórych obszarach z powodu efektu „ Urban Canyon ”.

Sieć

  • Wymagane uprawnienia:
  • Dokładność: 100 m - 1000 m +
  • Wymagania dotyczące zasilania: LOW - MEDIUM
  • Dostępność: W zasięgu sygnału z wieży komórkowej lub Wi-Fi
  • UWAGI:
    • Aktualizacje lokalizacji występują rzadziej niż GPS
    • Aktualizacje lokalizacji zwykle nie klastra dobrze (punkty „skok”), a dokładność może wahać się w zależności od liczby różnych czynników (liczba sygnałów Wi-Fi, siła sygnału, rodzaj wieży komórkowej itp.)

Bierny

  • Wymagane uprawnienia:
  • Dokładność: 10 m - 1000 m +
  • Wymagania dotyczące zasilania: BRAK
  • Dostępność: tylko wtedy, gdy inna aplikacja odbierze lokalizację z GPS lub sieci
  • UWAGI:
    • Nie polegaj na tym, aby otrzymywać ciągłe aktualizacje. To nasłuchuje pasywnie do innych aplikacji, które wysyłają żądania lokalizacji, i przekazuje te lokalizacje z powrotem.
    • Nie zwraca punktów wygenerowanych przez FusedLocationProviderApi, tylko punkty bazowe użyte do ich wygenerowania.

FusedLocationProviderApi

Plusy

  • Oferuje mniejsze zużycie baterii „po wyjęciu z pudełka”
  • Dobrze radzi sobie z kiepskim GPS
  • Pobiera aktualizacje częściej

Cons

  • Mniej szczegółowa kontrola nad GPS
  • Może nie być dostępny na wszystkich urządzeniach lub w niektórych krajach
  • Wymaga zależności biblioteki zewnętrznej

cechy

  • Dobrze zarządzane korzystanie z usług dostawców lokalizacji w celu uzyskania optymalnych oszczędności na cieście
  • Zazwyczaj generuje dokładniejsze punkty niż dostawca lokalizacji sieci
  • Częstsze aktualizacje biblioteki, pozwalające na większą poprawę
  • Nie trzeba określać, jakiego typu dostawcy należy użyć

LocationRequest Priority Levels

PRIORITY_HIGH_ACCURACY

  • Wymagane uprawnienia:
  • Dokładność: 10m - 100m
  • Wymagania dotyczące zasilania: WYSOKA
  • Dostępność: wszędzie tam, gdzie dostępne są usługi Google Play.
  • UWAGI:
    • Jeśli ACCESS_FINE_LOCATION nie zostanie użyty, nie użyje GPS do generowania aktualizacji lokalizacji, ale nadal znajdzie dość dokładny punkt w odpowiednich warunkach.
    • Jeśli ACCESS_FINE_LOCATION jest ACCESS_FINE_LOCATION , może, ale nie musi, używać GPS do generowania punktów lokalizacji, w zależności od tego, jak dokładnie może obecnie śledzić urządzenie w danych warunkach środowiskowych.
    • Chociaż może to zgłaszać dokładniejsze aktualizacje lokalizacji niż inne ustawienia, nadal jest podatne na efekt „ Urban Canyon ”.

PRIORITY_BALANCED_POWER_ACCURACY

  • Wymagane uprawnienia:
  • Dokładność: 100 m - 1000 m +
  • Wymagania dotyczące zasilania: ŚREDNI
  • Dostępność: wszędzie tam, gdzie dostępne są usługi Google Play.
  • UWAGI:
    • Te same notatki, co PRIORITY_HIGH_ACCURACY
    • Chociaż jest to mało prawdopodobne, to ustawienie może nadal używać GPS do generowania lokalizacji.

PRIORITY_LOW_POWER

  • Wymagane uprawnienia:
  • Dokładność: 100 m - 1000 m +
  • Wymagania dotyczące zasilania: LOW
  • Dostępność: wszędzie tam, gdzie dostępne są usługi Google Play.
  • UWAGI:
    • Prawdopodobnie nie używa GPS, ale do tej pory nie był testowany.
    • Aktualizacje zwykle nie są bardzo dokładne
    • Stosowany ogólnie do wykrywania znaczących zmian lokalizacji

PRIORITY_NO_POWER

  • Wymagane uprawnienia:
  • Dokładność: 10 m - 1000 m +
  • Wymagania dotyczące zasilania: BRAK
  • Dostępność: wszędzie tam, gdzie dostępne są usługi Google Play.
  • UWAGI:
    • Działa prawie identycznie jak PASSIVE_PROVIDER LocationManager PASSIVE_PROVIDER
    • Po otrzymaniu zgłasza aktualizacje Usług Google Play, przy czym PASSIVE_PROVIDER informuje o PASSIVE_PROVIDER bazowych aktualizacjach lokalizacji

Rozwiązywanie problemów

OnLocationChanged () Never Called

Ponieważ wydaje się, że jest to częsty problem z uzyskiwaniem Lokalizacji Androida, zamieszczę krótką listę typowych poprawek:


  1. Sprawdź swój manifest!

    Jednym z najczęstszych problemów jest to, że nigdy nie udzielono odpowiednich uprawnień. Jeśli używasz GPS (z siecią lub bez), użyj <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> , w przeciwnym razie użyj <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> . FusedLocationApi Google wymaga ACCESS_FINE_LOCATION .


  1. (Dla Androida 6+) Sprawdź uprawnienia czasu wykonywania !

    Sprawdź i poproś o uprawnienia! Jeśli nigdy nie otrzymasz uprawnień, nastąpi awaria lub, co gorsza (jeśli wychwytujesz wszystkie wyjątki), nic nie wskażesz! Nie ma znaczenia, czy użytkownik udzieli Ci zezwolenia na początku aplikacji, zawsze sprawdź, czy masz uprawnienia do wszystkich połączeń. Użytkownik może łatwo przejść do swoich ustawień i je odwołać.


  1. Dokładnie sprawdź swój kod!

    Czy na pewno podajesz odpowiedniego słuchacza? Czy dodałeś ten BroadcastReceiver lub IntentService do swojego manifestu? Czy używasz PendingIntent.getService() w klasie BroadcastReceiver , czy getBroadcast() w klasie IntentService ? Czy na pewno nie wyrejestrowujesz swojego odbiornika w innym miejscu w kodzie natychmiast po zgłoszeniu?


  1. Sprawdź ustawienia urządzenia!

    Oczywiście upewnij się, że masz włączone usługi lokalizacyjne.

    wprowadź opis zdjęcia tutaj

    Jeśli korzystasz z usług sieciowych, czy włączyłeś opcję „Skanowanie zawsze dostępne”? Czy tryb lokalizacji ustawiony jest na „Najlepsza” („Wysoka dokładność”) lub „Oszczędzanie baterii” („Tylko sieć”)?

    wprowadź opis zdjęcia tutaj

    Czy korzystasz z GPS, czy w trybie lokalizacji włączyłeś opcję „Najlepsza” („Wysoka dokładność”) czy „Tylko urządzenie”?

    wprowadź opis zdjęcia tutaj


  1. Dokładnie sprawdź swój kod!

    Tak, to jest tutaj dwa razy. Czy próbowałeś użyć obiektu LocationListener zamiast PendingIntent lub odwrotnie, aby upewnić się, że właściwie zaimplementowałeś PendingIntent LocationManager ? Czy jesteś pewien, że żądanie lokalizacji nie jest usuwane w jakiejś części cyklu działania lub usługi, której nie spodziewałeś się?


  1. Sprawdź swoje otoczenie!

    Czy testujesz GPS na pierwszym piętrze budynku w centrum San Francisco? Czy testujesz lokalizacje sieciowe w szczerym polu? Czy pracujesz w tajnym podziemnym bunkrze pozbawionym wszelkich sygnałów radiowych, zastanawiając się, dlaczego Twoje urządzenie nie otrzymuje lokalizacji? Zawsze dwukrotnie sprawdzaj otoczenie, próbując rozwiązać problemy z lokalizacją!


Może istnieć wiele innych mniej oczywistych powodów, dla których lokalizacja nie działa, ale przed wyszukaniem tych ezoterycznych poprawek wystarczy przejrzeć tę krótką listę kontrolną.

Interfejs API lokalizacji bezpieczników

Przykład użycia działania w / LocationRequest

/*
 * This example is useful if you only want to receive updates in this 
 * activity only, and have no use for location anywhere else.
 */
public class LocationActivity extends AppCompatActivity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        mLocationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) //GPS quality location points
                .setInterval(2000) //At least once every 2 seconds
                .setFastestInterval(1000); //At most once a second
    }

    @Override
    protected void onStart(){
        super.onStart();
        mGoogleApiClient.connect();
    }
    
    @Override
    protected void onResume(){
        super.onResume();
        //Permission check for Android 6.0+
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            if(mGoogleApiClient.isConnected()) {
                LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }
        }
    }
    
    @Override
    protected void onPause(){
        super.onPause();
        //Permission check for Android 6.0+
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            if(mGoogleApiClient.isConnected()) {
                LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            }
        }
    }
    
    @Override
    protected void onStop(){
        super.onStop();
        mGoogleApiClient.disconnect();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }

    @Override
    public void onLocationChanged(Location location) {
        //Handle your location update code here
    }
}

Przykład użycia usługi w / PendingIntent i BroadcastReceiver

Przykład Aktywności

Zalecana lektura: LocalBroadcastManager

/*
 * This example is useful if you have many different classes that should be 
 * receiving location updates, but want more granular control over which ones
 * listen to the updates.
 * 
 * For example, this activity will stop getting updates when it is not visible, but a database
 * class with a registered local receiver will continue to receive updates, until "stopUpdates()" is called here.
 *
 */
public class ExampleActivity extends AppCompatActivity {

    private InternalLocationReceiver mInternalLocationReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        
        //Create internal receiver object in this method only.
        mInternalLocationReceiver = new InternalLocationReceiver(this);
    }

    @Override
    protected void onResume(){
        super.onResume();
        
        //Register to receive updates in activity only when activity is visible
        LocalBroadcastManager.getInstance(this).registerReceiver(mInternalLocationReceiver, new IntentFilter("googleLocation"));
    }

    @Override
    protected void onPause(){
        super.onPause();
        
        //Unregister to stop receiving updates in activity when it is not visible.
        //NOTE: You will still receive updates even if this activity is killed.
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mInternalLocationReceiver);
    }

    //Helper method to get updates
    private void requestUpdates(){
        startService(new Intent(this, LocationService.class).putExtra("request", true));
    }

    //Helper method to stop updates
    private void stopUpdates(){
        startService(new Intent(this, LocationService.class).putExtra("remove", true));
    }

    /*
     * Internal receiver used to get location updates for this activity.
     * 
     * This receiver and any receiver registered with LocalBroadcastManager does
     * not need to be registered in the Manifest.
     *
     */
    private static class InternalLocationReceiver extends BroadcastReceiver{

        private ExampleActivity mActivity;

        InternalLocationReceiver(ExampleActivity activity){
            mActivity = activity;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            final ExampleActivity activity = mActivity;
            if(activity != null) {
                LocationResult result = intent.getParcelableExtra("result");
                //Handle location update here
            }
        }
    }
}

Usługa lokalizacji

UWAGA: Nie zapomnij zarejestrować tej usługi w Manifeście!

public class LocationService extends Service implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;

    @Override
    public void onCreate(){
        super.onCreate();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        mLocationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) //GPS quality location points
                .setInterval(2000) //At least once every 2 seconds
                .setFastestInterval(1000); //At most once a second
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        super.onStartCommand(intent, flags, startId);
        //Permission check for Android 6.0+
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            if (intent.getBooleanExtra("request", false)) {
                if (mGoogleApiClient.isConnected()) {
                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent());
                } else {
                    mGoogleApiClient.connect();
                }
            }
            else if(intent.getBooleanExtra("remove", false)){
                stopSelf();
            }
        }

        return START_STICKY;
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        if(mGoogleApiClient.isConnected()){
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, getPendingIntent());
            mGoogleApiClient.disconnect();
        }
    }
    
    private PendingIntent getPendingIntent(){
        
        //Example for IntentService
        //return PendingIntent.getService(this, 0, new Intent(this, **YOUR_INTENT_SERVICE_CLASS_HERE**), PendingIntent.FLAG_UPDATE_CURRENT);
        
        //Example for BroadcastReceiver
        return PendingIntent.getBroadcast(this, 0, new Intent(this, LocationReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        //Permission check for Android 6.0+
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent());
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Lokalizacja Odbiorca

UWAGA: Nie zapomnij zarejestrować tego odbiornika w Manifeście!

public class LocationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if(LocationResult.hasResult(intent)){
            LocationResult locationResult = LocationResult.extractResult(intent);
            LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("googleLocation").putExtra("result", locationResult));
        }
    }
}

Żądanie aktualizacji lokalizacji za pomocą menedżera lokalizacji

Jak zawsze musisz upewnić się, że masz wymagane uprawnienia.

public class MainActivity extends AppCompatActivity implements LocationListener{

    private LocationManager mLocationManager = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    }


    @Override
    protected void onResume() {
        super.onResume();

        try {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        }
        catch(SecurityException e){
            // The app doesn't have the correct permissions
        }
    }


    @Override
    protected void onPause() {
        try{
            mLocationManager.removeUpdates(this);
        }
        catch (SecurityException e){
            // The app doesn't have the correct permissions
        }

        super.onPause();
    }




    @Override
    public void onLocationChanged(Location location) {
        // We received a location update!
        Log.i("onLocationChanged", location.toString());
    }

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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }
}

Żądanie aktualizacji lokalizacji w oddzielnym wątku za pomocą menedżera lokalizacji

Jak zawsze musisz upewnić się, że masz wymagane uprawnienia.

public class MainActivity extends AppCompatActivity implements LocationListener{

    private LocationManager mLocationManager = null;
    HandlerThread mLocationHandlerThread = null;
    Looper mLocationHandlerLooper = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        mLocationHandlerThread = new HandlerThread("locationHandlerThread");
    }


    @Override
    protected void onResume() {
        super.onResume();

        mLocationHandlerThread.start();
        mLocationHandlerLooper = mLocationHandlerThread.getLooper();

        try {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this, mLocationHandlerLooper);
        }
        catch(SecurityException e){
            // The app doesn't have the correct permissions
        }
    }


    @Override
    protected void onPause() {
        try{
            mLocationManager.removeUpdates(this);
        }
        catch (SecurityException e){
            // The app doesn't have the correct permissions
        }

        mLocationHandlerLooper = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
            mLocationHandlerThread.quitSafely();
        else
            mLocationHandlerThread.quit();

        mLocationHandlerThread = null;


        super.onPause();
    }




    @Override
    public void onLocationChanged(Location location) {
        // We received a location update on a separate thread!
        Log.i("onLocationChanged", location.toString());

        // You can verify which thread you're on by something like this:
        // Log.d("Which thread?", Thread.currentThread() == Looper.getMainLooper().getThread() ? "UI Thread" : "New thread");
    }

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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }
}

Zarejestruj strefę geofence

Stworzyłem GeoFenceObserversationService singletonów GeoFenceObserversationService .

GeoFenceObserversationService.java :

public class GeoFenceObserversationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {

    protected static final String TAG = "GeoFenceObserversationService";
    protected GoogleApiClient mGoogleApiClient;
    protected ArrayList<Geofence> mGeofenceList;
    private boolean mGeofencesAdded;
    private SharedPreferences mSharedPreferences;
    private static GeoFenceObserversationService mInstant;
    public static GeoFenceObserversationService getInstant(){
        return mInstant;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mInstant = this;
        mGeofenceList = new ArrayList<Geofence>();
        mSharedPreferences = getSharedPreferences(AppConstants.SHARED_PREFERENCES_NAME, MODE_PRIVATE);
        mGeofencesAdded = mSharedPreferences.getBoolean(AppConstants.GEOFENCES_ADDED_KEY, false);

        buildGoogleApiClient();
    }


    @Override
    public void onDestroy() {
        mGoogleApiClient.disconnect();
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    protected void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle connectionHint) {
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
    }

    @Override
    public void onConnectionSuspended(int cause) {

    }

    private GeofencingRequest getGeofencingRequest() {

        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofences(mGeofenceList);
        return builder.build();
    }


    public void addGeofences() {
            if (!mGoogleApiClient.isConnected()) {
                Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
                return;
            }

        populateGeofenceList();
        if(!mGeofenceList.isEmpty()){
            try {
                LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, getGeofencingRequest(), getGeofencePendingIntent()).setResultCallback(this);
            } catch (SecurityException securityException) {
                securityException.printStackTrace();
            }
        }

        }

    public void removeGeofences() {
        if (!mGoogleApiClient.isConnected()) {
            Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient,getGeofencePendingIntent()).setResultCallback(this);
        } catch (SecurityException securityException) {
            securityException.printStackTrace();
        }
    }


    public void onResult(Status status) {

        if (status.isSuccess()) {
            mGeofencesAdded = !mGeofencesAdded;
            SharedPreferences.Editor editor = mSharedPreferences.edit();
            editor.putBoolean(AppConstants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
            editor.apply();
        } else {
            String errorMessage = AppConstants.getErrorString(this,status.getStatusCode());
            Log.i("Geofence", errorMessage);
        }
    }

    private PendingIntent getGeofencePendingIntent() {
        Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private void populateGeofenceList() {
        mGeofenceList.clear();
        List<GeoFencingResponce> geoFenceList = getGeofencesList;
        if(geoFenceList!=null&&!geoFenceList.isEmpty()){
            for (GeoFencingResponce obj : geoFenceList){
                mGeofenceList.add(obj.getGeofence());
                Log.i(TAG,"Registered Geofences : " + obj.Id+"-"+obj.Name+"-"+obj.Lattitude+"-"+obj.Longitude);
            }
        }
    }
}

AppConstant :

   public static final String SHARED_PREFERENCES_NAME = PACKAGE_NAME + ".SHARED_PREFERENCES_NAME";
    public static final String GEOFENCES_ADDED_KEY = PACKAGE_NAME + ".GEOFENCES_ADDED_KEY";
    public static final String DETECTED_GEOFENCES = "detected_geofences";
    public static final String DETECTED_BEACONS = "detected_beacons";

    public static String getErrorString(Context context, int errorCode) {
        Resources mResources = context.getResources();
        switch (errorCode) {
            case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
                return mResources.getString(R.string.geofence_not_available);
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
                return mResources.getString(R.string.geofence_too_many_geofences);
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
                return mResources.getString(R.string.geofence_too_many_pending_intents);
            default:
                return mResources.getString(R.string.unknown_geofence_error);
        }
    }

Gdzie rozpocząłem usługę? Z klasy aplikacji

  • startService(new Intent(getApplicationContext(),GeoFenceObserversationService.class));

Jak zarejestrowałem Geofence?

  • GeoFenceObserversationService.getInstant().addGeofences();

Uzyskaj adres z lokalizacji za pomocą Geokodera

Po uzyskaniu obiektu Location z FusedAPI możesz łatwo uzyskać informacje o Address z tego obiektu.

private Address getCountryInfo(Location location) {
    Address address = null;
    Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault());
    String errorMessage;
    List<Address> addresses = null;
    try {
        addresses = geocoder.getFromLocation(
                location.getLatitude(),
                location.getLongitude(),
                // In this sample, get just a single address.
                1);
    } catch (IOException ioException) {
        // Catch network or other I/O problems.
        errorMessage = "IOException>>" + ioException.getMessage();
    } catch (IllegalArgumentException illegalArgumentException) {
        // Catch invalid latitude or longitude values.
        errorMessage = "IllegalArgumentException>>" + illegalArgumentException.getMessage();
    }
    if (addresses != null && !addresses.isEmpty()) {
        address = addresses.get(0);
    }
    return country;
}

Pobieranie aktualizacji lokalizacji w odbiorniku BroadcastReceiver

Najpierw utwórz klasę BroadcastReceiver do obsługi nadchodzących aktualizacji lokalizacji:

public class LocationReceiver extends BroadcastReceiver implements Constants {

    @Override
     public void onReceive(Context context, Intent intent) {

        if (LocationResult.hasResult(intent)) {
            LocationResult locationResult = LocationResult.extractResult(intent);
            Location location = locationResult.getLastLocation();
            if (location != null) {
                // Do something with your location
            } else {
                Log.d(LocationReceiver.class.getSimpleName(), "*** location object is null ***");
            }
        }
    }
}

Następnie, gdy łączysz się z GoogleApiClient w wywołaniu zwrotnym onConnected:

@Override
public void onConnected(Bundle connectionHint) {
    Intent backgroundIntent = new Intent(this, LocationReceiver.class);
    mBackgroundPendingIntent = backgroundPendingIntent.getBroadcast(getApplicationContext(), LOCATION_REUEST_CODE, backgroundIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    mFusedLocationProviderApi.requestLocationUpdates(mLocationClient, mLocationRequest, backgroundPendingIntent);
}

Nie zapomnij usunąć zamiaru aktualizacji lokalizacji w odpowiednim wywołaniu zwrotnym cyklu życia:

@Override
public void onDestroy() {
    if (servicesAvailable && mLocationClient != null) {
        if (mLocationClient.isConnected()) {
            fusedLocationProviderApi.removeLocationUpdates(mLocationClient, backgroundPendingIntent);
            // Destroy the current location client
            mLocationClient = null;
        } else {
            mLocationClient.unregisterConnectionCallbacks(this);
            mLocationClient = null;
        }
    }
    super.onDestroy();
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow