在机器人中检测主按钮

这件事已经让我抓狂一段时间了。

是否有任何方法可靠地检测如果主页按钮已被按下在一个 Android 应用程序?

如果做不到这一点,是否有一种强有力的方法来判断是什么导致一个活动进入暂停状态?我们能否检测出这是由于一个新的活动发起或按回/家造成的。

我看到的一个建议是覆盖 onPause ()并调用 isFinishing () ,但是当按下 home 按钮时,这将返回 false,就像当一个新活动开始时一样,因此这无法区分两者。

非常感谢你的帮助。

* * 更新 * * : 感谢@android 饥渴的链接: < a href = “ http://nisha113a5.blogspot.com/”rel = “ norefrer”> https://nishandroid.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 并且让 home 密钥什么也不做。

更新 : 正如所料,有一些副作用与此-似乎嵌入式视频和谷歌地图是不可见的这种模式启用。

更新 : 据推测,从 Android 4.0开始,这种黑客手段就不再起作用了

155594 次浏览

It is impossible to detect and/or intercept the HOME button from within an Android app. This is built into the system to prevent malicious apps that cannot be exited.

An option for your application would be to write a replacement Home Screen using the android.intent.category.HOME Intent. I believe this type of Intent you can see the home button.

More details:

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

Since you only wish for the root activity to be reshown when the app is launched, maybe you can get this behavior by changing launch modes, etc. in the manifest?

For instance, have you tried applying the android:clearTaskOnLaunch="true" attribute to your launch activity, perhaps in tandem with android:launchMode="singleInstance"?

Tasks and Back Stack is a great resource for fine-tuning this sort of behavior.

It's a bad idea to change the behavior of the home key. This is why Google doesn't allow you to override the home key. I wouldn't mess with the home key generally speaking. You need to give the user a way to get out of your app if it goes off into the weeds for whatever reason.

I'd image any work around will have unwanted side effects.

Try to create a counter for each screen. If the user touch HOME, then the counter will be zero.

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


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

I needed to start/stop background music in my application when first activity opens and closes or when any activity is paused by home button and then resumed from task manager. Pure playback stopping/resuming in Activity.onPause() and Activity.onResume() interrupted the music for a while, so I had to write the following code:

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

which interrupts the playback only when application (all its activities) is closed or when home button is pressed. Unfortunatelly I didn't manage to change order of calls of onPause() method of the starting activity and onResume() of the started actvity when Activity.startActivity() is called (or detect in onPause() that activity is launching another activity other way) so this case have to be handled specially:

private boolean mIsStarting;


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

Another drawback is that this requires GET_TASKS permission added to AndroidManifest.xml:

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

Modifying this code that it only reacts on home button press is straighforward.

Override onUserLeaveHint() in the activity. There will never be any callback to the activity when a new activity comes over it or user presses back press.

Following code works for me :)

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

This is an old question but it might help someone.

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

According to the documentation, the onUserLeaveHint() method is called when the user clicks the home button OR when something interrupts your application (like an incoming phone call).

This works for me.. :)

You might consider a solution by Andreas Shrade in his post on How-To Create a Working Kiosk Mode in Android. It's a bit hacky, but given the reasons that interception of the home button is prevented it has to be ;)

I had this problem, and since overriding the onKeyDown() method didn't accomplish anything because of the underlying android system didn't call this method, I solved this with overriding onBackPressed(), and I had a boolean value set there to false, because I pressed back, let me show you what I mean in code:

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

So the reason why this worked is because the only way to navigate outside this activity is by pressing back or home so if back was pressed then i know the cause wasn't home, but otherwise the cause was home, therefore i set the default boolean value for homePressed to be true. However this will only work with a single activity instance in your application because otherwise you have more possibilities to cause the onPause() method to be called.

onUserLeaveHint();

override this activity class method.This will detect the home key click . This method is called right before the activity's onPause() callback.But it will not be called when an activity is interrupted like a in-call activity comes into foreground, apart from that interruptions it will call when user click home key.

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

Recently I was trying to detect the home press button, because I needed it to do the same as the method "onBackPressed()". In order to do this, I had to override the method "onSupportNavigateUp()" like this:

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

It worked perfectly. =)

Since API 14 you can use the function onTrimMemory() and check for the flag TRIM_MEMORY_UI_HIDDEN. This will tell you that your Application is going to the background.

So in your custom Application class you can write something like:

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

For an in-depth study of this, I invite you to read this article: http://www.developerphil.com/no-you-can-not-override-the-home-button-but-you-dont-have-to/

Jack's answer is perfectly working for click event while longClick is considering is as menu button click.

By the way, if anyone is wondering how to do via 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()
}
}
}
}
}

enter image description here Android Home Key handled by the framework layer you can't able to handle this in the application layer level. Because the home button action is already defined in the below level. But If you are developing your custom ROM, then It might be possible. Google restricted the HOME BUTTON override functions because of security reasons.

This works for me. You can override onUserLeaveHint method https://www.tutorialspoint.com/detect-home-button-press-in-android

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