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