stopservice servicio saber intent implement how esta ejemplo create corriendo como android android-service

saber - Servicio de fondo que muere en Android



service android ejemplo (9)

Hemos desarrollado una aplicación de Android que implica un servicio en segundo plano. Para implementar este servicio en segundo plano hemos utilizado IntentService . Queremos que la aplicación sondee el servidor cada 60 seconds . Por lo tanto, en IntentService , el servidor se sondea en un ciclo while. Al final del ciclo while hemos utilizado Thread.sleep(60000) para que la siguiente iteración comience solo después de 60 segundos.
Pero en el Logcat , veo que a veces le toma más de 5 minutos a la aplicación despertarse (salir de ese modo de suspensión y comenzar la siguiente iteración). Nunca es 1 minute como queremos que sea.

¿Cuál es la razón para esto? ¿Deben implementarse los Servicios en segundo plano de una manera diferente?

Problema 2

Android mata este proceso en segundo plano (servicio intencionado) después de algún tiempo. No puedo decir exactamente cuándo. Pero a veces son horas y, a veces, días antes de que el servicio en segundo plano muera. Le agradecería que me dijera la razón de esto. Porque los Servicios no están destinados a ser asesinados. Están destinados a ejecutarse en segundo plano siempre que lo deseemos.

Código:

@Override protected void onHandleIntent(Intent intent) { boolean temp=true; while(temp==true) { try { //connect to the server //get the data and store it in the sqlite data base } catch(Exception e) { Log.v("Exception", "in while loop : "+e.toString()); } //Sleep for 60 seconds Log.v("Sleeping", "Sleeping"); Thread.sleep(60000); Log.v("Woke up", "Woke up"); //After this a value is extracted from a table final Cursor cur=db.query("run_in_bg", null, null, null, null, null, null); cur.moveToLast(); String present_value=cur.getString(0); if(present_value==null) { //Do nothing, let the while loop continue } else if( present_value.equals("false") || present_value.equals("False") ) { //break out of the while loop db.close(); temp=false; Log.v("run_in_bg", "false"); Log.v("run_in_bg", "exiting while loop"); break; } } }

Pero cada vez que se mata el servicio, sucede cuando el proceso está dormido. El último registro dice: Sleeping : Sleeping . ¿Por qué se mata el servicio?


Android es bastante bueno para matar servicios de larga duración. He encontrado que WakefulIntentService de CommonsWare es útil en mi aplicación: https://github.com/commonsguy/cwac-wakeful

Le permite especificar un intervalo de tiempo mientras intenta hacerlo durmiendo.


El principal problema es que no podemos decir

Los servicios no están destinados a ser asesinados. Están destinados a ejecutarse en segundo plano siempre que lo deseemos.

Básicamente, eso no es verdad. El sistema aún puede terminar el servicio en poca memoria y posiblemente en otras situaciones. Hay 2 formas de superar esto:

  1. Si está implementando el servicio, anule onStartCommand() y devuelva START_STICKY como resultado. Le indicará al sistema que incluso si desea cancelar su servicio debido a la poca memoria, debería volver a crearlo tan pronto como la memoria vuelva a ser normal.
  2. Si no está seguro de que la primera aproximación funcionará, tendrá que utilizar AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html . Ese es un servicio del sistema, que ejecutará acciones cuando usted lo indique, por ejemplo, periódicamente. Eso asegurará que si su servicio terminará, o incluso todo el proceso morirá (por ejemplo, con el cierre forzado), AlarmManager lo reiniciará al 100%.

Buena suerte


Los servicios son asesinados. Al igual que la aplicación se mata. Es filosofía de Android que puedes matarte en cualquier momento.

Deberías, como otros escribieron, no asumir que tu fondo funciona para siempre.

Pero puede utilizar un servicio de tierra para reducir drásticamente la posibilidad de que lo maten / reinicien. Tenga en cuenta que esto obliga a una notificación que siempre está visible. Por ejemplo, reproductores de música, aplicaciones vpn y sportstracker usan esta API.


Para el problema 1, de Java vainilla, Thread.Sleep() está garantizado para reactivar el hilo después de que el temporizador haya expirado, pero no exactamente después de que haya expirado, puede ser más tarde dependiendo principalmente de los estados de otros hilos, prioridad, etc. ; así que si duermes tu hilo un segundo, dormirá al menos un segundo, pero puede ser 10 dependiendo de muchos factores, no soy muy versado en el desarrollo de Android, pero estoy bastante seguro de que es la misma situación .

Para el problema 2, los servicios pueden ser eliminados cuando la memoria baja o manualmente por el usuario, por lo que otros han señalado probablemente usando AlarmManager para reiniciar su servicio después de un cierto tiempo lo ayudará a tenerlo funcionando todo el tiempo.



Una mejor solución sería hacer que un AlarmManager suene cada 60 segundos. Este AlarmManager luego inicia el servicio que sondea el servidor, luego el servicio inicia un nuevo AlarmManager, es una solución recursiva que funciona bastante bien.

Esta solución será más confiable ya que no tiene la amenaza de que el sistema operativo Android mate su servicio que se cierne sobre usted. Según la API: el Administrador de alarmas está diseñado para casos en los que desee que su código de aplicación se ejecute en un momento específico, incluso si su aplicación no se está ejecutando actualmente.

En su UI / actividad principal, etc., configure este temporizador para que se apague en 60 segundos:

long ct = System.currentTimeMillis(); //get current time AlarmManager mgr=(AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE); Intent i= new Intent(getApplicationContext(), yourservice.class); PendingIntent pi=PendingIntent.getService(getApplicationContext(), 0, i, 0); mgr.set(AlarmManager.RTC_WAKEUP, ct + 60000 , pi); //60 seconds is 60000 milliseconds

En yourservice.class puedes tener esto, comprueba el estado de la conexión, si es bueno establece el temporizador para que se apague en otros 60 segundos:

public class yourservice extends IntentService { public yourservice() { //needs this constructor super("server checker"); } @Override protected void onHandleIntent(Intent intent) { WifiManager wificheck = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); if(check for a certain condition your app needs etc){ //could check connection state here and stop if needed etc stopSelf(); //stop service } else{ //poll the server again in 60 seconds long ct = System.currentTimeMillis(); AlarmManager mgr=(AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE); Intent i= new Intent(getApplicationContext(), yourservice.class); PendingIntent pi=PendingIntent.getService(getApplicationContext(), 0, i, 0); mgr.set(AlarmManager.RTC_WAKEUP, ct + 60000 , pi); stopSelf(); //stop service since its no longer needed and new alarm is set } } }


IntentService no está diseñado para seguir ejecutándose en un bucle while. La idea es reaccionar ante una Intent , hacer un procesamiento y detener el servicio una vez hecho.

Eso no significa que no esté funcionando y no puedo decirle por qué ve demoras tan largas, pero la solución más limpia es usar alguna fuente externa para pinchar el servicio periódicamente. Además de los métodos Java vainilla, también puedes echar un vistazo al http://developer.android.com/reference/android/app/AlarmManager.html o un Handler como se menciona en la documentación de AlarmManager .

El modo Handler funcionaría así.

public class TriggerActivity extends Activity implements Handler.Callback { // repeat task every 60 seconds private static final long REPEAT_TIME = 60 * 1000; // define a message id private static final int MSG_REPEAT = 42; private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new Handler(this); } @Override protected void onStart() { super.onStart(); // start cycle immediately mHandler.sendEmptyMessage(MSG_REPEAT); } @Override protected void onStop() { super.onStop(); // stop cycle mHandler.removeMessages(MSG_REPEAT); } @Override protected void onDestroy() { super.onDestroy(); mHandler = null; } @Override public boolean handleMessage(Message msg) { // enqueue next cycle mHandler.sendEmptyMessageDelayed(MSG_REPEAT, REPEAT_TIME); // then trigger something triggerAction(); return true; } private void triggerAction() { // trigger the service Intent serviceIntent = new Intent(this, MyService.class); serviceIntent.setAction("com.test.intent.OPTIONAL_ACTION"); startService(serviceIntent); } }

Una Activity simple (que podría ampliarse para tener esa funcionalidad en todas sus actividades) que se envía un Message todo el tiempo mientras se está ejecutando (aquí entre onStart y onStop )


IntentService que debería usar un Service lugar de un Service de IntentService pero si desea usar un servicio de IntentService y hacer que se ejecute cada 60 segundos, debe usar el AlarmManager lugar de simplemente decirle al Thread que se IntentService dormido. IntentService quiere parar, dejarlo y AlarmManager que AlarmManager lo AlarmManager cuando debería ejecutarse de nuevo.


It could be probably for two reasons..

  1. O bien el ciclo while crea un problema, hace que el controlador funcione hasta temp==true
  2. A esto se le agregan hilos, lo que crea long delays hasta 6 seconds . En el caso, el sistema está trabajando para una gran base de datos, creando long delays entre cada consulta se agregará a la memoria del sistema. Cuando el uso de la memoria para la aplicación se vuelve tan grande que la system memory gets low del system memory gets low , el sistema debe terminate the process .

    Solución para el problema ...

  3. Puede reemplazar arriba con Alarm Manager para revocar los servicios del sistema después de un intervalo de tiempo particular usando Alarm Manager.

  4. Además, para recuperar la intención después de que el sistema recupere la aplicación de la finalización, debe usar START_REDELIVER_INTENT . Es para recuperar su último intento de trabajo después de que finalice la aplicación. para su uso, estudie https://developer.android.com/reference/android/app/Service.html#START_REDELIVER_INTENT