Как я могу определить, как пользователь нажимает клавишу HOME в моей деятельности?

Не могли бы вы рассказать мне, как моя активность может обнаружить пользователя нажатием клавиши HOME?

Спасибо.

11 ответов

Обновление [Август 2015]: согласно комментарию JM Lord, этот ответ может работать не так, как хотелось бы, для устройств Lollipop и выше, См. Альтернатива getRunningTasks в Android L

Хотя, старый вопрос, но большинство ответов не работало для меня в API уровня 17 и выше. Я отвечаю, что в конечном итоге сработало для меня. Я пробовал много методов, но ни один из них не работает как сегодня. Я пробовал ответы на

Вызов метода, когда кнопка home нажата на андроид,

Отключить домашнюю кнопку нажмите на android и

Переопределение кнопки "Главная" - как мне избавиться от выбора?. Суть в том, что Home - это как кнопка аварийного выхода. Поэтому вы не можете переопределить его, но можете обнаружить его в некотором роде.

Некоторые из тех, что я пробовал (включая ответы выше) и не работают:

  • Использование keyCode==KeyEvent.KEYCODE_HOME во многом указано выше. Теперь, если вы прочтете документацию KeyEvent.KEYCODE_HOME, он говорит, что This key is handled by the framework and is never delivered to applications. Так что его больше нет действительный сейчас.

  • Я пробовал использовать onUserLeaveHint(). В документации указано:

    Вызывается как часть жизненного цикла активности, когда активность чтобы выйти на задний план в результате выбора пользователя. Например, когда пользователь нажимает клавишу "Домой", onUserLeaveHint() будет но когда входящий телефонный вызов вызывает активность в вызове для автоматического перехода на передний план.

    Проблема в том, что метод также вызывается при запуске Activity из того, в котором вы вызываете onUserleaveLint(), как и в моем случае. Подробнее см. Android onBackPressed/onUserLeaveHint. Поэтому он не уверен, что он будет называться ТОЛЬКО, нажав кнопку "домой".

  • Вызов onStop(). Его также можно назвать, когда деятельность происходит поверх существующей деятельности и полностью ее охватывает. Так что это тоже не сработает.

Наконец, выполнил для меня:

Увидев Как проверить текущие запущенные приложения на Android?, вы можете сказать, что если ваша недавняя задача показана при длительном нажатии кнопки "домой", отправьте на задний план.

Итак, в вашей onPause() активности, в которой вы пытаетесь обнаружить кнопку дома, вы можете проверить, было ли приложение отправлено на задний план.

@Override
public void onPause() {
 if (isApplicationSentToBackground(this)){
 // Do what you want to do on detecting Home Key being Pressed 
 }
 super.onPause();
}

Функция, чтобы проверить, было ли ваше приложение, которое было недавно отправлено на задний план:

public boolean isApplicationSentToBackground(final Context context) {
 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
 List<runningtaskinfo> tasks = am.getRunningTasks(1);
 if (!tasks.isEmpty()) {
 ComponentName topActivity = tasks.get(0).topActivity;
 if (!topActivity.getPackageName().equals(context.getPackageName())) {
 return true;
 }
 }
 return false;
}
</runningtaskinfo>

Благодаря @idish, указав, что не забудьте включить в свой манифест следующее разрешение:

Я не уверен, есть ли какие-то недостатки, но это сработало для меня хорошо. Надеюсь, это когда-нибудь поможет кому-нибудь.

P.S: Если вы используете этот метод в Activity, который был запущен с флагом FLAG_ACTIVITY_NO_HISTORY, тогда это не будет полезно, поскольку он проверяет недавнюю историю для выяснения, была ли нажата кнопка Home.


Вы можете обнаружить нажатие кнопки HOME через Activity.onUserLeaveHint(). Этот метод вызывается в двух ситуациях; когда пользователь нажимает HOME и когда начинается новое действие. Убедитесь, что они каким-то образом отличаются друг от друга.


Формального способа уведомления о нажатии клавиши "HOME" не существует. Но есть довольно простая работа, чтобы ваше приложение отличалось нажатием клавиши "HOME" и любым другим действием, которое могло бы остановить действие.

Для каждого класса, который должен выполнить какое-либо действие над клавишей "HOME", нажмите, чтобы они расширились от действия, которое содержит следующее:

/**************************************** On Home **********************************/
private boolean leaveCalled = false;
@Override
public void startActivity(Intent intent) { 
 leaveCalled= true;
 super.startActivity(intent);
}
@Override
public void onBackPressed() {
 leaveCalled = true;
 super.onBackPressed();
}
@Override
protected void onStop() { 
 super.onStop();
 // Home button pressed
 if(!leaveCalled) {
 // Do whatever you like.
 }
 leaveCalled = false;
}

ИЗМЕНИТЬ

Вам также необходимо расширить свои фрагменты из родительского класса, который содержит это. Это связано с тем, что фрагменты в противном случае обеспечивали бы дополнительный маршрут для переключения между действиями в вашем приложении в ожидаемом, а не "HOME" способом.

@Override
public void startActivity(Intent intent) { 
 getActivity().startActivity(intent);
}

РЕДАКТИРОВАТЬ 2

Я приближаюсь к мысли, что это не самый простой способ справиться с этим... Вам нужно также добавить onConfigurationChange = "orientation" ко всем вашим действиям, которые используют этот метод. Затем вы можете добавить это:

@Override
public void onConfigurationChanged(Configuration newConfig) { 
 super.onConfigurationChanged(newConfig);
 leaveCalled = true; 
 finish();
 startActivity(getIntent()); 
}

РЕДАКТИРОВАТЬ 3

Urgh

@Override
public void finish() {
 leaveCalled = true;
 super.finish();
}


Вы не можете зафиксировать событие HOME и каким-либо образом перехватить его. Пользователь всегда будет доставлен на главный экран своего устройства, когда они нажимают домашний ключ.

Если вам нужно знать, когда ваша активность отправляется на задний план, например, от пользователя, нажимая на главную или обратно клавиши, я бы выполнил метод onStop().


использовать метод onUserLeaveHint() в вашей деятельности

@Override
protected void onUserLeaveHint()
{
 super.onUserLeaveHint();
}

http://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()


Это можно сделать (uptil 2.3 atleast). Протестировано на Android-версии 2.3.5 без троса HTC WildFire-S. Фрагмент кода для блокировки/отключения всех клавиш управления:

@Override
public void onAttachedToWindow() {
 super.onAttachedToWindow(); 
 this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
}
public boolean onKeyDown(int keyCode, KeyEvent event) { 
 if(keyCode == KeyEvent.KEYCODE_HOME || keyCode == KeyEvent.KEYCODE_POWER || keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_SEARCH )
 {
 Toast.makeText(getApplicationContext(),"You pressed a control button with keyCode : " + keyCode, Toast.LENGTH_SHORT).show();
 return false;
 }
 else
 {
 Toast.makeText(getApplicationContext(),"You pressed" + keyCode, Toast.LENGTH_SHORT).show();
 }
 return true;
}
public boolean onKeyUp(int keyCode, KeyEvent event) { 
 if(keyCode == KeyEvent.KEYCODE_HOME || keyCode == KeyEvent.KEYCODE_POWER || keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_SEARCH )
 {
 return false;
 }
 else
 {
 // Do nothing
 }
 return true;
}


Вы можете написать прослушиватель Broadcast и установить фильтр на

Из приемника широковещательной передачи запустите активность/уведомление активности.


Я нашел это решение на основе предложения @Springfeed. При этом вопрос достаточно общий, обратите внимание, что это конкретное решение будет:

  • Работайте с Lollipop, а также с более низкими версиями Android (мой код прецедента, основанный на ActivityManager, не выполнен на Lollipop)
  • Захватывает кнопки "Главная" и "История"
  • Не будет захвачен Дом, если сама деятельность определена как Главная - Всегда
  • Захват дома, если активность является одним из многих домашних параметров или вообще не является домашним.

Этот код находится в моем базовом классе Activity (из которого наследуются все действия)

public boolean startingActivity = false;
 @Override
 protected void onUserLeaveHint()
 {
 if(startingActivity)
 {
 // Reset boolean for next time
 startingActivity = false;
 }
 else
 {
 // User is exiting to another application, do what you want here
 Log.i(TAG, "Exiting");
 ...
 }
 }
 @Override
 public void startActivity(Intent intent)
 {
 startingActivity = true;
 super.startActivity(intent);
 }
 @Override
 public void startActivityForResult(Intent intent, int requestCode)
 {
 startingActivity = true;
 super.startActivityForResult(intent, requestCode);
 }

Как некоторые методы могут также использовать контекст приложения для запуска намерений, я определил ContextWrapper, который был проведен моим классом Application, чтобы также переключить логическое (заметьте, что у меня есть статический доступ к самой верхней активности моего собственного приложения через этот базовый класс).

public class MyContext extends ContextWrapper
{
 public MyContext(Context base)
 {
 super(base);
 }
 @Override
 public void startActivity(Intent intent)
 {
 BaseActivity activity = BaseActivity.getActivity();
 if(activity != null)
 {
 activity.startingActivity = true;
 }
 super.startActivity(intent);
 }
}

Можно также переопределить startActivities (...), если это необходимо.

Надеюсь, что это поможет:)


android.text.method.KeyListener.onKeyDown([view],[text],KEYCODE_HOME,[event])

Я не уверен, как вписываются другие параметры или даже как реализовать вышеописанное, но информация все в keylistner документация.

Но они также упоминают в другую страницу, что домашний ключ ВСЕГДА идет домой, вы не можете это изменить. Поэтому, если вы планируете иметь какой-то диалог "вы уверены, что хотите выйти", это не сработает.


public boolean isApplicationSentToBackground(final Context context) {
 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
 List<runningtaskinfo> tasks = am.getRunningTasks(1);
 if (!tasks.isEmpty()) {
 ComponentName topActivity = tasks.get(0).topActivity;
 if (!topActivity.getPackageName().equals(context.getPackageName())) {
 return true;
 }
 }
 return false;
 }
 public void onPause() {
 super.onPause();
 if(isApplicationSentToBackground(this))
 {
 Log.i("Home", "Home Pressed..!");
 }
 }
</runningtaskinfo>


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

licensed under cc by-sa 3.0 with attribution.