2013-02-25 10 views
7

che voglio fare qualcosa di simile:aggiornamenti di posizione Android in un Servizio di

  • Quando la mia applicazione si avvia voglio avviare un servizio che dovrebbe controllare la mia posizione

  • Quando l'applicazione va a sfondo voglio arrestare il servizio

ho due problemi principali:

  1. Come posso rilevare che la mia applicazione passa allo sfondo? Ho diverse attività, e ho provato che nella mia MainActivity si è annullato onPause, ma la onPause viene anche chiamata quando avvio un'altra attività.

  2. Questo problema è più importante: come dovrebbe essere il mio servizio che controlla la mia posizione? Ho provato diversi approcci, ma senza successo.

Il mio servizio si presenta così e non funziona. Cosa dovrei cambiare per farlo funzionare?

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

onResume(), lasciare che il servizio ricerca Informazioni posizione e il metodo onPause() rimuovano la Posizione. – user2060383

+0

Desidero utilizzare la mia posizione in diverse attività, non solo nell'attività principale. Quindi non sarebbe saggio fermare il servizio in onPause, perché se viene avviata un'altra attività, viene chiamato onPause e io smetterei di ricevere gli aggiornamenti di posizione. – ffddani

+0

android.permission.ACCESS_COARSE_LOCATION android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_NETWORK_STATE hanno aggiunto questi Permission nel file manifest? –

risposta

4

Ciò contribuirà a farmi ridare ciò che il vostro requirment è ma non dimenticate di aggiungere l'autorizzazione ho aggiunto nel commento e anche non dimenticate di numero di servizio aggiunto nel file manifesto pezzo di codice presentato seguendo

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

Grazie per la tua ottima risposta. Ho solo bisogno di aggiungere il seguente codice al mio AndroidManifest.xml per poter avviare il servizio da un'attività: '' –

0

Prova questo codice .. Utilizzando questo si può trovare se la vostra applicazione è in primo piano o in background. Spero che questo ti possa aiutare.

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

Quali autorizzazioni sono necessarie per far funzionare questo codice? – ffddani

+0

ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION per il futuro codice di localizzazione niente di più, ricordati di aggiungere ogni servizio al tuo AndroidManifest – akuzma

+0

senza permessi .. basta usare il contesto che è .. e il foreground è un valore booleano .. ctx è Context .. usalo e lasciami conosci i tuoi commenti – itsrajesh4uguys

2
  1. Application non è un componente visiva in Android. È diviso in Attività, ognuna delle quali viene eseguita quando è visibile, in pausa e distrutta in altro modo. Pertanto, non esiste alcuna idea che l'intera applicazione vada in secondo piano, le attività sono sospese e riprese in base alla loro visibilità individuale e sono completamente indipendenti da altre attività in questa materia.

  2. Il servizio deve registrarsi con Location Manager nel suo onCreate(), annullare la registrazione dallo stesso nel suo onDestroy(). Nel suo onBind() restituisce un oggetto Messenger. E, in onLocationChanged() dovrebbe inviare un messaggio attraverso il suo Messenger condiviso. Non è necessario utilizzare START_STICKY perché non si desidera che il Servizio sia sempre in esecuzione.

  3. L'Attività (può essere qualsiasi attività in App) ha solo bisogno di chiamare bindService() nella sua onStart(), il servizio partirà se non è già, e attività otterrà un Messenger dal servizio. Inoltre, l'attività dovrebbe chiamare unbindService() dal suo onStop(). Il Servizio si fermerà automaticamente quando non vi è alcun legame con esso.

  4. Se avete bisogno di fare le cose al punto 3 a livello di App (Task), implementare la classe Application, e usare il suo onCreate() e onTerminate(). La classe dell'applicazione non viene messa in pausa o interrotta come un'attività.

+0

Come posso rilevare che la mia APPLICAZIONE va in background? Non ho mai detto di alcuna attività che va in background. non importa più, perché il mio primo problema è risolto – ffddani

+0

Non c'è nessun componente ** Visible Application ** in Android Se una delle attività è visibile, l'app è in esecuzione, altrimenti l'app viene interrotta e potrebbe essere anche dest royed. Comunque, puoi usare il punto 4. –

0

Okey, il mio primo problema è risolto utilizzando il codice di cui sopra in questo modo:

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

Ora, come posso fare il mio lavoro LocationService?

1

Ti suggerisco di utilizzare l'ultima posizione api fornita da google (compatibile anche con la versione 2.2).

ecco un esempio mostra come utilizzare questo: https://github.com/chenjishi/android_location_demo

quando la vostra applicazione per eseguire sfondo, è possibile chiamare Disconnetti per interrompere l'aggiornamento posizione.

Problemi correlati