Обнаружение кнопки домашнего нажатия в андроиде

Это уже некоторое время подталкивает меня орехами.

Есть ли способ надежного обнаружения, если кнопка home нажата в приложении Android?

В противном случае, есть ли надежный способ узнать, что вызвало активность в onPause? i.e Можем ли мы обнаружить, было ли это вызвано запуском нового действия или нажатием кнопки "Назад/Дом".

Одно из предположений, которое я видел, - это переопределить onPause() и вызвать isFinishing(), но при нажатии кнопки home это будет возвращать false, как если бы оно начиналось, так что это не позволяет отличить эти два.

Любая помощь очень ценится.

** Обновление **: Благодаря @android-hungry для этой ссылки: http://nisha113a5.blogspot.com/

Переопределение следующего метода:

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

Затем следующее событие будет запущено для нажатия кнопок на главной странице:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME)
    {
       //The Code Want to Perform. 
    }
});

Я не уверен, есть ли какие-либо побочные эффекты в этой строке:

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

Таким образом, казалось бы, вопреки распространенному мнению, вы действительно можете услышать домашний ключ. Беспокойно, вы можете вернуть false, а домашний ключ ничего не делает.

Обновление: Как и ожидалось, в этом есть некоторые побочные эффекты - кажется, что встроенные видео и карты Google не отображаются при включенном режиме.

Обновление: Предположительно, этот хак уже не работает с Android 4.0 вперед

Ответ 1

Следующий код работает для меня :)

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 (mReceiver != null) {
            mContext.registerReceiver(mReceiver, mFilter);
        }
    }

    public void stopWatch() {
        if (mReceiver != 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 {
    void onHomePressed();
    void onHomeLongPressed();
}

Ответ 2

Это старый вопрос, но он может помочь кому-то.

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

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

Это работает для меня..:)

Ответ 3

Невозможно обнаружить и/или перехватить кнопку HOME из приложения Android. Это встроено в систему, чтобы предотвратить появление вредоносных приложений, которые не могут быть завершены.

Ответ 4

Мне нужно было запустить/остановить фоновую музыку в моем приложении, когда первая активность открывается и закрывается или когда какое-либо действие приостанавливается кнопкой "домой", а затем возобновляется из диспетчера задач. Чистое воспроизведение/возобновление воспроизведения в Activity.onPause() и Activity.onResume() прерывало музыку некоторое время, поэтому мне пришлось написать следующий код:

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

который прерывает воспроизведение только тогда, когда приложение (все его действия) закрыто или нажата кнопка дома. К сожалению, мне не удалось изменить порядок вызовов метода onPause() начального действия и onResume() запущенной actvity, когда Activity.startActivity() вызывается (или обнаруживает в onPause(), что действие запускает другое действие другим способом) поэтому этот случай нужно обрабатывать специально:

private boolean mIsStarting;

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

Другим недостатком является то, что для этого требуется GET_TASKS разрешение, добавленное в AndroidManifest.xml:

<uses-permission
  android:name="android.permission.GET_TASKS"/>

Модификация этого кода, который он реагирует только на нажатие кнопки "домой", находится в напряжении.

Ответ 5

Переопределить onUserLeaveHint() в действии. Никогда не будет никакого обратного вызова для активности, когда на нее наступит новое действие или пользователь нажмет кнопку "Назад".

Ответ 6

Попробуйте создать счетчик для каждого экрана. Если пользователь коснется ДОМОЙ, то счетчик будет равен нулю.

public void onStart() {
  super.onStart();
  counter++;
}

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

Ответ 7

Вы можете рассмотреть решение Андреаса Шрейда в своем посте "Как создать рабочий режим киоска" на Android. Это немного взломанно, но с учетом причин, по которым предотвращается перехват домашней кнопки, она должна быть;)

Ответ 8

У меня была эта проблема, и поскольку переопределение метода onKeyDown() ничего не выполняло из-за того, что базовая система Android не вызывала этот метод, я решил это с переопределением onBackPressed(), и у меня было задано значение boolean там к false, потому что я нажал назад, позвольте мне показать вам, что я имею в виду в коде:

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

Итак, причина, по которой это сработало, заключается в том, что единственный способ передвигаться вне этой активности - это вернуться назад или домой, поэтому, если была нажата, тогда я знаю, что причина не была дома, но в противном случае причина была дома, поэтому я установил значение по умолчанию для boolean для homePressed должно быть истинным. Однако это будет работать только с одним экземпляром действия в вашем приложении, потому что в противном случае у вас будет больше возможностей вызвать метод onPause().

Ответ 9

Начиная с API 14 вы можете использовать функцию onTrimMemory() и проверить наличие флага TRIM_MEMORY_UI_HIDDEN. Это скажет вам, что ваше приложение идет в фоновом режиме.

Так что в вашем собственном классе Application вы можете написать что-то вроде:

override fun onTrimMemory(level: Int) {
    if (level == TRIM_MEMORY_UI_HIDDEN) {
        // Application going to background, do something
    }
}

Для более глубокого изучения этого, я предлагаю вам прочитать эту статью: http://www.developerphil.com/no-you-can-not-override-the-home-button-but-you-dont-have -в/

Ответ 10

onUserLeaveHint();

переопределить этот метод класса активности. Это обнаружит щелчок на домашнем ключе. Этот метод вызывается непосредственно перед действием onPause() callback. Но он не будет вызываться, когда действие прерывается, так как активность в вызове выходит на передний план, кроме тех прерываний, которые он вызывается, когда пользователь нажимает домашний ключ.

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

Ответ 11

Вариантом для вашего приложения было бы написать начальный экран замены, используя намерение android.intent.category.HOME. Я считаю, что этот тип намерения вы можете увидеть домашнюю кнопку.

Подробнее:

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

Ответ 12

Среднее приложение может прекрасно ладить без необходимости знать разницу между прессом Home и событием паузы. Другими словами, onPause() обычно является достаточным.

Почему вы хотите это сделать? Предоставление нам дополнительной информации о ваших намерениях может привести к лучшей общей стратегии для вас.

Ответ 13

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

Например, попробовали ли вы применить атрибут android: clearTaskOnLaunch = "true" к вашей активности запуска, возможно, в тандеме с android: launchMode = "singleInstance" ?

Задачи и Back Stack - отличный ресурс для тонкой настройки такого поведения.

Ответ 14

Неплохая идея изменить поведение домашнего ключа. Вот почему Google не позволяет переопределять домашний ключ. Я вообще не буду возиться с ключом дома. Вам нужно дать пользователю возможность выйти из вашего приложения, если он по какой-либо причине уходит в сорняки.

Я хотел бы, чтобы у любой работы были нежелательные побочные эффекты.

Ответ 15

override метод onUserLeaveHint может перехватить событие домашнего пресса, но вам также нужно учитывать события щелчка пользователя. следующие коды работают для меня.

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

Ответ 16

Недавно я пытался обнаружить кнопку домашнего нажатия, потому что мне нужно было сделать то же самое, что и метод " onBackPressed() ". Для этого мне пришлось переопределить метод " onSupportNavigateUp() " следующим образом:

override fun onSupportNavigateUp(): Boolean {
    onBackPressed()
    return true
}

Это сработало отлично. знак равно

Ответ 17

Джек ответ отлично работает для click события в то время как longClick рассматривает как menu кнопки.

Кстати, если кто-то задается вопросом, как это сделать через kotlin,

class HomeButtonReceiver(private var context: Context,private var listener: OnHomeButtonClickListener) {
    private val mFilter: IntentFilter = IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
    private var mReceiver: InnerReceiver = InnerReceiver()

    fun startWatch() {
        context.registerReceiver(mReceiver, mFilter)
    }

    fun stopWatch() {
        context.unregisterReceiver(mReceiver)
    }

    inner class InnerReceiver: BroadcastReceiver() {
        private val systemDialogReasonKey = "reason"
        private val systemDialogReasonHomeKey = "homekey"
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action
            if (action == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) {
                val reason = intent.getStringExtra(systemDialogReasonKey)
                if (reason != null && reason == systemDialogReasonHomeKey) {
                    listener.onHomeButtonClick()
                }
            }
        }
    } 
}

Ответ 18

Это помощь для меня.

На самом деле, этот метод срабатывает, когда вы нажимаете кнопку HOME или когда что-то прерывает ваше приложение

@Override
    protected void onUserLeaveHint() {
        super.onUserLeaveHint();
        Log.e(TAG, "onUserLeaveHint: Home button pressed");
        Toast.makeText(this, "home button press", Toast.LENGTH_SHORT).show();
    }

Ответ 19

enter image description here  Ключ Android Home, управляемый слоем фреймворка, вы не можете справиться с этим на уровне приложения. Потому что действие кнопки домой уже определено на нижнем уровне. Но если вы разрабатываете свой собственный ROM, то это может быть возможно. Google ограничил функции отмены КНОПКИ HOME из соображений безопасности.