Detecta el botón de inicio presiona en Android

Esto me ha estado volviendo loco durante un tiempo.

¿Hay alguna forma de detectar de manera confiable si se presionó el botón de inicio en una aplicación de Android?

En su defecto, ¿hay alguna forma sólida de decir qué causó que una actividad entrara en Pausa? es decir, ¿podemos detectar si fue causado por un nuevo lanzamiento de actividad o presionando back / home.

Una sugerencia que he visto es anular onPause () y llamar a isFinishing () pero esto devolverá falso al presionar el botón de inicio como lo haría si se inicia una nueva actividad, por lo que no se puede distinguir entre los dos.

Cualquier ayuda muy apreciada.

** Actualización **: gracias a @ android-hungry para este enlace: http://nisha113a5.blogspot.com/

Sobrevalorando el siguiente método:

@Override public void onAttachedToWindow() { super.onAttachedToWindow(); this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); } 

Luego, el siguiente evento será despedido para presionar botones de inicio:

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_HOME) { //The Code Want to Perform. } }); 

No estoy seguro de si hay algún efecto secundario con esta línea:

 this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); 

Por lo tanto, parece que, contrario a la creencia popular, de hecho puedes escuchar la clave de inicio. Preocupantemente, puede devolver falso y tener la tecla de inicio no hacer nada.

Actualización : como se esperaba, hay algunos efectos secundarios con esto: parece que los videos incrustados y los mapas de Google no son visibles con este modo habilitado.

Actualización : supuestamente este truco ya no funciona a partir de Android 4.0 en adelante

El siguiente código funciona para mí 🙂

 HomeWatcher mHomeWatcher = new HomeWatcher(this); mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() { @Override public void onHomePressed() { // do something here... } @Override public void onHomeLongPressed() { } }); mHomeWatcher.startWatch(); 
 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; public class HomeWatcher { static final String TAG = "hg"; private Context mContext; private IntentFilter mFilter; private OnHomePressedListener mListener; private InnerReceiver mReceiver; public HomeWatcher(Context context) { mContext = context; mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); } public void setOnHomePressedListener(OnHomePressedListener listener) { mListener = listener; mReceiver = new InnerReceiver(); } public void startWatch() { if (mRecevier != null) { mContext.registerReceiver(mReceiver, mFilter); } } public void stopWatch() { if (mRecevier != null) { mContext.unregisterReceiver(mReceiver); } } class InnerReceiver extends BroadcastReceiver { final String SYSTEM_DIALOG_REASON_KEY = "reason"; final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY); if (reason != null) { Log.e(TAG, "action:" + action + ",reason:" + reason); if (mListener != null) { if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) { mListener.onHomePressed(); } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { mListener.onHomeLongPressed(); } } } } } } } 
 public interface OnHomePressedListener { public void onHomePressed(); public void onHomeLongPressed(); } 

Esta es una vieja pregunta, pero podría ayudar a alguien.

 @Override protected void onUserLeaveHint() { Log.d("onUserLeaveHint","Home button pressed"); super.onUserLeaveHint(); } 

De acuerdo con la documentación, se llama al método onUserLeaveHint () cuando el usuario hace clic en el botón de inicio O cuando algo interrumpe su aplicación (como una llamada de teléfono entrante).

Esto funciona para mí … 🙂

Es imposible detectar y / o interceptar el botón INICIO desde dentro de una aplicación de Android. Esto está integrado en el sistema para evitar aplicaciones maliciosas que no pueden salir.

Necesitaba iniciar / detener la música de fondo en mi aplicación cuando se abre y cierra la primera actividad, o cuando cualquier actividad se pausa con el botón de inicio y luego se reanuda desde el administrador de tareas. La reproducción pura detener / reanudar en Activity.onPause() y Activity.onResume() interrumpió la música por un tiempo, así que tuve que escribir el siguiente código:

 @Override public void onResume() { super.onResume(); // start playback here (if not playing already) } @Override public void onPause() { super.onPause(); ActivityManager manager = (ActivityManager) this.getSystemService(Activity.ACTIVITY_SERVICE); List tasks = manager.getRunningTasks(Integer.MAX_VALUE); boolean is_finishing = this.isFinishing(); boolean is_last = false; boolean is_topmost = false; for (ActivityManager.RunningTaskInfo task : tasks) { if (task.topActivity.getPackageName().startsWith("cz.matelier.skolasmyku")) { is_last = task.numRunning == 1; is_topmost = task.topActivity.equals(this.getComponentName()); break; } } if ((is_finishing && is_last) || (!is_finishing && is_topmost && !mIsStarting)) { mIsStarting = false; // stop playback here } } 

que interrumpe la reproducción solo cuando la aplicación (todas sus actividades) está cerrada o cuando se presiona el botón de inicio. Desafortunadamente no logré cambiar el orden de las llamadas del método onPause() de la actividad inicial y onResume() de la actividad iniciada cuando se llama a Activity.startActivity() (o detectar en onPause() esa actividad está lanzando otra actividad otra manera) por lo que este caso debe manejarse especialmente:

 private boolean mIsStarting; @Override public void startActivity(Intent intent) { mIsStarting = true; super.startActivity(intent); } 

Otro inconveniente es que esto requiere el permiso GET_TASKS agregado a AndroidManifest.xml :

  

La modificación de este código que solo reactjs al presionar el botón de inicio es directo.

Anular onUserLeaveHint() en la actividad. Nunca se volverá a llamar a la actividad cuando aparezca una nueva actividad o el usuario presione nuevamente.

Intenta crear un contador para cada pantalla. Si el usuario toca INICIO, entonces el contador será cero.

 public void onStart() { super.onStart(); counter++; } public void onStop() { super.onStop(); counter--; if (counter == 0) { // Do.. } } 

Puede considerar una solución de Andreas Shrade en su publicación sobre cómo crear un modo de quiosco de trabajo en Android . Es un poco hacky, pero teniendo en cuenta las razones por las que se impide la interceptación del botón de inicio, tiene que ser;)

Tuve este problema, y ​​dado que anular el método onKeyDown () no logró nada debido a que el sistema android subyacente no llamó a este método, lo resolví con la anulación de onBackPressed (), y tuve un valor booleano establecido en false , porque presioné hacia atrás, déjame mostrarte lo que quiero decir en código:

 import android.util.Log; public class HomeButtonActivity extends Activity { boolean homePressed = false; // override onCreate() here. @Override public void onBackPressed() { homePressed = false; // simply set homePressed to false } @Overide public void onResume() { super.onResume(); homePressed = true; // default: other wise onBackPressed will set it to false } @Override public void onPause() { super.onPause(); if(homePressed) { Log.i("homePressed", "yay"); } } 

Entonces, la razón por la que esto funcionó es porque la única forma de navegar fuera de esta actividad es presionar hacia atrás o hacia la casa, así que si se presionó, entonces sé que la causa no estaba en casa, pero la causa fue el hogar, por lo tanto configuré el booleano predeterminado valor para el hogarPresionado para ser cierto. Sin embargo, esto solo funcionará con una sola instancia de actividad en su aplicación, ya que de lo contrario tendrá más posibilidades de hacer que se invoque el método onPause ().

onUserLeaveHint ();

anula este método de clase de actividad. Esto detectará el clic de la tecla de inicio. Este método se llama justo antes de la activación de OnPause () de la actividad. Pero no se ejecutará cuando se interrumpa una actividad, como una actividad en llamada entra en primer plano, aparte de esas interrupciones llamará cuando el usuario haga clic en la tecla de inicio.

 @Override protected void onUserLeaveHint() { super.onUserLeaveHint(); Log.d(TAG, "home key clicked"); } 

Una opción para su aplicación sería escribir una Pantalla de inicio de reemplazo utilizando android.intent.category.HOME Intent. Creo que este tipo de intención puede ver el botón de inicio.

Más detalles:

http://developer.android.com/guide/topics/intents/intents-filters.html#imatch

Como solo desea que la actividad raíz se vuelva a ver cuando se inicia la aplicación, ¿puede obtener este comportamiento cambiando los modos de inicio, etc., en el manifiesto?

Por ejemplo, ¿ha intentado aplicar el atributo android: clearTaskOnLaunch = “true” a su actividad de inicio, tal vez en conjunto con android: launchMode = “singleInstance” ?

Tareas y Back Stack es un gran recurso para ajustar este tipo de comportamiento.

No es una buena idea cambiar el comportamiento de la tecla de inicio. Esta es la razón por la que Google no le permite anular la clave de inicio. No me meteré con la tecla de inicio en general. Necesitas darle al usuario una manera de salir de tu aplicación si se interrumpe en las malas hierbas por cualquier razón.

Me imagino cualquier trabajo alrededor tendrá efectos secundarios no deseados.

anular el método UserLeaveHint puede atrapar el evento de prensa hogareña, pero también debe considerar los eventos de clic de usuario. los siguientes códigos funcionan para mí.

 private boolean isUserClickToLeave = false; private Handler mHandler = new Handler(); Runnable resetUserClickFlagRunnable = new Runnable() { @Override public void run() { isUserClickToLeave = false; } }; @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) { isUserClickToLeave = true; mHandler.removeCallbacks(resetUserClickFlagRunnable); mHandler.postDelayed(resetUserClickFlagRunnable, 1000); } return super.dispatchTouchEvent(ev); } @Override protected void onUserLeaveHint() { super.onUserLeaveHint(); if (!isUserClickToLeave ) { //user press home button case. onHomePressed(); } isUserClickToLeave = false; } private onHomePressed() { //do something here. }