Servicio de Android y tareas repetitivas que se ejecutan en subprocesos

Estoy ejecutando un servicio en segundo plano que lee la ubicación de GPS / Red y necesita hacer lo siguiente:

Hay algunas cosas que he considerado y no estoy seguro si he entendido bien. El servicio se ejecuta en el mismo subproceso que la aplicación principal, por lo que enviar la ubicación al servidor en el mismo hilo que el subproceso de interfaz de usuario puede activar la interfaz de usuario congela y esto no es bueno. También no estoy seguro si los oyentes del GPS / red tienen sus propios hilos o utilizan el mismo hilo que la aplicación.

He aquí un código abreviado del servicio para aclarar las cosas:

public class GPSLoggerService extends Service { @Override public void onCreate() { locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); } @Override public int onStartCommand(Intent intent, int flags, int startId) { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 50, locationListenerNetwork); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, locationListenerGps); scheduleTaskExecutor = Executors.newScheduledThreadPool(5); scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { updateLocation(lastLocation); }, 60, 60, TimeUnit.SECONDS); return START_STICKY; } LocationListener locationListenerGps = new LocationListener() { @Override public void onLocationChanged(Location location) { updateLocation(location); } ... } LocationListener locationListenerNetwork = new LocationListener() { @Override public void onLocationChanged(Location location) { updateLocation(location); } ... } private void updateLocation(Location readLocation) { //web service call String response = WebServiceCalls.updateLocation(readLocation); //log data in a local Sqlite database saveLocation(readLocation) } 

Mi principal preocupación es cómo manejar la llamada updateLocation y tenerlo en un hilo separado del hilo principal de la aplicación. El scheduleTaskExecutor Creo que no es el camino a seguir. A veces, incluso después de llamar a stopService (), el servicio permanece activo, incluso si le digo al TaskExecutor que cierre ShutDown. No puedo encontrar otra explicación para que el servicio no es stoping. Así que para recapitular: Tengo que enviar la ubicación cada vez que los oyentes reciben una nueva ubicación y volver a enviar cada 60 segundos. También necesito poder parar el servicio rápidamente con la cancelación activa de los hilos.

¿Cómo me recomendaría que manejara mi caso?

Para evitar que su servicio destruya, puede iniciar su servicio como un servicio de primer plano .

Y después de obtener una ubicación del método onLocationChanged (), puede utilizar un asynctask para enviar una ubicación al servicio web para que no bloquee su interfaz de usuario.

Editar

  1. Puede establecer el tiempo mínimo y la distancia mínima recorrida en su método requestLocationUpdates . Por lo tanto, no creo que deba utilizar la tarea del planificador para enviar la ubicación al servidor. Según el argumento sobre el tiempo mínimo y la distancia mínima el gerente de localización comprobará la localización. Si hay una ubicación cambiada, llamará al método onLocationChanged () con la nueva ubicación. Ahora su solución sobre el usuario permanece en la misma posición. Usted puede cambiar algo de lógica al lado del servidor como si hay una diferencia de 1 hora entre dos ubicaciones sucesivas location1 y location2 significa que el usuario ha permanecido 1 hora en location1.

  2. Puede utilizar una sola clase LocationListener para escuchar la ubicación del GPS y la RED.

  3. Cuando obtiene la ubicación en el método onLocationChanged (), puede enviar esa ubicación utilizando un asynctask.
  4. Después de obtener la ubicación puede guardar esa ubicación en la preferencia o base de datos para comprobar el tiempo el proveedor de GPS y red que le envía la misma ubicación por lo que si va a realizar un seguimiento, entonces usted puede guardar su llamada webAPI y por lo que puede guardar parte de la batería.

Utilizaría un IntentService y usaría el AlarmManager para disparar intenciones.

La gran ventaja de esto es que no hay código de hilo para preocuparse, ya que hace su trabajo en el fondo

ACTUALIZAR

Otro enfoque interesante puede encontrarse en https://stackoverflow.com/a/7709140/808940

  • El servicio ejecuta el mismo proceso que la aplicación principal, no el subproceso. Además, si desea ejecutar el servicio en otro proceso, puede utilizar la etiqueta android: process .

  • No estoy seguro de por qué desea llamar a WebService cada 60 segundos, porque 60 segundos es demasiado menor. También debe omitir la llamada a WebService cuando la ubicación no ha cambiado, ya que requiere una comunicación de red y es una operación costosa.

  • No hay necesidad de utilizar a los Ejecutores. Debe mantener el número de subprocesos lo menos posible. Para realizar una tarea en un intervalo determinado, utilice AlarmManager para entregar la intención en un momento determinado. Compruebe el método setRepeating () para configurar la alarma.

  • Otra cosa es, usted debe tratar de evitar hacer cualquier tarea en Listener. Porque hay un tiempo de espera de 10 segundos que el sistema permite antes de considerar que el receptor / oyente sea bloqueado y que un candidato sea asesinado. Debe utilizar el controlador para realizar tareas en el subproceso de fondo (es decir, cada vez que reciba la actualización del oyente, agregue un mensaje a la cola del manejador y se seleccionará cuando el hilo del procesador esté libre).

Debe utilizar AsynchTask:

 public class RefreshTask extends AsyncTask<Integer, Void, Integer> { /** * The system calls this to perform work in a worker thread and delivers * it the parameters given to AsyncTask.execute() */ public RefreshTask() { } protected Integer doInBackground(Integer... millis) { try{ int waitTime = 0; while(waitTime<60000){ Thread.sleep(100); waitTime += 100; } //update location here }catch(InterruptedException e){ } return 1; } /** * The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Integer result) { new RefreshTask.execute(); } } 
  • Inicio del servicio de fondo cuando se enciende Android
  • ¿Cómo mantener un servicio con los oyentes vivo después de desatar en Android?
  • ¿Puede existir un servicio de fondo sin su aplicación principal?
  • Android - Ejecutar en segundo plano - Service vs. standard java class
  • MVC en Android: ¿Aplicación o servicio para actualizaciones asíncronas?
  • En Android: ¿Cómo llamar a la función de la actividad de un servicio?
  • Lanzar una excepción personalizada de un servicio a una actividad
  • Una forma más eficiente de actualizar la interfaz de usuario del servicio que las intenciones?
  • Android - ¿Cómo decidir si ejecutar un servicio en un proceso separado?
  • Servicio de Android - URL de ping
  • ResultReceiver no sobrevive a la rotación de la pantalla
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.