Android: come sovrascrivere il pulsante "Indietro" in modo che non finisca () la mia attività?


199

Al momento ho un'attività che quando viene visualizzata verrà visualizzata anche una notifica nella barra delle notifiche.

In questo modo, quando l'utente preme home e l'attività viene spostata in background, può tornare all'attività tramite la notifica.

Il problema sorge quando un utente preme il pulsante Indietro, la mia attività viene distrutta ma la notifica rimane, poiché desidero che l'utente sia in grado di premere indietro, ma sia comunque in grado di accedere all'attività tramite la notifica. Ma quando un UTENTE ci prova, ottengo Null Pointers mentre cerca di avviare una nuova attività piuttosto che riportare quella vecchia.

Quindi essenzialmente voglio che il pulsante Indietro si comporti esattamente come il pulsante Home ed 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 sopra riportato sembra ancora consentire la distruzione della mia attività. Come posso impedire la distruzione della mia attività quando si preme il pulsante Indietro?




Inoltre penso che devi cambiare il tuo codice in `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <` dovrebbe diventare un >.
SudoPlz,

1
Anche se lo risolvi, devi comunque gestire la possibilità che il sistema uccida la tua app, giusto? Voglio dire, il caso nullo è ancora possibile? O se il sistema uccide la tua app per qualsiasi motivo, rimuoverà anche la tua notifica? Sto pensando che questo debba essere un problema, poiché lo scopo di una notifica è esistere anche se l'app non lo è.
ToolmakerSteve

Controlla qui il codice dell'applicazione di esempio freakyjolly.com/how-to-add-back-arrow-in-android-activity
Codice spia

Risposte:


276

Rimuovi il tuo listener di chiavi o ritorna truequando hai KEY_BACK.

Hai solo bisogno la seguente per prendere la chiave (Assicurarsi di non chiamare super- in onBackPressed()).

Inoltre, se prevedi di eseguire un servizio in background, assicurati di guardare startForeground()e assicurarti di avere una notifica in corso, altrimenti Android ucciderà il tuo servizio se deve liberare memoria.

@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);
}

70

È stato più semplice implementarlo solo con una riga di codice:

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

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

Grazie :) puoi elaborare il concetto alla base?
Farrukh Faizy,

1
Basta semplicemente ignorare l'evento onBackPressed (), facendolo spostare l'attività sul retro.
Squirrelkiller,

1
Questa soluzione non ripristinerà l'attività quando riavvii l'app dalla schermata principale (se è presente un'altra attività nello stack di attività).
IgorGanapolsky,

12

Penso che ciò che vuoi non sia ignorare il pulsante Indietro (che non sembra una buona idea - il sistema operativo Android definisce quel comportamento, perché cambiarlo?), Ma usare il ciclo di vita delle attività e mantenere le tue impostazioni / i tuoi dati nel Evento onSaveInstanceState (Bundle) .

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

Quindi usi onCreate (Bundle) per ottenere tutto da quel bundle persistente 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
}

Considera il codice psuedo sopra indicato per indirizzarti nella giusta direzione. Leggere sul ciclo di vita delle attività dovrebbe aiutarti a determinare il modo migliore per realizzare ciò che stai cercando.


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
Donal Rafferty,

5
Mi sono imbattuto in almeno alcune situazioni in cui volevo simulare il comportamento dello stack di attività standard senza avviare effettivamente nuove attività. In questi casi, penso, sia opportuno sovrascrivere il comportamento predefinito onBackPressed (). In generale, però, sono d'accordo: evitare l'override.
Matt Briançon,

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

1
OnSaveInstanceState e il salvataggio dei dati non sono una domanda completamente diversa?
Ted

@Ted -se stai dicendo che in aggiunta a onSaveInstanceState, ci deve essere anche un codice che persista i dati delle app non UI, quindi sono d'accordo. Non appena abbandonerai il primo piano, la tua app potrebbe essere uccisa senza ulteriori avvisi. Devi sempre salvare tutto ciò che conta. D'altra parte, penso che i metodi del ciclo di vita dell'app verranno chiamati indipendentemente dalla tecnica utilizzata per nascondere l'app ma tenerla in giro, quindi non dovrebbe essere necessario aggiungere la logica di salvataggio solo per questo caso. La tua app ha bisogno di quel codice in tutti i posti giusti, indipendentemente.
ToolmakerSteve,

11

fai semplicemente questo ..

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

commentando //super.onBackPressed (); farà il trucco


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

Sì, hai assolutamente ragione. Sostituirà semplicemente il pulsante Indietro e non farà nulla fino a quando non metterai un po 'di logica lì. Potrebbe essere una condizione per premere due volte il pulsante per chiudere l'applicazione o si desidera solo disabilitare un'operazione in corso (finestra di dialogo di avanzamento) ecc., Ma è completamente all'altezza del requisito.
androCoder-BD,

5

Prova questo:

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

3

Nel caso in cui desideri gestire il comportamento del pulsante Indietro (nella parte inferiore del telefono) e del pulsante Home (quello a sinistra della barra delle azioni), questa attività personalizzata che sto usando 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 tua attività:

public class SomeActivity extends BackActivity {

    // ....

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

1
@Override
public void onBackPressed() {
// Put your code here.
}

//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() {
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);
}
Just write this above or below the onCreate Method(within the class)

0

A Kotlin:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    // Handle the back button event
}

Per ulteriori informazioni puoi controllare questo .

C'è anche una domanda specifica sulla sostituzione del pulsante Indietro in Kotlin.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.