2013-01-23 8 views
63

Ich erstelle einen Hintergrunddienst, der in einem eigenen Prozess ausgeführt wird. Es sollte mir erlauben zu hören, wenn sich der Gerätestandort geändert hat. Ich sollte in der Lage sein, Kriterien wie die bewegte Distanz zu ändern, bevor ich die Benutzeroberfläche benachrichtige.Hintergrunddienst mit Standortlistener in Android

Wie kann ich das gleiche tun? Ich habe ein wenig Wissen über Service und LocationListener Implementierungen. Alle Tutorials rund um das Netz wären willkommen.

Ich habe eine back-link von Stack-Überlauf, aber ich habe nicht viel davon verstanden.

+2

prüft diese Blog-Post aus: http://android-developers.blogspot.ro/2011/06/deep-dive-into-location.html – Felix

+0

neueste GoogleApiClient Methode Siehe http : //stackoverflow.com/a/41981246/3496570 – Nepster

Antwort

97

Zuerst müssen Sie eine Service erstellen. Erstellen Sie in dieser Service eine Klasse, die LocationListener erweitert. Verwenden Sie hierzu den folgenden Code-Schnipsel Service:

public class LocationService extends Service 
{ 
     public static final String BROADCAST_ACTION = "Hello World"; 
     private static final int TWO_MINUTES = 1000 * 60 * 2; 
     public LocationManager locationManager; 
     public MyLocationListener listener; 
     public Location previousBestLocation = null; 

     Intent intent; 
     int counter = 0; 

    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 
     intent = new Intent(BROADCAST_ACTION);  
    } 

    @Override 
    public void onStart(Intent intent, int startId) 
    {  
     locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
     listener = new MyLocationListener();   
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener); 
     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener); 
    } 

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

    protected boolean isBetterLocation(Location location, Location currentBestLocation) { 
     if (currentBestLocation == null) { 
      // A new location is always better than no location 
      return true; 
     } 

     // Check whether the new location fix is newer or older 
     long timeDelta = location.getTime() - currentBestLocation.getTime(); 
     boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; 
     boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 
     boolean isNewer = timeDelta > 0; 

     // If it's been more than two minutes since the current location, use the new location 
     // because the user has likely moved 
     if (isSignificantlyNewer) { 
      return true; 
     // If the new location is more than two minutes older, it must be worse 
     } else if (isSignificantlyOlder) { 
      return false; 
     } 

     // Check whether the new location fix is more or less accurate 
     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
     boolean isLessAccurate = accuracyDelta > 0; 
     boolean isMoreAccurate = accuracyDelta < 0; 
     boolean isSignificantlyLessAccurate = accuracyDelta > 200; 

     // Check if the old and new location are from the same provider 
     boolean isFromSameProvider = isSameProvider(location.getProvider(), 
       currentBestLocation.getProvider()); 

     // Determine location quality using a combination of timeliness and accuracy 
     if (isMoreAccurate) { 
      return true; 
     } else if (isNewer && !isLessAccurate) { 
      return true; 
     } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
      return true; 
     } 
     return false; 
    } 



/** Checks whether two providers are the same */ 
    private boolean isSameProvider(String provider1, String provider2) { 
     if (provider1 == null) { 
      return provider2 == null; 
     } 
     return provider1.equals(provider2); 
    } 



@Override 
    public void onDestroy() {  
     // handler.removeCallbacks(sendUpdatesToUI);  
     super.onDestroy(); 
     Log.v("STOP_SERVICE", "DONE"); 
     locationManager.removeUpdates(listener);   
    } 

    public static Thread performOnBackgroundThread(final Runnable runnable) { 
     final Thread t = new Thread() { 
      @Override 
      public void run() { 
       try { 
        runnable.run(); 
       } finally { 

       } 
      } 
     }; 
     t.start(); 
     return t; 
    } 




public class MyLocationListener implements LocationListener 
    { 

     public void onLocationChanged(final Location loc) 
     { 
      Log.i("**************************************", "Location changed"); 
      if(isBetterLocation(loc, previousBestLocation)) { 
       loc.getLatitude(); 
       loc.getLongitude();    
       intent.putExtra("Latitude", loc.getLatitude()); 
       intent.putExtra("Longitude", loc.getLongitude());  
       intent.putExtra("Provider", loc.getProvider());     
       sendBroadcast(intent);   

      }        
     } 

     public void onProviderDisabled(String provider) 
     { 
      Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT).show(); 
     } 


     public void onProviderEnabled(String provider) 
     { 
      Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show(); 
     } 


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

     } 

    } 
} 

Dieses Service irgendwo in Ihrem Projekt, wie Sie wollen! :)

+0

funktioniert perfekt. –

+4

Hinweis: Dieser Code sieht so aus, als könnte er aus einem [GPL-Projekt] stammen (https://code.google.com/p/chararound-dto/source/browse/chararound-client/src/com/service) /chararound/listener/MyLocationListener.java?r=101) (oder möglicherweise von [this] (https://code.google.com/p/apk/source/browse/trunk/src/com/vouov/ listener/MyLocationListener.java? r = 5) MIT lizensiertes Projekt.Wer kennt den Lizenzstatus des obigen Codes? – Inactivist

+0

@Nilanchala wenn das für Sie funktioniert, dann markieren Sie es richtig, damit ich anderen helfen kann, die ein solches Problem haben –

11

Ich weiß, dass ich diese Antwort wenig spät posten, aber ich fühlte, dass es wert ist, Googles Fuse Location Provider Service zu verwenden, um den aktuellen Standort zu erhalten.

Hauptmerkmale dieser api sind:

1.Simple APIs: Hier können Sie Ihre Genauigkeit sowie den Stromverbrauch zu wählen.

2. Sofort verfügbar: Gibt Ihren Apps sofortigen Zugriff auf den besten und aktuellsten Standort.

3.Power-Effizienz: Es wählt den effizienteste Weg, um die Lage mit weniger Stromverbrauch

4.Versatility zu erhalten: erfüllt eine Vielzahl von Bedürfnissen, von Vordergrund Anwendungen, die hochgenaue müssen Standort zu Hintergrund verwendet, der regelmäßige Standortaktualisierungen mit vernachlässigbarer Auswirkung auf die Stromversorgung benötigt.

Es ist flexibel in der Aktualisierung in Standort auch. Wenn Sie den aktuellen Standort nur beim Start Ihrer App möchten, können Sie die Methode getLastLocation(GoogleApiClient) verwenden.

Wenn Sie Ihren Standort aktualisieren möchten kontinuierlich, dann können Sie requestLocationUpdates(GoogleApiClient,LocationRequest, LocationListener)

verwenden Sie können einen sehr schönen Blog über Sicherung Lage here und google doc für Sicherung Standort finden können auch here finden.

aktualisiert

Laut Entwicklern docs von Android OS beginnen sie neue Grenzen im Hintergrund Standort hinzugefügt haben.

Wenn Ihre App im Hintergrund läuft, das Ortungssystem Service berechnet einen neuen Standort für Ihre App nur ein paar Mal pro Stunde. Diese ist der Fall, auch wenn Ihre App häufiger Standort Updates anfordert. Wenn Ihre App jedoch im Vordergrund ausgeführt wird, gibt es keine Änderung der Standort-Abtastraten im Vergleich zu Android 7.1.1 (API-Ebene 25).

+1

Ich denke, Sie haben recht, aber einige Custom Rom haben den Google Play-Dienst entfernt, so dass Sie den Sicherungsstandortanbieter nicht verwenden können. – Chen

+1

Wenn Sie nur ungefähr wissen möchten, wo Sie sich zu einer bestimmten Zeit befinden oder für weniger genaues Tracking, ist 'FusedLocationProvider' in Ordnung, aber für Anwendungen, die eine hohe Genauigkeit erfordern, ist es einfach nicht gut genug. – StuStirling

+2

Eine Lösung für diese Custom Roms [LOST] (https://github.com/mapzen/LOST) aus Mapzen. Bietet die gleiche Funktionalität mit FusedLocationProviderAPI von Google, ohne sich bei Google Play Service registrieren zu müssen. –

1

Sehr einfach keine Notwendigkeit Klasse erzeugen erstreckt Location 1- Variable

private LocationManager mLocationManager; 
private LocationListener mLocationListener; 
private static double currentLat =0; 
private static double currentLon =0; 

2- onStartService()

@Override public void onStartService() { 
    addListenerLocation(); 
} 

3- Method addListenerLocation()

private void addListenerLocation() { 
    mLocationManager = (LocationManager) 
      getSystemService(Context.LOCATION_SERVICE); 
    mLocationListener = new LocationListener() { 
     @Override 
     public void onLocationChanged(Location location) { 
      currentLat = location.getLatitude(); 
      currentLon = location.getLongitude(); 

      Toast.makeText(getBaseContext(),currentLat+"-"+currentLon, Toast.LENGTH_SHORT).show(); 

     } 

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

     @Override 
     public void onProviderEnabled(String provider) { 
      Location lastKnownLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      if(lastKnownLocation!=null){ 
       currentLat = lastKnownLocation.getLatitude(); 
       currentLon = lastKnownLocation.getLongitude(); 
      } 

     } 

     @Override 
     public void onProviderDisabled(String provider) { 
     } 
    }; 
    mLocationManager.requestLocationUpdates(
      LocationManager.GPS_PROVIDER, 500, 10, mLocationListener); 
} 

4- onDestroy()

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    mLocationManager.removeUpdates(mLocationListener); 
} 
4

Hintergrund Standortdienst und ich werde auch nach Kill-App starten.

MainActivity.java

public class MainActivity extends AppCompatActivity { 
    AlarmManager alarmManager; 
    Button stop; 
    PendingIntent pendingIntent; 

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

     if (alarmManager == null) { 
      alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
      Intent intent = new Intent(this, AlarmReceive.class); 
      pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); 
      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 30000, 
        pendingIntent); 
     } 
    } 
} 

BookingTrackingService.java

public class BookingTrackingService extends Service implements LocationListener { 

    private static final String TAG = "BookingTrackingService"; 
    private Context context; 
    boolean isGPSEnable = false; 
    boolean isNetworkEnable = false; 
    double latitude, longitude; 
    LocationManager locationManager; 
    Location location; 
    private Handler mHandler = new Handler(); 
    private Timer mTimer = null; 
    long notify_interval = 30000; 

    public double track_lat = 0.0; 
    public double track_lng = 0.0; 
    public static String str_receiver = "servicetutorial.service.receiver"; 
    Intent intent; 

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

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     mTimer = new Timer(); 
     mTimer.schedule(new TimerTaskToGetLocation(), 5, notify_interval); 
     intent = new Intent(str_receiver); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     this.context = this; 


     return START_NOT_STICKY; 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     Log.e(TAG, "onDestroy <<"); 
     if (mTimer != null) { 
      mTimer.cancel(); 
     } 
    } 

    private void trackLocation() { 
     Log.e(TAG, "trackLocation"); 
     String TAG_TRACK_LOCATION = "trackLocation"; 
     Map<String, String> params = new HashMap<>(); 
     params.put("latitude", "" + track_lat); 
     params.put("longitude", "" + track_lng); 

     Log.e(TAG, "param_track_location >> " + params.toString()); 

     stopSelf(); 
     mTimer.cancel(); 

    } 

    @Override 
    public void onLocationChanged(Location location) { 

    } 

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

    } 

    @Override 
    public void onProviderEnabled(String provider) { 

    } 

    @Override 
    public void onProviderDisabled(String provider) { 

    } 

    /******************************/ 

    private void fn_getlocation() { 
     locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE); 
     isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
     isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 

     if (!isGPSEnable && !isNetworkEnable) { 
      Log.e(TAG, "CAN'T GET LOCATION"); 
      stopSelf(); 
     } else { 
      if (isNetworkEnable) { 
       location = null; 
       locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this); 
       if (locationManager != null) { 
        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
        if (location != null) { 

         Log.e(TAG, "isNetworkEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + ""); 
         latitude = location.getLatitude(); 
         longitude = location.getLongitude(); 
         track_lat = latitude; 
         track_lng = longitude; 
//      fn_update(location); 
        } 
       } 
      } 

      if (isGPSEnable) { 
       location = null; 
       locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this); 
       if (locationManager != null) { 
        location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
        if (location != null) { 
         Log.e(TAG, "isGPSEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + ""); 
         latitude = location.getLatitude(); 
         longitude = location.getLongitude(); 
         track_lat = latitude; 
         track_lng = longitude; 
//      fn_update(location); 
        } 
       } 
      } 

      Log.e(TAG, "START SERVICE"); 
      trackLocation(); 

     } 
    } 

    private class TimerTaskToGetLocation extends TimerTask { 
     @Override 
     public void run() { 

      mHandler.post(new Runnable() { 
       @Override 
       public void run() { 
        fn_getlocation(); 
       } 
      }); 

     } 
    } 

// private void fn_update(Location location) { 
// 
//  intent.putExtra("latutide", location.getLatitude() + ""); 
//  intent.putExtra("longitude", location.getLongitude() + ""); 
//  sendBroadcast(intent); 
// } 
} 

AlarmReceive.java (BroadcastReceiver)

public class AlarmReceive extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.e("Service_call_" , "You are in AlarmReceive class."); 
     Intent background = new Intent(context, BookingTrackingService.class); 
//  Intent background = new Intent(context, GoogleService.class); 
     Log.e("AlarmReceive ","testing called broadcast called"); 
     context.startService(background); 
    } 
} 

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

<service 
      android:name=".ServiceAndBroadcast.BookingTrackingService" 
      android:enabled="true" /> 

     <receiver 
      android:name=".ServiceAndBroadcast.AlarmReceive" 
      android:exported="false"> 
      <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED" /> 
      </intent-filter> 
     </receiver> 
+0

'if (isNetworkEnable) {' könnte es sein 'if (! IsNetworkEnable) {' fehlt NICHT in anderen Fällen. ;) –

+1

Außerdem muss die Verfügbarkeit der Berechtigungen überprüft werden. 'if (ActivityCompat.checkSelfPermission (diese, Manifest.permission.ACCESS_FINE_LOCATION)! = PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (dies, Manifest.permission.ACCESS_COARSE_LOCATION)! = PackageManager.PERMISSION_GRANTED) {return;}' –

Verwandte Themen