162

Actualmente tengo una actividad que cuando se muestra una notificación también se mostrará en la barra de notificaciones.Android - Cómo anular el botón "Atrás" para que no termine() mi actividad?

Esto es para que cuando el usuario presione Inicio y la actividad se pase al fondo puedan volver a la actividad mediante la notificación.

El problema surge cuando un usuario presiona el botón Atrás, mi actividad se destruye pero la notificación se mantiene porque quiero que el usuario pueda retroceder pero aún así poder acceder a la actividad mediante la notificación. Pero cuando un USUARIO prueba esto, obtengo Null Pointers porque está intentando iniciar una nueva actividad en lugar de recuperar la anterior.

Así que, esencialmente Quiero el botón Atrás para actuar exactamente el mismo que el botón de inicio y así es como he intentado hasta ahora:


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

Sin embargo el código anterior parece que todavía Permitir que se destruya mi actividad. ¿Cómo puedo evitar que mi actividad se destruya cuando se presiona el botón Atrás?

+0

Hay una pregunta similar: http://stackoverflow.com/questions/2459848/android-prompt-user-to-save-changes- when-back-button-is-pressed – aleung

+1

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

+0

También creo que debe cambiar su código a 'if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5', el' <'debe convertirse en un'> '. – SudoPlz

Respuesta

229

Quite su oyente de clave o devuelva true cuando tenga KEY_BACK.

Solo necesita lo siguiente para capturar la tecla Atrás (Asegúrese de no llamar a super en onBackPressed()).

Además, si planea ejecutar un servicio en segundo plano, asegúrese de mirar startForeground() y asegúrese de tener una notificación en curso o de lo contrario, Android matará a su servicio si necesita liberar 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

Creo que lo que quiere es no anular el botón Atrás (eso no parece una buena idea - el sistema operativo Android define ese comportamiento, ¿por qué cambiarlo?), Pero para usar el Activity Lifecycle y persistir su configuración/datos en el evento onSaveInstanceState(Bundle).

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

continuación, utiliza onCreate(Bundle) para conseguir todo de que persistió paquete y recrear su estado.

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

Considere el código psuedo anterior para apuntarle en la dirección correcta. Leer en el Activity Lifecycle debería ayudarlo a determinar la mejor manera de lograr lo que está buscando.

+0

Hola Kiswa, esto es cierto, no quiero cambiar el comportamiento predeterminado. He intentado usar onSavedInstanceState y no funcionaba, pero creo que he detectado mi error ahora. Gracias –

+5

He encontrado al menos algunas situaciones en las que quería simular el comportamiento de la pila de actividades estándar sin realmente iniciar nuevas actividades. En estos casos, creo que es apropiado anular el comportamiento predeterminado deBackPressed(). En general, sin embargo, estoy de acuerdo: evite anular. –

+4

Estoy de acuerdo con @Matt. Actualmente estoy trabajando en un juego de plataforma cruzada que usa el NDK. Como tal, es más fácil si todo es una sola actividad. Debido a esto, el comportamiento predeterminado del botón Atrás es escapar de la aplicación, que no es lo que la mayoría de los usuarios esperan. Así que tuve que sobrescribir el comportamiento predeterminado para que la actividad se comportara de manera diferente, como si el usuario realmente hubiera ido a una actividad diferente, y solo salga de la aplicación en ciertas circunstancias. –

46

que era más fácil de implementar que sólo con una línea de código:

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

Esta debería ser la respuesta aceptada. Esto hace exactamente lo que la pregunta está haciendo y está usando la funcionalidad limpia integrada. – Shadoninja

+0

Gracias :) ¿puedes elaborar el concepto detrás de esto? –

+0

Simplemente anula el evento onBackPressed(), haciendo que mueva la actividad a la parte posterior. – Squirrelkiller

8

simplemente hacer esto ..

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

comentando la // súper.onBackPressed(); hará el truco

+1

Una observación útil, pero ¿no hará esto que el botón Atrás no haga nada en absoluto, como si estuviera roto? Eso no es algo bueno, confuso y molesto para los usuarios. En mi humilde opinión, debo agregar la lógica de otra respuesta, para actuar como el botón de Inicio, tal como se solicitó en la pregunta. La respuesta aceptada * menciona * que deliberadamente no llamaban supermétodo. – ToolmakerSteve

+0

Sí, tiene toda la razón. Simplemente anulará el botón Atrás y no hará nada hasta que ponga algo de lógica allí. Puede ser una condición para presionar dos veces el botón para cerrar la aplicación o simplemente desea deshabilitar una operación en curso (diálogo de progreso), etc., pero está completamente a la altura de los requisitos. –

1

Prueba esto:

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

Esto es muy divertido. –

0

En caso de que desea manejar el comportamiento del botón de retroceso (en la parte inferior del teléfono) y el botón de inicio (el que está a la izquierda de la barra de acciones), esta actividad personalizada que estoy usando en mi proyecto puede ayudarlo.

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

Ejemplo de uso en su actividad:

public class SomeActivity extends BackActivity { 

    // .... 

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