studio programacion herramientas fundamentos con avanzado aplicaciones android android-activity android-service android-intentservice

programacion - manual de android en pdf



Servicio llamado automáticamente en la actividad de destrucción (4)

(1) Para su diálogo:

La solución es llamar a onDestroy() en el onDestroy() Dialog que creó antes de salir de la Activity , por ejemplo, en onDestroy() . Todos los cuadros de diálogo de Windows y se deben cerrar antes de salir de una Activity .

(2) Para su autostart de servicio:

tienes que mirar el valor que devuelve el servicio desde su método onStartCommand. El valor predeterminado es START_STICKY, que reiniciará el servicio después de que se destruya. Eche un vistazo a la documentación de onStartCommand para más detalles:

Estoy atascado con el problema de Activity + Service porque tengo el siguiente número de Actividades y Servicios.

Ocupaciones:

LoginActivity => OrderListActivity => AddOrderActivity => ConfirmOrderActivity

Servicios:

  1. ReceivingOrderService - Recepción de nuevos datos del servidor
  2. SendingOrderService - Envío de datos nuevos al servidor

Sobre ambas llamadas de servicio desde otro servicio separado en la duración de algún intervalo .

  1. CheckAutoSyncReceivingOrder - Para llamar a ReceivingOrderService (15Mins de intervalo)
  2. CheckAutoSyncSendingOrder - Para llamar a SendingOrderService (Interval 3Mins)

CheckAutoSyncReceivingOrder:

public class CheckAutoSyncReceivingOrder extends Service { Timer timer; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub if(timer != null) { timer.cancel(); Log.i(TAG, "RECEIVING OLD TIMER CANCELLED>>>"); } timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { if(InternetConnection.checkConnection(getApplicationContext())) { if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists()) startService(new Intent(CheckAutoSyncReceivingOrder.this, ReceivingOrderService.class)); } else { Log.d(TAG, "Connection not available"); } } }, 0, 60000); // 1000*60*15 = 9,00,000 = 15 minutes } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if(timer != null) timer.cancel(); Log.d(TAG, "Stopping Receiving..."); } }

CheckAutoSyncSendingOrder:

public class CheckAutoSyncSendingOrder extends Service { Timer timer; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub if(timer != null) { timer.cancel(); Log.i(TAG, "OLD TIMER CANCELLED>>>"); } timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Log.i(TAG, ">>>>>>>> SENDING AUTO SYNC SERVICE >>>>>>>>"); if(InternetConnection.checkConnection(getApplicationContext())) { if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists()) startService(new Intent(CheckAutoSyncSendingOrder.this, SendingOrderService.class)); } else { Log.d(TAG, "connection not available"); } } }, 0, 120000); // 1000*120*15 = 1,800,000 = 15 minutes } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if(timer != null) timer.cancel(); Log.d(TAG, "Stopping Sending..."); } }

ConfirmOrderActivity # Final Task que he solicitado para insertar datos:

new AsyncTask<Void, Void, Integer>() { ProgressDialog progressDialog; @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); progressDialog = new ProgressDialog( ConfirmOrderProductActivity.this); progressDialog.setMessage("Inserting " + (isInquiry ? "Inquiry" : "Order") + "..."); progressDialog.setCancelable(false); progressDialog .setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.show(); } @Override protected Integer doInBackground(Void... params) { // TODO Auto-generated method stub int account_id = context.getSharedPreferences(PREF_DATA, MODE_APPEND).getInt(DATA_ACCOUNT_ID, 0); /** * Check Whether isInquiry or not... */ product_type = isWeight ? 1 : 0; if (isInquiry) { /* * INSERTING DATA IN INQUIRY TABLE */ return m_inquiry_id; } else { /* * INSERTING DATA IN ORDER TABLE */ return m_order_id; } } @Override protected void onPostExecute(Integer m_order_id) { // TODO Auto-generated method stub super.onPostExecute(m_order_id); progressDialog.dismiss(); if (dbHelper.db.isOpen()) dbHelper.close(); String title = "Retry"; String message = "There is some problem, Go Back and Try Again"; AlertDialog.Builder alert = new AlertDialog.Builder( ConfirmOrderProductActivity.this); if (m_order_id != -1) { title = isInquiry ? "New Inquiry" : "New Order"; message = isInquiry ? "Your Inquiry Send Successfully." : "Your Order Saved Successfully."; alert.setIcon(R.drawable.success).setCancelable(false); } else { alert.setIcon(R.drawable.fail).setCancelable(false); } alert.setTitle(title).setMessage(message) .setPositiveButton("OK", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub dialog.dismiss(); startActivity(new Intent( ConfirmOrderProductActivity.this, FragmentChangeActivity.class) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); /* Opening Left to Right Animation */ overridePendingTransition(R.anim.right_out, R.anim.right_in); } }); AlertDialog alertDialog = alert.create(); alertDialog.show(); } }.execute();

Todo funciona bien según el flujo de inserción de registros en la base de datos.

Después de agregar una consulta:

Destrucción de actividad y obtención de Logcat siguiente:

Problema principal:

Cuando realicé el pedido correctamente desde ConfirmOrderActivity , muestra AlertDialog of Success Message, que es AlertDialog false . Cuando CheckAutoSyncReceivingOrder aplicación de esta actividad, llama tanto a CheckAutoSyncReceivingOrder como a CheckAutoSyncSendingOrder automáticamente.

Editado:

Estoy llamando a ambos servicios desde LoginActivity solamente, después de eso se llamará automáticamente después de intervalos dados, pero se produce un problema cuando destruyo ConfirmOrderActivity cuando se muestra el cuadro de diálogo.

No sabía por qué sucede que Why se está ejecutando automáticamente cuando dejo Activity Directly.

Intenté onStartCommand() con START_NON_STICKY en el Service pero no funcionaba. (como START_STICKY es el predeterminado)

@Override public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; }

¿Hay alguna solución?


Debe ejecutar su servicio en primer plano para que cuando se destruya la actividad también lo haga el servicio o utilice un servicio encuadernado y administre el enlace con el ciclo de vida de la actividad, para que no se reinicie continuamente cuando se destruye la actividad.

De este android docs tutorial Bound Services

Debe hacer esto para cada servicio.

public class CheckAutoSyncReceivingOrder extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { CheckAutoSyncReceivingOrder getService() { return CheckAutoSyncReceivingOrder.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; }

De su actividad que crea y llama al servicio, cuando se destruye quiere que se destruya su servicio.

public class BindingActivity extends Activity { CheckAutoSyncReceivingOr mService; boolean mBound = false; @Override protected void onStart() { super.onStart(); // Bind to CheckAutoSyncReceivingOr Intent intent = new Intent(this, CheckAutoSyncReceivingOr.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We''ve bound to CheckAutoSyncReceivingOr, cast the IBinder and get CheckAutoSyncReceivingOr instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }

Y administre el ciclo de vida del servicio . Reinicie el mismo servicio con su temporizador, no cree un nuevo servicio.

public class ExampleService extends Service { int mStartMode; // indicates how to behave if the service is killed IBinder mBinder; // interface for clients that bind boolean mAllowRebind; // indicates whether onRebind should be used @Override public void onCreate() { // The service is being created } @Override public int onStartCommand(Intent intent, int flags, int startId) { // The service is starting, due to a call to startService() return mStartMode; } @Override public IBinder onBind(Intent intent) { // A client is binding to the service with bindService() return mBinder; } @Override public boolean onUnbind(Intent intent) { // All clients have unbound with unbindService() return mAllowRebind; } @Override public void onRebind(Intent intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } @Override public void onDestroy() { // The service is no longer used and is being destroyed } }

Tenga en cuenta que START_NOT_STICKY solo evitará que el servicio se reinicie si el dispositivo tiene poca memoria.

Tenga en cuenta que cuando inicia servicios, solo empiece una vez y permita que el servicio mantenga su propio ciclo de vida hasta que lo destruya con su actividad.

Esto es en respuesta a su pregunta original no editada, cuando la aplicación se bloqueaba misteriosamente:

Debe destruir el cuadro de diálogo antes de la ventana de contexto al que está conectado el cuadro de diálogo. Eso causará un problema. Así que aquí es donde el flujo de programas y el orden de cierre y limpieza de recursos es importante. Ellos, con frecuencia tienen que ser destruidos en el orden inverso al que fueron creados si dependen de las ventanas principales (que a menudo se encuentran en la forma de una actividad particular).

Es difícil rastrear su código, así que esta es una respuesta genérica.

Utiliza onPause y onDestroy en tus actividades.

En todas sus actividades, administre los recursos que haya creado dentro de esa actividad y con una verificación nula, ciérrelos. Como lo has hecho en tu clase de servicio. Si desea sobrescribir el elemento primario en Destroy, coloque el código personalizado antes de super.onDestroy.

protected void onDestroy() { if(timer != null) timer.cancel(); Log.d(TAG, "Stopping Sending..."); super.onDestroy(); }


Los servicios se mataron cuando se eliminó la aplicación (agregue registros en las funciones onStartCommand() y onDestroy() e intente borrar la aplicación de la lista reciente y verá que se onDestroy() . Android reiniciará el servicio si ha devuelto START_STICKY intento en onStartCommand() ).

Hay dos enfoques para solucionar su problema.

  1. Haga sus dos servicios como servicio de primer plano .

  2. En lugar de utilizar CheckAutoSyncReceivingOrder y CheckAutoSyncSendingOrder para programar el inicio de otros servicios, debe usar AlarmManager para programar su tarea.


Si el proceso que ejecuta su servicio es eliminado, el sistema Android lo reiniciará automáticamente, es un comportamiento predeterminado.

Este comportamiento se define por el valor de retorno de onStartCommand() en la implementación de su Servicio. La constante START_NOT_STICKY le dice a Android que no reinicie el servicio si se está ejecutando mientras el proceso se "mata".

onStartCommand() método onStartCommand() en su clase de servicio y mover todo su código del método onStartCommand() método onStartCommand() .

De acuerdo con la documentación de Android:

Para los servicios iniciados, hay dos modos principales de operación adicionales en los que pueden decidir ejecutarse, según el valor que devuelven desde onStartCommand() : START_STICKY se usa para servicios que se inician y detienen explícitamente según sea necesario, mientras se START_NOT_STICKY o START_REDELIVER_INTENT para servicios que solo deberían seguir ejecutándose mientras se procesan los comandos enviados a ellos

onStart() método onStart() llama cada vez que se reinicia el servicio pero no se onStartCommand() método onStartCommand() si devuelve START_NON_STICKY .

Ya no usas onStart (), está en desuso.

Espero que te ayude.