162

J'ai actuellement une activité qui, lorsqu'elle sera affichée, affichera également une notification dans la barre de notification. Il en résulte que lorsque l'utilisateur appuie à la maison et que l'activité est mise en arrière-plan, il peut revenir à l'activité via la notification. Le problème survient lorsqu'un utilisateur appuie sur le bouton de retour, mon activité est détruite mais la notification reste telle que je souhaite que l'utilisateur puisse appuyer de nouveau sur la touche, tout en restant capable d'accéder à l'activité via la notification. Mais quand un UTILISATEUR essaie ceci, j'obtiens Null Pointers en essayant de démarrer une nouvelle activité plutôt que de ramener l'ancienne.Android - Comment remplacer le bouton "Précédent" pour qu'il ne finisse pas() mon activité?

Je veux donc essentiellement le bouton Précédent pour agir exactement le même que le bouton Home et voici comment je l'ai essayé jusqu'à présent:


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

Cependant, le code ci-dessus semble encore permettre à mon activité d'être détruite, comment puis-je empêcher mon activité d'être détruite quand le bouton de retour est enfoncé?

+0

Il y a une question similaire: http://stackoverflow.com/questions/2459848/android-prompt-user-to-save-changes- quand-bouton-arrière-est-pressé – aleung

+1

Réponse similaire .. http://stackoverflow.com/questions/5914040/onbackpressed-to-hide-not-destroy-activity/23759328#23759328 – Nepster

+0

Aussi je pense que vous devez changer votre code à 'if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5', le' <'devrait devenir un'> '. – SudoPlz

Répondre

229

Supprimez votre programme d'écoute de touche ou renvoyez true lorsque vous avez KEY_BACK.

Vous avez juste besoin de ce qui suit pour attraper la touche de retour (Assurez-vous de ne pas appeler super dans onBackPressed()). De plus, si vous envisagez d'exécuter un service en arrière-plan, veillez à consulter le startForeground() et assurez-vous d'avoir une notification en cours, sinon Android supprimera votre service s'il a besoin de libérer de la mémoire.

@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

Je pense que ce que vous voulez est de ne pas remplacer le bouton de retour (cela ne semble pas une bonne idée - Android OS définit ce comportement, pourquoi le changer?), Mais d'utiliser le Activity Lifecycle et persister vos paramètres/données dans l'événement onSaveInstanceState(Bundle).

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

Ensuite, vous utilisez onCreate(Bundle) pour obtenir tout de ce paquet a persisté et recréez votre état. Considérez le code de pseudo ci-dessus pour vous orienter dans la bonne direction. Lire sur le Activity Lifecycle devrait vous aider à déterminer la meilleure façon d'accomplir ce que vous cherchez.

+0

Salut Kiswa, c'est vrai, je ne veux pas changer le comportement par défaut. J'ai essayé d'utiliser le onSavedInstanceState et cela ne fonctionnait pas mais je crois avoir repéré mon erreur maintenant. Merci –

+5

J'ai rencontré au moins quelques situations où je voulais simuler le comportement de la pile d'activité standard sans réellement démarrer de nouvelles activités. Dans ces cas, je pense, il est approprié de remplacer le comportement par défaut onBackPressed(). En général, cependant, je suis d'accord: éviter de surcharger. –

+4

Je suis d'accord avec @Matt. Je travaille actuellement sur un jeu multi-plateforme qui utilise le NDK. En tant que tel, il est plus facile si tout est une seule activité. Pour cette raison, le comportement par défaut du bouton de retour est d'échapper à l'application, ce qui n'est pas ce à quoi la plupart des utilisateurs s'attendent. J'ai donc dû remplacer le comportement par défaut pour que l'activité se comporte différemment, comme si l'utilisateur était réellement allé à une activité différente, et seulement quitter l'application dans certains cas. –

46

Il était plus facile à mettre en œuvre avec une seule ligne de code:

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

Ceci devrait être la réponse acceptée. Cela fait exactement ce que la question demande et utilise une fonctionnalité intégrée propre. – Shadoninja

+0

Merci :) pouvez-vous élaborer le concept derrière? –

+0

Vous remplacez simplement l'événement onBackPressed(), ce qui le fait passer l'activité à l'arrière. – Squirrelkiller

8

Il suffit de faire ce ..

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

commentant la // super.onBackPressed(); fera l'affaire

+1

Une observation utile, mais est-ce que le bouton de retour ne fera rien du tout, comme s'il était cassé? Ce n'est pas une bonne chose à faire - déroutant et agaçant pour les utilisateurs. À mon humble avis doit ajouter la logique d'une autre réponse, pour agir comme bouton d'accueil, comme cela a été demandé en question. La réponse acceptée * mentionne * qu'ils n'appelaient délibérément pas super méthode. – ToolmakerSteve

+0

Oui, vous avez absolument raison. Il va simplement remplacer le bouton de retour et ne fera rien tant que vous n'aurez pas mis de la logique là-bas. Peut être une condition pour appuyer deux fois sur le bouton pour fermer l'application ou vous voulez juste désactiver une opération en cours (boîte de dialogue de progression) etc., mais c'est complètement à la hauteur de l'exigence. –

1

Essayez ceci:

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

C'est tellement drôle. –

0

Juste au cas où vous voulez gérer le comportement du bouton de retour (en bas du téléphone) et le bouton d'accueil (celui à gauche la barre d'action), cette activité personnalisée que j'utilise dans mon projet peut vous aider.

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

Exemple d'utilisation dans votre activité:

public class SomeActivity extends BackActivity { 

    // .... 

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