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:
-
Correr en segundo plano sin interrupciones en la reinicialización de la aplicación y mantenerlo vivo tanto como sea posible sin ser asesinado (Esto se resuelve con la ayuda del comentario de Merlin abajo)
- Descubrimiento del servicio de red error de tutorial android: Servicio perdido, el teléfono se desactiva
- El servicio no se reinicia después de que "Clear Memory" + appWidget se bloquea
- Depuración de fallos de servicio
- Servicio de asignar un montón de memoria?
- Android detecta el estado táctil desde cualquier aplicación
-
En una nueva ubicación recibida, llame a un servicio web y envíe la ubicación de lectura
-
Tener una tarea repetitiva que se ejecuta cada 60 segundos y volver a enviar la última ubicación al servicio web. Esto ayudará en caso de que el usuario permanezca en la misma posición.
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?
- android - utiliza la cámara desde el servicio de fondo
- OnServiceConnected nunca llamado después del método bindService
- Cómo iniciar una tarea de fondo de larga ejecución en el servicio de Android
- Servicio con cola de prioridad en Android
- Envío de una notificación desde un servicio en Android
- El mejor enfoque para ejecutar el servicio en Android
- ¿Cómo actualizar un TextView en una actividad de un servicio en Android?
- Obtener: No se permite iniciar el servicio Intención ... sin permiso Proceso de servicio es malo
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
-
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.
-
Puede utilizar una sola clase LocationListener para escuchar la ubicación del GPS y la RED.
- Cuando obtiene la ubicación en el método onLocationChanged (), puede enviar esa ubicación utilizando un asynctask.
- 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(); } }
- ¿Cómo agregar funcionalidad al botón oficial Take Photo de los teléfonos Android?
- Android 3.0 Barra de Acción Buscar Ver