162

Attualmente ho un'attività che quando viene visualizzata una notifica verrà visualizzata anche nella barra di notifica.Android - Come sovrascrivere il pulsante "Indietro" in modo che non finisca() la mia attività?

Questo è così che quando l'utente preme a casa e l'attività viene spinta in background, è possibile tornare all'Attività tramite la notifica.

Il problema sorge quando preme un utente il pulsante indietro, la mia attività viene distrutta, ma la notifica rimane come voglio che l'utente sia in grado di premere di nuovo, ma ancora in grado di raggiungere l'attività tramite la notifica. Ma quando un utente cerca di farlo, ottengo che Null Pointers stia cercando di avviare una nuova attività piuttosto che riportare quella vecchia.

Quindi, in sostanza voglio il pulsante Indietro per agire esattamente lo stesso come il tasto Home e ecco come ho provato finora:


 @Override 
     public boolean onKeyDown(int keyCode, KeyEvent event) { 
      if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5 
        && keyCode == KeyEvent.KEYCODE_BACK 
        && event.getRepeatCount() == 0) { 
       Log.d("CDA", "onKeyDown Called"); 
       onBackPressed(); 
      } 

      return super.onKeyDown(keyCode, event); 
     } 

     public void onBackPressed() { 
      Log.d("CDA", "onBackPressed Called"); 
      Intent setIntent = new Intent(Intent.ACTION_MAIN); 
      setIntent.addCategory(Intent.CATEGORY_HOME); 
      setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      startActivity(setIntent); 

      return; 
     } 

Tuttavia, il codice di cui sopra sembra ancora consentire che la mia attività venga distrutta, come posso impedire che la mia attività venga distrutta quando si preme il pulsante Indietro?

+0

C'è una domanda simile: http://stackoverflow.com/questions/2459848/android-prompt-user-to-save-changes- quando-back-button-è-pressato – aleung

+1

risposta simile .. http://stackoverflow.com/questions/5914040/onbackpressed-to-hide-not-destroy-activity/23759328#23759328 – Nepster

+0

anche io penso che si debba cambiare la vostra il codice a 'se (Integer.parseInt (android.os.Build.VERSION.SDK)> 5', il' < 'dovrebbe diventare un'> '. – SudoPlz

risposta

229

Rimuovere l'ascoltatore chiave o restituire true quando si dispone di KEY_BACK.

Per catturare la chiave posteriore è sufficiente quanto segue (Assicurarsi di non chiamare super in onBackPressed()).

Inoltre, se si prevede di avere un servizio in esecuzione in background, assicurarsi di guardare startForeground() e assicurarsi di avere una notifica in corso oppure Android ucciderà il servizio se è necessario liberare memoria.

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
    if (Integer.parseInt(android.os.Build.VERSION.SDK) > 5 
      && keyCode == KeyEvent.KEYCODE_BACK 
      && event.getRepeatCount() == 0) { 
     Log.d("CDA", "onKeyDown Called"); 
     onBackPressed(); 
     return true; 
    } 
    return super.onKeyDown(keyCode, event); 
} 


@Override 
public void onBackPressed() { 
    Log.d("CDA", "onBackPressed Called"); 
    Intent setIntent = new Intent(Intent.ACTION_MAIN); 
    setIntent.addCategory(Intent.CATEGORY_HOME); 
    setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    startActivity(setIntent); 
} 
12

Penso che quello che vuoi è non sovrascrivere il pulsante Indietro (che non sembra proprio una buona idea - Android OS definisce questo comportamento, perché cambiarlo?), Ma per usare il Activity Lifecycle e mantenere le tue impostazioni/dati nell'evento onSaveInstanceState(Bundle).

@Override 
onSaveInstanceState(Bundle frozenState) { 
    frozenState.putSerializable("object_key", 
     someSerializableClassYouWantToPersist); 
    // etc. until you have everything important stored in the bundle 
} 

quindi si utilizza onCreate(Bundle) per ottenere tutto fuori che persisteva fascio e ricreare il tuo stato.

@Override 
onCreate(Bundle savedInstanceState) { 
    if(savedInstanceState!=null){ //It could be null if starting the app. 
     mCustomObject = savedInstanceState.getSerializable("object_key"); 
    } 
    // etc. until you have reloaded everything you stored 
} 

Si consideri il codice psuedo di cui sopra per indicarti la giusta direzione. La lettura dello Activity Lifecycle dovrebbe aiutarti a determinare il modo migliore per ottenere ciò che stai cercando.

+0

Ciao Kiswa, questo è vero, non voglio cambiare il comportamento predefinito. Ho provato a utilizzare onSavedInstanceState e non funzionava, ma credo di aver individuato il mio errore ora. Grazie –

+5

Mi sono imbattuto in almeno alcune situazioni in cui volevo simulare il comportamento dello stack di attività standard senza effettivamente avviare nuove attività. In questi casi, penso, è opportuno sovrascrivere il comportamento predefinito suBackPressed(). In generale, però, sono d'accordo: evitare prevalente. –

+4

Sono d'accordo con @Matt. Attualmente sto lavorando a un gioco multipiattaforma che utilizza NDK. In quanto tale, è più facile se tutto è una singola attività. Per questo motivo, il comportamento predefinito del pulsante Indietro è di sfuggire all'applicazione, che non è ciò che la maggior parte degli utenti si aspetta. Quindi ho dovuto sovrascrivere il comportamento predefinito per far sì che l'attività si comportasse in modo diverso, come se l'utente fosse effettivamente passato a un'attività diversa e abbandonasse l'app solo in determinate circostanze. –

46

era più facile da implementare solo con una riga di codice:

@Override 
public void onBackPressed() { 
    moveTaskToBack(true); 
} 
+0

Questa dovrebbe essere la risposta accettata. Questo fa esattamente quello che la domanda sta ponendo e sta usando una funzionalità integrata pulita. – Shadoninja

+0

Grazie :) puoi approfondire il concetto? –

+0

È sufficiente ignorare l'evento onBackPressed(), spostando l'attività sul retro. – Squirrelkiller

8

semplicemente fare questo ..

@Override 
public void onBackPressed() { 
    //super.onBackPressed(); 
} 

commentando la // eccellente.onBackPressed(); farà il trucco

+1

Un'osservazione utile, ma non farà in modo che il pulsante Indietro non faccia nulla, come se fosse rotto? Non è una buona cosa da fare: confondere e annoiare gli utenti. IMHO deve aggiungere la logica da un'altra risposta, per agire come il pulsante Home, come richiesto in questione. La risposta accettata * menziona * che non stavano deliberatamente chiamando il super metodo. – ToolmakerSteve

+0

Sì, hai assolutamente ragione. Sostituirà semplicemente il pulsante Indietro e non farà nulla finché non metterai un po 'di logica lì. Può essere una condizione per premere due volte il pulsante per chiudere l'applicazione o semplicemente per disabilitare un'operazione in corso (finestra di avanzamento) ecc., Ma è completamente all'altezza del requisito. –

1

Prova questo:

@Override 
public void onBackPressed() { 
    finish(); 
} 
+0

Questo è così divertente. –

0

Solo nel caso in cui si desidera gestire il comportamento del pulsante Indietro (nella parte inferiore del telefono) e il tasto Home (quello a sinistra di la barra delle azioni), questa attività personalizzata che sto utilizzando nel mio progetto potrebbe aiutarti.

import android.os.Bundle; 
import android.support.v7.app.ActionBar; 
import android.support.v7.app.AppCompatActivity; 
import android.view.MenuItem; 

/** 
* Activity where the home action bar button behaves like back by default 
*/ 
public class BackActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setupHomeButton(); 
    } 

    private void setupHomeButton() { 
     final ActionBar actionBar = getSupportActionBar(); 
     if (actionBar != null) { 
      actionBar.setDisplayHomeAsUpEnabled(true); 
      actionBar.setHomeButtonEnabled(true); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case android.R.id.home: 
       onMenuHomePressed(); 
       return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    protected void onMenuHomePressed() { 
     onBackPressed(); 
    } 
} 

Esempio di utilizzo nella vostra attività:

public class SomeActivity extends BackActivity { 

    // .... 

    @Override 
    public void onBackPressed() 
    { 
     // Example of logic 
     if (yourConditionToOverride) { 
      // ... do your logic ... 
     } else { 
      super.onBackPressed(); 
     } 
    }  
} 
Problemi correlati