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:
- ReceivingOrderService - Recepción de nuevos datos del servidor
- 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 .
- CheckAutoSyncReceivingOrder - Para llamar a ReceivingOrderService (15Mins de intervalo)
- 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.
Haga sus dos servicios como servicio de primer plano .
En lugar de utilizar
CheckAutoSyncReceivingOrder
yCheckAutoSyncSendingOrder
para programar el inicio de otros servicios, debe usarAlarmManager
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 seSTART_NOT_STICKY
oSTART_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.