Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Antecedentes El servicio se mata en android

Hemos desarrollado una aplicación para Android que implica un servicio en segundo plano. Para implementar este servicio de fondo hemos utilizado IntentService . Queremos que la aplicación examine el servidor cada 60 seconds . Así que en IntentService , el servidor se consulta en un bucle while. Al final del bucle while hemos utilizado Thread.sleep(60000) para que la siguiente iteración comience sólo después de 60 segundos.
Pero en el Logcat , veo que a veces toma la aplicación más de 5 minutos para despertar (salir de ese sueño e iniciar la siguiente iteración). Nunca es 1 minute como queremos que sea.

¿Cuál es la razón para esto? ¿Deberían implementarse los servicios de fondo de una manera diferente?

Problema2

Android mata este proceso de fondo (servicio de intenciones) después de algún tiempo. No puedo decir exactamente cuándo. Pero a veces sus horas ya veces días antes de que el servicio de fondo se mata. 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 correr en el fondo, siempre y cuando lo queremos.

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 cuando el servicio es asesinado, ocurre cuando el proceso está dormido. El último registro lee – Sleeping : Sleeping . ¿Por qué el servicio es asesinado?

  • El servicio USSD no funciona
  • Continuar el servicio incluso si la aplicación se ha eliminado de la aplicación Reciente.
  • Android: ¿Cómo solucionar la falla de la conexión de la API de Google desde un servicio?
  • ¿Cómo puedo llamar a startIntentSenderForResult en el servicio correctamente?
  • ¿Cómo funcionan las aplicaciones de Android, como Facebook, WhatsApp, en primer plano sin notificación?
  • Llamar setVolumeControlStream desde un servicio
  • No se puede iniciar el servicio Intención: no se encuentra
  • Implementación de un grupo de subprocesos dentro de un servicio
  • 9 Solutions collect form web for “Antecedentes El servicio se mata en android”

    El principal problema es que no podemos decir

    Los servicios no están destinados a ser asesinados. Están destinados a correr en el fondo, siempre y cuando lo queremos.

    Básicamente, eso no es cierto. El sistema todavía puede terminar el servicio en la memoria baja y posiblemente otras situaciones. Hay dos maneras de superar esto:

    1. Si está implementando el servicio, onStartCommand() y devuelva START_STICKY como resultado. Se le dirá al sistema que incluso si quiere matar a su servicio debido a la baja memoria, debe volver a crear tan pronto como la memoria volverá a la normalidad.
    2. Si no está seguro de que la primera aproximación funcionará – usted tendrá que usar AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html . Es un servicio del sistema, que ejecutará acciones cuando lo digas, por ejemplo periódicamente. Eso asegurará que si su servicio será terminado, o incluso todo el proceso morirá (por ejemplo, con el cierre de la fuerza) – será reiniciado al 100% por AlarmManager.

    Buena suerte

    Puede utilizar ScheduledExecutorService diseñado específicamente para tal propósito.

    No utilice Temporizadores, como se demuestra en "Concurrencia de Java en la Práctica" pueden ser muy inexactos.

    IntentService no pretende seguir ejecutándose en un bucle while. La idea es reaccionar a una Intent , hacer algún procesamiento y detener el servicio una vez hecho.

    Eso no significa que no está funcionando y no puedo decirte por qué ves tan largos retrasos, pero la solución más limpia es usar alguna fuente externa para empujar el servicio periódicamente. Además de los métodos Java de vainilla, también puedes echar un vistazo a AlarmManager o Handler como se menciona en la documentación de AlarmManager .

    La manera de Handler funcionaría de esta manera

     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 sencilla (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 )

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

    Esta solución será más confiable, ya que no tienen la amenaza de la OS Android matando a su servicio, que se cierne sobre usted. Según el API: El Administrador de alarmas está diseñado para los casos en los que desea 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, ajuste 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 la yourservice.class podría tener esto, verifica el estado de la conexión, si su buena fija el temporizador para apagarse 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 } } } 

    Los servicios mueren. Al igual que la aplicación se mata. Es la filosofía de Android que se puede matar en cualquier momento.

    Usted debe como otro escribió no hacer la suposición de que su backgroundservice se ejecuta para siempre.

    Pero usted puede utilizar un servicio de tierra delantero para reducir drásticamente la posibilidad de ser asesinado / reiniciado. Tenga en cuenta que esto obliga a una notificación siempre visible. Por ejemplo, reproductores de música, aplicaciones vpn y sportstracker utilizan esta API.

    Para el problema 1, de Java vainilla, Thread.Sleep() se garantiza para despertar el hilo después de que el temporizador ha expirado, pero no exactamente después de que ha expirado, puede ser posterior dependiendo principalmente de los estados de otros hilos, prioridad, etc. ; Así que si usted duerme su hilo de un segundo, entonces se duerme por lo menos un segundo, pero puede ser 10 dependiendo de una gran cantidad de 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 tiempo determinado le ayudará a tenerlo funcionando todo el tiempo.

    El sonido como usted debe utilizar un Service vez de un IntentService pero si usted quiere utilizar un IntentService y lo hace funcionar cada 60 segundos que usted debe utilizar el AlarmManager vez de apenas decir el Thread para dormir. IntentService s desea parar, lo deja Y tienen AlarmManager despertarlo cuando debe funcionar otra vez.

    Android es bastante bueno sobre la muerte de los servicios de larga duración. He encontrado el servicio WakefulIntentService de CommonsWare útil en mi aplicación: https://github.com/commonsguy/cwac-wakeful

    Le permite especificar un intervalo de tiempo como usted está intentando hacer durmiendo.

     It could be probably for two reasons.. 
    1. El bucle while está creando un problema, está haciendo que el controlador funcione hasta que temp==true
    2. A ello se añaden hilos, que crean long delays hasta 6 seconds . En caso, el sistema está trabajando para una base de datos grande, creando long delays entre cada consulta agregará en la memoria del sistema. Cuando el uso de la memoria para la aplicación llega a ser tan enorme que la system memory gets low del system memory gets low , el sistema tiene que terminate the process .

      Solución para el problema ..

    3. Puede reemplazar por arriba con el Alarm Manager para revocar los servicios del sistema después de un intervalo de tiempo determinado usando el Administrador de alarmas.

    4. También para obtener la intención de nuevo después de que el sistema recupera la aplicación de la terminación, debe utilizar START_REDELIVER_INTENT . Es para recuperar su última intención de trabajo una vez finalizada la aplicación. Para su uso, estudia https://developer.android.com/reference/android/app/Service.html#START_REDELIVER_INTENT
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.