2013-02-25 15 views
7

Chcę zrobić coś takiego:Android aktualizacje lokalizacji w usłudze

  • Kiedy moi uruchamiany Chcę uruchomić usługę, która powinna sprawdzić, czy moje położenie

  • Gdy aplikacja przechodzi do tła Chcę zatrzymać usługę

mam dwa główne problemy:

  1. Jak wykryć, że moja aplikacja przechodzi do tła? Nienawidzę kilku działań i próbowałem tego w moim MainActivity nadpisując onPause, ale funkcja onPause jest również wywoływana, gdy zaczynam inną aktywność.

  2. Ten problem jest ważniejszy: Jak powinna wyglądać moja usługa sprawdzająca moją lokalizację? Próbowałem kilku podejść, ale bez powodzenia.

Moja usługa wygląda tak, i to nie działa. Co powinienem zmienić, aby działało?

package com.pivoscore.service; 

import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.os.IBinder; 

public class LocationService extends Service { 

    private LocationListener locationListener; 

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

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

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); 
     this.locationListener = new MyLocationListener(); 
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, this.locationListener); 
    } 

    private static class MyLocationListener implements LocationListener { 

     @Override 
     public void onLocationChanged(final Location location) { 
     } 

     @Override 
     public void onProviderDisabled(final String provider) { 
     } 

     @Override 
     public void onProviderEnabled(final String provider) { 
     } 

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

    } 

} 
+0

Metoda onResume(), umożliwia wyszukiwanie usługi Informacje o lokalizacji i metodę onPause() usuwa lokalizację. – user2060383

+0

Chcę używać mojej lokalizacji w kilku działaniach, nie tylko w głównej działalności. Więc nie byłoby rozsądnie zatrzymywać usługi w trybie pauzy, ponieważ jeśli inna czynność zostanie osiągnięta, zostanie wywołana opcja onPauza, a ja przestanę pobierać aktualizacje lokalizacji. – ffddani

+0

android.permission.ACCESS_COARSE_LOCATION android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_NETWORK_STATE masz dodany te Permission w pliku manifestu? –

Odpowiedz

4

Pomoże to exaclty co twój requirment jest ale nie zapomnij dodać pozwolenie Dodałem w komentarzu a także nie zapomnij dodanym znacznikiem serwisowym w pliku manifestu Kod Snipet jest obserwuję

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, 0, 0, listener); 
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 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);   
      /*final Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());   
      String Text = ""; 
      try { 
       List<Address> addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);     
       Text = "My current location is: "+addresses.get(0).getAddressLine(0); 

      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       Text = "My current location is: " +"Latitude = " + loc.getLatitude() + ", Longitude = " + loc.getLongitude(); 
      } 
      */ 
      //Toast.makeText(getApplicationContext(), "Location polled to server", Toast.LENGTH_SHORT).show(); 
     }        
    } 

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

    } 

} 
+0

Dzięki za wspaniałą odpowiedź. Potrzebowałem tylko dodać następujący kod do mojego AndroidManifest.xml, aby móc uruchomić usługę z działania: '' –

0

Spróbuj ten kod .. Za pomocą tego można znaleźć, czy aplikacja jest na pierwszym planie lub w tle. Mam nadzieję, że to ci pomoże.

try { 
    foreground = new ForegroundCheckTask().execute(ctx).get(); 
} 

====================================== 


class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> { 

@Override 
protected Boolean doInBackground(Context... params) { 
    final Context context = params[0].getApplicationContext(); 
    return isAppOnForeground(context); 
} 

private boolean isAppOnForeground(Context context) { 
    ActivityManager activityManager = (ActivityManager) context 
      .getSystemService(Context.ACTIVITY_SERVICE); 
    List<RunningAppProcessInfo> appProcesses = activityManager 
      .getRunningAppProcesses(); 
    if (appProcesses == null) { 
     return false; 
    } 
    final String packageName = context.getPackageName(); 


    String activePackageName = activityManager.getRunningTasks(1).get(0).topActivity.getPackageName(); 
    if (activePackageName.equals(packageName)) { 
     return true; 
    } 
    else{ 
     return false; 
    } 


} 

} 
+0

Jakie uprawnienia są potrzebne, aby ten kod działał? – ffddani

+0

ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION dla przyszłego kodu lokalizacji nic więcej, tylko pamiętaj, aby dodać każdą usługę do AndroidManifest – akuzma

+0

bez uprawnień .. po prostu użyj kontekstu, który jest to ... a pierwszy plan jest wartością boolowską .. ctx to Kontekst .. użyj go i pozwól mi poznaj swoje komentarze. – itsrajesh4uguys

2
  1. Aplikacja nie jest wizualnym elementem w Androidzie. Jest podzielony na działania, każdy z nich działa, gdy jest widoczny, wstrzymany i zniszczony w inny sposób. Tak więc nie ma pojęcia, że ​​cała Aplikacja przechodzi w tło, Działania są wstrzymywane i wznawiane na podstawie ich indywidualnej widoczności i są całkowicie niezależne od innych Działalności w tym zakresie.

  2. Twoja firma zarejestruje się w Menedżerze lokalizacji pod numerem onCreate(), wyrejestrując go z tego samego w swojej onDestroy(). W swoim onBind() zwraca obiekt Messenger. I, w onLocationChanged() powinien wysłać wiadomość za pośrednictwem udostępnionego Messenger. Nie musisz używać START_STICKY, ponieważ nie chcesz, aby usługa działała cały czas.

  3. Activity (może być żadnej aktywności w aplikacji) po prostu potrzebuje zadzwonić bindService() w swojej onStart(), Usługa zostanie uruchomiony, jeśli nie już, i aktywny dostanie Messenger z eksploatacji. Aktywność powinna również wywoływać numer unbindService() z jego numeru onStop(). Usługa zatrzyma się automatycznie, gdy nic nie będzie z nią związane.

  4. Jeśli trzeba robić rzeczy w pkt 3 w (Zadanie) poziomu aplikacji, zaimplementować klasę Application i wykorzystać swoje onCreate() i onTerminate(). Klasa aplikacji nie jest wstrzymana ani zatrzymana jak działanie.

+0

Jak mogę wykryć, że moja aplikacja przechodzi w tło? Nigdy nie powiedziałem, że jakakolwiek aktywność będzie prowadzona w tle. nie ma to już znaczenia, ponieważ mój pierwszy problem został rozwiązany: – ffddani

+0

W systemie Android nie ma składnika ** Widoczna aplikacja **. Jeśli widoczne jest dowolne działanie, aplikacja działa, w przeciwnym razie aplikacja została zatrzymana i może być nawet dest. Royed. Mimo to możesz użyć punktu 4. –

0

Okey, mój pierwszy problem jest rozwiązany przy użyciu kodu powyżej tak:

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

    final Intent locationServiceIntent = new Intent(this, LocationService.class); 
    this.startService(locationServiceIntent); 
} 

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

    if (!Utils.isAppInForeground(this)) { 
     final Intent locationServiceIntent = new Intent(this, LocationService.class); 
     this.stopService(locationServiceIntent); 
    } 
} 

Teraz jaki sposób można uczynić moją pracę LocationService?

1

Sugeruję, abyś użył najnowszej api aplikacji dostarczonej przez google (również kompatybilnej z wersją 2.2).

tutaj jest przykład pokazuje, jak używać, że: https://github.com/chenjishi/android_location_demo

gdy aplikacja biec do tła, można zadzwonić odłączyć, aby zatrzymać aktualizację lokalizacji.

Powiązane problemy