Suche…


Einführung

Android-Standort-APIs werden in einer Vielzahl von Apps für verschiedene Zwecke verwendet, z. B. zum Ermitteln des Benutzerorts, zum Benachrichtigen, wenn ein Benutzer einen allgemeinen Bereich (Geofencing) verlassen hat, und zur Interpretation der Benutzeraktivitäten (Gehen, Laufen, Fahren usw.).

Android-Standort-APIs sind jedoch nicht die einzige Möglichkeit, den Standort des Benutzers zu ermitteln. Im Folgenden finden Sie Beispiele zur Verwendung von LocationManager und anderen gängigen Standortbibliotheken von Android.

Bemerkungen

Für das Erstellen von standortbezogenen Apps in Android gibt es zwei Pfade:

Location-Manager

Pros

  • Feinere Kontrolle
  • In allen Geräten verfügbar
  • Teil des Android-Frameworks

Cons

  • Die Batterieentladung ist ein Problem, wenn sie nicht ordnungsgemäß verwaltet wird
  • Erfordert eine Logik zum Wechseln der Standortanbieter, wenn das Gerät keinen Standort finden kann (z. B. schlechtes GPS in einem Gebäude)

Eigenschaften

  • NMEA-Listener
  • GPS Status Listener
  • Hören Sie sich den Status des Anbieters ab (z. B. GPS ist vom Benutzer deaktiviert)
  • Liste der Anbieter, aus denen die Standortquelle ausgewählt werden kann

Anbieter

Geographisches Positionierungs System

  • Erforderliche Berechtigungen:
  • Genauigkeit: 10m - 100m
  • Leistungsbedarf: HIGH
  • Verfügbarkeit: Weltweit (mit freier Sicht zum Himmel)
  • HINWEISE :
    • Standortaktualisierungen werden in der Regel einmal pro Sekunde gesendet. In Situationen, in denen GPS jedoch längere Zeit nicht verwendet wurde und A-GPS nicht verfügbar ist, dauert es einige Minuten, bis ein Standort empfangen wird.
    • In Fällen, in denen die freie Sicht zum Himmel versperrt ist, werden GPS-Punkte nicht sehr gut gebündelt (Positionspunkte "springen"), und die Genauigkeit kann aufgrund des " Urban Canyon " -Effekts in bestimmten Bereichen irreführend sein.

Netzwerk

  • Erforderliche Berechtigungen:
  • Genauigkeit: 100m - 1000m +
  • Leistungsbedarf: LOW - MEDIUM
  • Verfügbarkeit: In Reichweite des Zellenturm- oder WLAN-Signals
  • ANMERKUNGEN:
    • Standortaktualisierungen werden seltener als GPS ausgeführt
    • Standortaktualisierungen bilden sich normalerweise nicht gut zusammen (Standortpunkte "springen") und die Genauigkeit kann von der Anzahl verschiedener Faktoren abhängen (Anzahl der WLAN-Signale, Signalstärke, Typ des Zellturms usw.).

Passiv

  • Erforderliche Berechtigungen:
  • Genauigkeit: 10m - 1000m +
  • Leistungsbedarf: KEINE
  • Verfügbarkeit: Nur wenn eine andere App einen Standort von GPS oder Netzwerk empfängt
  • ANMERKUNGEN:
    • Verlassen Sie sich nicht darauf, um Sie ständig zu aktualisieren. Dieser hört passiv auf andere Apps, die Standortanfragen stellen, und gibt diese Orte zurück.
    • Gibt keine von FusedLocationProviderApi generierten Punkte zurück, sondern nur die zugrunde liegenden Standortpunkte, die zu ihrer Erzeugung verwendet werden.

FusedLocationProviderApi

Pros

  • Bietet weniger Batterieentlastung "out of the box"
  • Behandelt schlechtes GPS gut
  • Ruft regelmäßig Updates auf

Cons

  • Weniger genaue Kontrolle über GPS
  • Ist möglicherweise nicht auf allen Geräten oder in bestimmten Ländern verfügbar
  • Erfordert die Bibliotheksabhängigkeit von Drittanbietern

Eigenschaften

  • Gut gemanagte Nutzung von Standortanbietern für optimale Einsparungen beim Batteriebetrieb
  • Erzeugt normalerweise genauere Punkte als Network Location Provider
  • Häufigere Aktualisierungen der Bibliothek ermöglichen weitere Verbesserungen
  • Sie müssen nicht angeben, welcher Providertyp verwendet werden soll

LocationRequest Prioritätsstufen

PRIORITY_HIGH_ACCURACY

  • Erforderliche Berechtigungen:
  • Genauigkeit: 10m - 100m
  • Leistungsbedarf: HIGH
  • Verfügbarkeit: Wo immer Google Play-Dienste verfügbar sind.
  • ANMERKUNGEN:
    • Wenn ACCESS_FINE_LOCATION nicht verwendet wird, verwendet dies kein GPS zum Generieren von Standortaktualisierungen, findet jedoch unter den richtigen Bedingungen immer noch einen ziemlich genauen Punkt.
    • Wenn ACCESS_FINE_LOCATION verwendet wird, kann GPS möglicherweise verwendet werden, um Standortpunkte zu generieren, je nachdem, wie genau das Gerät unter den Umgebungsbedingungen aktuell verfolgt werden kann.
    • Obwohl dies möglicherweise genauere Standortaktualisierungen enthält als die anderen Einstellungen, ist es dennoch anfällig für den " Urban Canyon " -Effekt.

PRIORITY_BALANCED_POWER_ACCURACY

  • Erforderliche Berechtigungen:
  • Genauigkeit: 100m - 1000m +
  • Leistungsbedarf: MEDIUM
  • Verfügbarkeit: Wo immer Google Play-Dienste verfügbar sind.
  • ANMERKUNGEN:
    • Gleiche Notizen wie PRIORITY_HIGH_ACCURACY
    • Obwohl es unwahrscheinlich ist, kann diese Einstellung immer noch GPS verwenden, um einen Standort zu generieren.

PRIORITY_LOW_POWER

  • Erforderliche Berechtigungen:
  • Genauigkeit: 100m - 1000m +
  • Leistungsbedarf: LOW
  • Verfügbarkeit: Wo immer Google Play-Dienste verfügbar sind.
  • ANMERKUNGEN:
    • Verwendet wahrscheinlich kein GPS, ist aber bisher noch nicht getestet.
    • Updates sind normalerweise nicht sehr genau
    • Wird im Allgemeinen zum Erkennen signifikanter Standortänderungen verwendet

PRIORITY_NO_POWER

  • Erforderliche Berechtigungen:
  • Genauigkeit: 10m - 1000m +
  • Leistungsbedarf: KEINE
  • Verfügbarkeit: Wo immer Google Play-Dienste verfügbar sind.
  • ANMERKUNGEN:
    • Funktioniert fast identisch mit dem LocationManager PASSIVE_PROVIDER
    • PASSIVE_PROVIDER bei PASSIVE_PROVIDER Aktualisierungen der Google Play-Dienste zurück, wobei PASSIVE_PROVIDER die zugrunde liegenden Standortaktualisierungen PASSIVE_PROVIDER

Fehlerbehebung

OnLocationChanged () wurde nie aufgerufen

Da dies anscheinend ein häufiges Problem beim Beziehen von Android-Standorten ist, werde ich eine kurze Checkliste der gebräuchlichen Korrekturen auflisten:


  1. Überprüfen Sie Ihr Manifest!

    Eines der häufigsten Probleme ist, dass die richtigen Berechtigungen niemals erteilt wurden. Wenn Sie GPS (mit oder ohne Netzwerk) verwenden, verwenden Sie <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> , ansonsten verwenden Sie <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> . Die FusedLocationApi von Google erfordert ACCESS_FINE_LOCATION .


  1. (Für Android 6+) Überprüfen Sie die Laufzeitberechtigungen !

    Nach Berechtigungen suchen und Berechtigungen anfordern! Wenn Sie niemals Berechtigungen erhalten, werden Sie zum Absturz führen oder, schlimmer (wenn Sie alle Ausnahmen wahrnehmen), erhalten Sie keine Hinweise auf irgendetwas! Es ist egal, ob der Benutzer Ihnen beim Start der App die Berechtigung erteilt. Überprüfen Sie immer, ob Sie für alle Anrufe Berechtigungen haben. Der Benutzer kann einfach zu seinen Einstellungen wechseln und sie widerrufen.


  1. Überprüfen Sie Ihren Code!

    Sind Sie sicher, dass Sie den richtigen Hörer übergeben? Haben Sie diesen BroadcastReceiver oder IntentService zu Ihrem Manifest IntentService ? Verwenden Sie PendingIntent.getService() für eine BroadcastReceiver Klasse oder getBroadcast() für eine IntentService Klasse? Sind Sie sicher, dass Sie Ihren Listener nicht sofort nach der Abfrage an einer anderen Stelle in Ihrem Code abmelden?


  1. Geräteeinstellungen überprüfen!

    Stellen Sie natürlich sicher, dass Sie Standortdienste aktiviert haben.

    Geben Sie hier die Bildbeschreibung ein

    Wenn Sie Netzwerkdienste verwenden, haben Sie "Scannen immer verfügbar" aktiviert? Haben Sie Ihren Standortmodus auf "Beste" ("Hohe Genauigkeit") oder "Batteriesparen" ("Nur Netzwerk") eingestellt?

    Geben Sie hier die Bildbeschreibung ein

    Wenn Sie GPS verwenden, haben Sie im Standortmodus "Beste" ("Hohe Genauigkeit") oder "Nur Gerät" aktiviert?

    Geben Sie hier die Bildbeschreibung ein


  1. Überprüfen Sie Ihren Code!

    Ja, das ist zweimal hier. Haben Sie versucht, einen LocationListener anstelle eines PendingIntent oder umgekehrt, um sicherzustellen, dass Sie LocationManager tatsächlich ordnungsgemäß implementiert haben? Sind Sie sicher, dass die Standortanfrage in einem Teil des Aktivitäten- oder Service-Lebenszyklus, von dem Sie nicht erwartet hätten, nicht entfernt wird?


  1. Überprüfen Sie Ihre Umgebung!

    Testen Sie GPS im ersten Stock eines Gebäudes mitten in San Francisco? Testen Sie Netzwerkstandorte mitten im Nirgendwo? Arbeiten Sie in einem geheimen unterirdischen Bunker ohne Funksignale und fragen Sie sich, warum Ihr Gerät keinen Standort findet? Überprüfen Sie immer Ihre Umgebung, wenn Sie versuchen, Standortprobleme zu beheben!


Es kann viele andere, weniger offensichtliche Gründe dafür geben, dass der Standort nicht funktioniert. Bevor Sie jedoch die esoterischen Korrekturen durchsuchen, müssen Sie diese kurze Checkliste durchgehen.

Fixierte Standort-API

Beispiel mit Activity mit 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
    }
}

Beispiel mit Service mit PendingIntent und BroadcastReceiver

BeispielAktivität

Empfohlene Lektüre: 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
            }
        }
    }
}

LocationService

HINWEIS: Vergessen Sie nicht, diesen Dienst im Manifest zu registrieren!

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

LocationReceiver

HINWEIS: Vergessen Sie nicht, diesen Empfänger im Manifest zu registrieren!

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

Anfordern von Standortaktualisierungen mit LocationManager

Wie immer müssen Sie sicherstellen, dass Sie über die erforderlichen Berechtigungen verfügen.

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) {

    }
}

Anfordern von Standortaktualisierungen in einem separaten Thread mithilfe von LocationManager

Wie immer müssen Sie sicherstellen, dass Sie über die erforderlichen Berechtigungen verfügen.

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) {

    }
}

Geofence registrieren

Ich habe die GeoFenceObserversationService Singleton- Klasse erstellt.

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

Wo habe ich Service angefangen? Aus der Anwendungsklasse

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

Wie habe ich Geofences registriert?

  • GeoFenceObserversationService.getInstant().addGeofences();

Adresse von Standort mit Geocoder abrufen

Nachdem Sie das bekam Location - Objekt aus FusedAPI , können Sie ganz einfach erwerben Address von diesem Objekt.

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

Standortaktualisierungen in einem BroadcastReceiver abrufen

Erstellen Sie zuerst eine BroadcastReceiver-Klasse, um die eingehenden Standortaktualisierungen zu verarbeiten:

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 ***");
            }
        }
    }
}

Wenn Sie dann beim onConnected-Rückruf eine Verbindung zum GoogleApiClient herstellen:

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

Vergessen Sie nicht, die Standortaktualisierungsabsicht im entsprechenden Lebenszyklus-Rückruf zu entfernen:

@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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow