Android
Ort
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:
- Der native Open Source-
LocationManager
Android -
FusedLocationProviderApi
von Google, ein Teil der Google Play Services
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:
-
ACCESS_FINE_LOCATION
für einen genaueren Standort oderACCESS_COARSE_LOCATION
für einen weniger genauen Standort
-
- 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.
- Wenn
PRIORITY_BALANCED_POWER_ACCURACY
- Erforderliche Berechtigungen:
-
ACCESS_FINE_LOCATION
für einen genaueren Standort oderACCESS_COARSE_LOCATION
für einen weniger genauen Standort
-
- 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.
- Gleiche Notizen wie
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
beiPASSIVE_PROVIDER
Aktualisierungen der Google Play-Dienste zurück, wobeiPASSIVE_PROVIDER
die zugrunde liegenden StandortaktualisierungenPASSIVE_PROVIDER
- Funktioniert fast identisch mit dem
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:
Ü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 erfordertACCESS_FINE_LOCATION
.
(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.
Überprüfen Sie Ihren Code!
Sind Sie sicher, dass Sie den richtigen Hörer übergeben? Haben Sie diesen
BroadcastReceiver
oderIntentService
zu Ihrem ManifestIntentService
? Verwenden SiePendingIntent.getService()
für eineBroadcastReceiver
Klasse odergetBroadcast()
für eineIntentService
Klasse? Sind Sie sicher, dass Sie Ihren Listener nicht sofort nach der Abfrage an einer anderen Stelle in Ihrem Code abmelden?
Geräteeinstellungen überprüfen!
Stellen Sie natürlich sicher, dass Sie Standortdienste aktiviert haben.
Wenn Sie Netzwerkdienste verwenden, haben Sie "Scannen immer verfügbar" aktiviert? Haben Sie Ihren Standortmodus auf "Beste" ("Hohe Genauigkeit") oder "Batteriesparen" ("Nur Netzwerk") eingestellt?
Wenn Sie GPS verwenden, haben Sie im Standortmodus "Beste" ("Hohe Genauigkeit") oder "Nur Gerät" aktiviert?
Überprüfen Sie Ihren Code!
Ja, das ist zweimal hier. Haben Sie versucht, einen
LocationListener
anstelle einesPendingIntent
oder umgekehrt, um sicherzustellen, dass SieLocationManager
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?
Ü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();
}