Mi servono per la mia applicazione.
Ma prima cerchiamo di renderla con le variabili globali...
Ecco, ho ripristinato il meccanismo di reciproca chiamata fra un Service e un'Activity.
Service di nome Timer:
@Override
public void onDestroy(){
Log.d("TIMER","ONDESTROY");
Intent intent=new Intent(this,Form.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Log.d("TIMER","/ ONDESTROY");
super.onDestroy();
}
Activity di nome Form, alla pressione di un pulsante si ha l'istruzione finish() che rimanda a onDestroy().
public void onDestroy(){
startService(new Intent(this, Timer.class));
super.onDestroy();
}
Quest'ultima non è marcata. La marco e procedo allo studio dell'interruzione del ciclo.
public void onDestroy(){
Log.d("FORM","ONDESTROY");
startService(new Intent(this, Timer.class));
Log.d("FORM","/ ONDESTROY");
super.onDestroy();
}
Per il momento, c'è il richiamo immediato di Form da Timer, mentre il richiamo inverso è ritardato solo in quanto subordinato alla pressione del pulsante.
Ora inserisco un AlarmManager in Timer:
@Override
public void onDestroy(){
Log.d("TIMER","ONDESTROY");
Intent intent=new Intent(this,Form.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent=PendingIntent.getActivity(this, 0, intent, 0);
alarmManager=(AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+5*1000, pendingIntent);
Log.d("TIMER","/ ONDESTROY");
super.onDestroy();
}
L'ho impostato a 5 secondi.Lo sperimento.
Ho dovuto fare qualche aggiustamento per correggere errori di distrazione e dovuti al fatto che non ricordavo bene la procedura...
Comunque alla fine funziona: l'Act Form appare dopo 5 secondi dalla prima pressione del pulsante Start e quindi si ripete sempre dopo 5 secondi dal suo tasto Invia.
Ora devo gestire lo stop, con le variabili globali.
Aggiungo questa riga:
@Override
public void onDestroy(){
Log.d("TIMER","ONDESTROY");
Intent intent=new Intent(this,Form.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent=PendingIntent.getActivity(this, 0, intent, 0);
alarmManager=(AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+5*1000, pendingIntent);
if(Globals.Stop==true)alarmManager.cancel(pendingIntent);
Log.d("TIMER","/ ONDESTROY");
super.onDestroy();
}
e il codice per il pulsante che renda true la variabile globale Stop.
bttStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Globals.Stop=true;
}
});
Vediamo...Per far ripartire il ciclo ci metto pure la variabile che ridiventa false con il pulsante Start:
bttStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Globals.Stop=false;
startService(new Intent(getApplicationContext(),Timer.class));
}
});
Sperimento la cosa. Quando sono tornato sulla schermata Main, quella con i due pulsanti Start e Stop, se schiaccio Stop il ciclo successivo si ripete per una volta e quindi si stoppa definitivamente.
Evidentemente, una volta che alarmManager è "partito"; anche se viene cancellato, questo vale per il ciclo successivo.
Faccio un'altra prova: metto il Cancel direttamente dove sta senza condizioni...
@Override
public void onDestroy(){
Log.d("TIMER","ONDESTROY");
Intent intent=new Intent(this,Form.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent=PendingIntent.getActivity(this, 0, intent, 0);
alarmManager=(AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+3*1000, pendingIntent);
/*if(Globals.Stop==true)*/alarmManager.cancel(pendingIntent);
Log.d("TIMER","/ ONDESTROY");
super.onDestroy();
}
Ecco: così facendo, il ciclo non parte affatto perché alarmManager viene cancellato "sul nascere".Dunque il problema non è che il ciclo era già stato avviato quando viene richiesto il valore della variabile Stop, ma forse il fatto che la variabile Stop è ancora false fino a quando non si sia avviato Form.
Questo codice:
@Override
public void onDestroy(){
Log.d("TIMER","ONDESTROY");
Intent intent=new Intent(this,Form.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent=PendingIntent.getActivity(this, 0, intent, 0);
alarmManager=(AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+3*1000, pendingIntent);
if(Globals.Stop==true)alarmManager.cancel(pendingIntent);
Log.d("STOP",""+Globals.Stop);
Log.d("TIMER","/ ONDESTROY");
super.onDestroy();
}
...me lo prova:
06-28 14:13:39.367: D/TIMER(4762): ONSTARTCOMMAND 06-28 14:13:39.367: D/TIMER(4762): / ONSTARTCOMMAND 06-28 14:13:39.367: D/TIMER(4762): ONDESTROY 06-28 14:13:39.377: D/STOP(4762): false 06-28 14:13:39.377: D/TIMER(4762): / ONDESTROYOssia quando viene premuto il pulsante, Globals.Stop è ancora false.
Ma proseguendo ancora oltre...
06-28 14:13:39.367: D/TIMER(4762): ONSTARTCOMMAND 06-28 14:13:39.367: D/TIMER(4762): / ONSTARTCOMMAND 06-28 14:13:39.367: D/TIMER(4762): ONDESTROY 06-28 14:13:39.377: D/STOP(4762): false 06-28 14:13:39.377: D/TIMER(4762): / ONDESTROY 06-28 14:13:50.018: D/FORM(4762): ONDESTROY 06-28 14:13:50.018: D/FORM(4762): / ONDESTROY 06-28 14:13:50.038: D/TIMER(4762): ONSTARTCOMMAND 06-28 14:13:50.038: D/TIMER(4762): / ONSTARTCOMMAND 06-28 14:13:50.038: D/TIMER(4762): ONDESTROY 06-28 14:13:50.048: D/STOP(4762): true 06-28 14:13:50.048: D/TIMER(4762): / ONDESTROY...si vede che al ciclo successivo la variabile è true e quindi il ciclo si ferma.
Dunque voglio vedere quando diventa true: mi marco a tale scopo anche Form...
public class Form extends Activity {
Button button1, button2, button3, button4, button5;
ImageView imageView;
DBHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_form);
Log.d("FORM","ONCREATE");
Log.d("STOP",""+Globals.Stop);
button1=(Button)findViewById(R.id.button1);
button2=(Button)findViewById(R.id.button2);
button3=(Button)findViewById(R.id.button3);
button4=(Button)findViewById(R.id.button4);
button5=(Button)findViewById(R.id.bttInvia);
imageView=(ImageView)findViewById(R.id.imageView1);
OnClickListener onClickListener=new View.OnClickListener() {
@Override
public void onClick(View v) {
if(v==button1) imageView.setImageResource(R.drawable.nonurgentenonimportante);
if(v==button2) imageView.setImageResource(R.drawable.urgentenonimportante);
if(v==button3) imageView.setImageResource(R.drawable.urgenteimportante);
if(v==button4) imageView.setImageResource(R.drawable.nonurgenteimportante);
button5.setVisibility(View.VISIBLE);
}
};
button5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
button1.setOnClickListener(onClickListener);
button2.setOnClickListener(onClickListener);
button3.setOnClickListener(onClickListener);
button4.setOnClickListener(onClickListener);
Log.d("FORM","/ ONCREATE");
}
public void onDestroy(){
Log.d("FORM","ONDESTROY");
Log.d("STOP",""+Globals.Stop);
startService(new Intent(this, Timer.class));
Log.d("FORM","/ ONDESTROY");
super.onDestroy();
}
}
E riproviamo: interrogo il valore della variabile all'inizio di FORM ONCREATE e all'inizio di FORM ONDESTROY.06-28 14:26:35.604: D/TIMER(9225): ONDESTROY 06-28 14:26:35.604: D/STOP(9225): false 06-28 14:26:35.604: D/TIMER(9225): / ONDESTROY 06-28 14:26:38.677: D/FORM(9225): ONCREATE 06-28 14:26:38.677: D/STOP(9225): false 06-28 14:26:38.687: D/FORM(9225): / ONCREATE 06-28 14:26:41.280: D/FORM(9225): ONDESTROY 06-28 14:26:41.280: D/STOP(9225): false 06-28 14:26:41.280: D/FORM(9225): / ONDESTROY 06-28 14:26:41.300: D/TIMER(9225): ONSTARTCOMMAND 06-28 14:26:41.300: D/TIMER(9225): / ONSTARTCOMMAND 06-28 14:26:41.300: D/TIMER(9225): ONDESTROY 06-28 14:26:41.300: D/STOP(9225): false 06-28 14:26:41.300: D/TIMER(9225): / ONDESTROY 06-28 14:26:44.353: D/FORM(9225): ONCREATE 06-28 14:26:44.353: D/STOP(9225): true 06-28 14:26:44.353: D/FORM(9225): / ONCREATE 06-28 14:26:46.345: D/FORM(9225): ONDESTROY 06-28 14:26:46.345: D/STOP(9225): true 06-28 14:26:46.355: D/FORM(9225): / ONDESTROY 06-28 14:26:46.365: D/TIMER(9225): ONSTARTCOMMAND 06-28 14:26:46.375: D/TIMER(9225): / ONSTARTCOMMAND 06-28 14:26:46.375: D/TIMER(9225): ONDESTROY 06-28 14:26:46.385: D/STOP(9225): true 06-28 14:26:46.385: D/TIMER(9225): / ONDESTROYSì... pare che quello che conta sia il valore all'inizio del metodo.
Quindi la soluzione più pratica che mi venga in mente è bloccare la comparsa del Form se la variabile è pari a true, perché al momento in cui è cessato il metodo TIMER ONDESTROY il valore della variabile globale true sarà finalmente palese.
Provo a trovare una soluzione...
@Override
protected void onCreate(Bundle savedInstanceState) {
if(Globals.Stop)finish();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_form);
Log.d("FORM","ONCREATE");
Log.d("STOP",""+Globals.Stop);
.....
Questa sembra funzionare.Ma gettiamo un occhio a come vengono terminate tutte le componenti...
06-28 14:43:13.188: D/TIMER(13654): ONDESTROY 06-28 14:43:13.188: D/STOP(13654): false 06-28 14:43:13.188: D/TIMER(13654): / ONDESTROY 06-28 14:43:16.231: D/FORM(13654): ONCREATE 06-28 14:43:16.231: D/STOP(13654): true 06-28 14:43:16.231: D/FORM(13654): / ONCREATE 06-28 14:43:16.281: D/FORM(13654): ONDESTROY 06-28 14:43:16.281: D/STOP(13654): true 06-28 14:43:16.281: D/FORM(13654): / ONDESTROY 06-28 14:43:16.281: D/TIMER(13654): ONSTARTCOMMAND 06-28 14:43:16.281: D/TIMER(13654): / ONSTARTCOMMAND 06-28 14:43:16.281: D/TIMER(13654): ONDESTROY 06-28 14:43:16.291: D/STOP(13654): true 06-28 14:43:16.291: D/TIMER(13654): / ONDESTROYEcco: viene chiamato FORM, questo viene cessato e alla sua onDestroy viene chiamato Timer, il quale vede disattivato AlarmManager e non può più richiamare FORM.
Si potrebbe evitare il richiamo a vuoto di TIMER semplicemente ponendo il suo richiamo da FORM ONDESTROY come subordinato al valore false di Globals.Stop.
public void onDestroy(){
Log.d("FORM","ONDESTROY");
Log.d("STOP",""+Globals.Stop);
if(Globals.Stop==false) startService(new Intent(this, Timer.class));
Log.d("FORM","/ ONDESTROY");
super.onDestroy();
}
E seguiamo...
06-28 14:47:13.302: D/TIMER(16187): ONDESTROY 06-28 14:47:13.302: D/STOP(16187): false 06-28 14:47:13.302: D/TIMER(16187): / ONDESTROY 06-28 14:47:16.355: D/FORM(16187): ONCREATE 06-28 14:47:16.355: D/STOP(16187): true 06-28 14:47:16.355: D/FORM(16187): / ONCREATE 06-28 14:47:16.415: D/FORM(16187): ONDESTROY 06-28 14:47:16.415: D/STOP(16187): true 06-28 14:47:16.415: D/FORM(16187): / ONDESTROYCome previsto!
Forse a questo punto si potrebbe pure evitare il blocco di AlarmManager: una volta che questo abbia chiamato Form, questo si distrugge, e dal suo ONDESTROY non viene richiamato TIMER.
Ma lasciamocelo, come mezzo di sicurezza in più!
Nessun commento:
Posta un commento