studio - Detecta el botón de inicio presiona en Android
manual de programacion android pdf (14)
Anular onUserLeaveHint()
en la actividad. Nunca se volverá a llamar a la actividad cuando aparezca una nueva actividad o el usuario presione nuevamente.
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
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 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.
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 InnerRecevier mRecevier;
public HomeWatcher(Context context) {
mContext = context;
mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
}
public void setOnHomePressedListener(OnHomePressedListener listener) {
mListener = listener;
mRecevier = new InnerRecevier();
}
public void startWatch() {
if (mRecevier != null) {
mContext.registerReceiver(mRecevier, mFilter);
}
}
public void stopWatch() {
if (mRecevier != null) {
mContext.unregisterReceiver(mRecevier);
}
}
class InnerRecevier 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();
}
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.
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í ... :)
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..
}
}
La aplicación promedio puede llevarse bien sin necesidad de saber la diferencia entre una prensa hogareña y un evento de pausa. En otras palabras, onPause () suele ser suficiente.
¿Por qué quieres hacer esto? Dándonos más información sobre sus intenciones podría conducir a una mejor estrategia general para usted.
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<ActivityManager.RunningTaskInfo> 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
:
<uses-permission
android:name="android.permission.GET_TASKS"/>
La modificación de este código que solo reacciona al presionar el botón de inicio es directo.
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.
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 ().
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
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.
}
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");
}