2012-07-13 14 views
15

Sto sviluppando un'app per Android utilizzando la comunicazione Bluetooth (utilizzando un protocollo di propensione) e devo catturare il momento in cui l'app viene uccisa.L'app per Android non chiama "onDestroy()" quando viene uccisa (ICS)

Volevo utilizzare il metodo "onDestroy()" ma non viene chiamato ogni volta che l'app viene uccisa. Ho notato che viene chiamato quando premo il pulsante Indietro e, solo a volte, quando uccido l'app dal task manager.

La domanda è: come posso prendere il momento prima che l'app venga uccisa?

Ecco il codice ho provato ad usare:

@Override 
public void onDestroy() { 
    sendMessage(msg); 
    Log.d("SampleApp", "destroy"); 
    super.onDestroy(); 
} 

@Override 
public void finish(){ 

    sendMessage(msg); 
    Log.d("SampleApp", "finish"); 
    super.finish(); 
} 

Purtroppo finitura() non viene mai chiamato e OnDestroy non è chiamato ogni volta che chiudo l'applicazione dal task manager.

Come posso gestirlo?

+0

Intendi quando l'app viene uccisa dal sistema, quando l'utente preme Force Stop nelle impostazioni, o solo quando il pulsante HOME o BACK viene premuto mentre si guarda l'attività? – Devunwired

+0

Entrambi sono ok per me, vorrei catturare il momento in cui l'utente uccide l'app dal task manager (o premere a lungo la schermata iniziale e uccide l'app da lì, in sandwich gelato) ma va bene anche catturando il momento in cui l'utente preme il tasto HOME o INDIETRO guardando la mia attività. –

risposta

13

Come indicato nella documentazione here, non vi è alcuna garanzia che onDestroy() venga mai chiamato. Invece, usa onPause() per fare le cose che vuoi fare ogni volta che l'app entra in background e lasciare solo quel codice in onDestroy() che vuoi eseguire quando la tua app viene uccisa.

EDIT:

Dai vostri commenti, sembra che si desidera eseguire del codice ogni volta che la vostra applicazione passa in secondo piano, ma non se è andato in secondo piano, perché è stato lanciato un intento. Per quanto ne so, non esiste un metodo in Android che gestisce questo per impostazione predefinita, ma è possibile utilizzare qualcosa di simile:

Avere un booleano come:

boolean usedIntent = false; 

Ora prima di usare un intento, impostare il valore booleano true. Ora nel tuo onPause(), spostare il codice per il caso intento in un blocco if come questo:

if(usedIntent) 
{ 
//Your code 
} 

Infine, nel vostro onResume(), impostare il valore booleano false di nuovo in modo che possa gestire la sua l'app viene spostata in background da un mezzo non intenzionale in modo appropriato.

+0

L'ho già letto ma il problema è che se inserisco il mio codice in onPause() verrà eseguito anche se avvio una nuova intenzione nella mia app. Invece mi piacerebbe inviare il mio messaggio solo quando viene chiamato il onPause per tornare alla schermata iniziale –

+0

Solo la schermata iniziale o un'altra app come quando arriva una chiamata o l'utente visualizza una notifica? –

+0

diciamo che mi piacerebbe sapere quando la mia app non è più visualizzata (quindi va in background per qualsiasi motivo), ma non voglio fare nulla quando viene avviato un intent perché ho iniziato un nuovo intent dalla mia app –

13

L'applicazione non riceverà alcuna callback aggiuntiva se il processo è terminato con mezzi esterni (ovvero, per motivi di memoria o l'utente Forza interrompe l'applicazione). Dovrai accontentarti delle richiamate che hai ricevuto quando l'app è stata messa in background per la pulizia dell'applicazione.

finish() viene chiamato dal sistema solo quando l'utente preme il pulsante INDIETRO dall'attività, sebbene venga spesso chiamato direttamente dalle applicazioni per lasciare un'attività e tornare a quella precedente. Questo non è tecnicamente un callback del ciclo di vita.

onDestroy() viene chiamato su un'attività solo a seguito di una chiamata a finish(), quindi principalmente solo quando l'utente preme il pulsante INDIETRO. Quando l'utente preme il pulsante HOME, l'attività in primo piano passa solo attraverso onPause() e onStop().

Ciò significa che Android non fornisce molto feedback a un'attività per distinguere un utente che va da Casa a uno spostamento verso un'altra attività (dalla propria app o da qualsiasi altra); l'attività stessa sa semplicemente che non è più in primo piano.Un'applicazione Android è più una raccolta libera di attività di quanto non sia un concetto singolarmente strettamente integrato (come si potrebbe essere abituati ad altre piattaforme) quindi non ci sono veri callback di sistema da sapere quando l'applicazione nel suo complesso è stata anticipata o spostato all'indietro.

In definitiva, vorrei esortare a riconsiderare l'architettura dell'applicazione se si basa sulla conoscenza dell'eventualità che QUALSIASI Attività nella vostra applicazione sia in primo piano, ma a seconda delle esigenze, potrebbero esserci altri modi più amichevoli per il framework di realizzare questo. Un'opzione consiste nell'implementare un limite Service all'interno dell'applicazione che ad ogni Activity si associa a quando attivo (ad esempio tra onStart() e onStop()). Ciò che ti fornisce è la possibilità di sfruttare il fatto che un limite Service sopravvive solo finché i client sono associati, quindi puoi monitorare i metodi onCreate() e onDestroy()del Servizio per sapere quando l'attività in primo piano corrente non è parte della tua domanda.

Potresti anche trovare this article scritto da Dianne Hackborn per interessare in modo più dettagliato l'architettura di Android e il modo in cui Google pensa che dovrebbe essere utilizzato.

+0

Penso che questo sia il modo più corretto, penso che dovrebbe aggiungere un'interfaccia (o una classe astratta) nell'applicazione per imporre attività (o componenti) appena aggiunte per definire il comportamento per questo. –

+0

https://developer.android.com/guide/components/activities/activity-lifecycle.html –

0

Ho appena risolto un problema simile.

Ecco cosa è possibile fare se il proprio interrompe il servizio quando l'applicazione viene interrotta scorrendo dall'elenco delle app recenti.

All'interno del file manifest, mantenere la flag stopWithTask come true per il servizio. Come:

<service 
    android:name="com.myapp.MyService" 
    android:stopWithTask="true" /> 

Ma come dici che si desidera annullare la registrazione ascoltatori e smettere di notifica, ecc, vorrei suggerire questo approccio:

  1. Dentro il file manifesto, tenere bandiera stopWithTask come false per il servizio. Come:

    <service 
        android:name="com.myapp.MyService" 
        android:stopWithTask="false" /> 
    
  2. Ora nel vostro servizio MyService, metodo di sostituzione onTaskRemoved. (Questo verrà attivato solo se stopWithTask è impostato su false).

    public void onTaskRemoved(Intent rootIntent) { 
    
        //unregister listeners 
        //do any other cleanup if required 
    
        //stop service 
        stopSelf(); 
    } 
    

consultare my question per maggiori dettagli, che contiene altra parte del codice, anche.

    servizio
  1. Inizia come qui di seguito

StartService (nuovo Intent (questo, MyService.class));

Spero che questo aiuti.