Android에서 홈 버튼 누름 감지


94

이것은 한동안 나를 미치게 만들었다.

Android 애플리케이션에서 홈 버튼을 눌렀는지 확실하게 감지 할 수있는 방법이 있습니까?

실패하면 활동이 onPause로 들어가는 원인을 알 수있는 강력한 방법이 있습니까? 즉, 새로운 활동이 시작되거나 뒤로 / 홈을 눌러서 발생했는지 감지 할 수 있습니까?

내가 본 한 가지 제안은 onPause ()를 재정의하고 isFinishing ()을 호출하는 것이지만 새 활동이 시작되는 것처럼 홈 버튼을 누르면 false를 반환하므로 둘을 구분하지 못합니다.

많은 도움을 주셔서 감사합니다.

** 업데이트 ** : https://nishandroid.blogspot.com/ 링크에 대한 @ android-hungry 감사합니다.

다음 방법을 재정의합니다.

@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 이상에서 더 이상 작동하지 않습니다.


내 문제는 백과 홈 키 사이를 위장하는 것이 아니었지만 두 경우 모두 신청을 마치고 싶었습니다. 내가 Activity.onUserLeaveHint().
harism

유일한 문제는 onUserLeaveHint ()가 해당 활동에서 활동을 시작할 때도 실행된다는 것입니다. 제안 해 주셔서 감사합니다
Dean Wild

그것은 사실이지만 불행히도 내가 아는 한 홈 키 사용에 대한 정보를받을 수있는 유일한 곳입니다. 오탐을 찾아내는 것이 더 문제가되게하는데, 많은 것 중에서 쉽게 알아볼 수 있지만 여전히 쉬운 소리를내는 작업을 다소 복잡하게 만듭니다.
harism

2
: @DeanWild : u는이 읽기 않았다 nisha113a5.blogspot.com
Pratik 바트

2
TYPE_KEYGUARD 상수가 Android 5.0의 WindowManager.LayoutParams에서 제거되었습니다
theb1uro

답변:


136

다음 코드는 나를 위해 작동합니다. :)

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

3
귀하는 onHomeLongPressed실제로 "최근"시스템 활동의 시작에 해당하는 것 같습니다. 내 전화에서는 홈 버튼 옆의 최근 버튼을 눌러 트리거되므로 집에서 길게 누르는 것에 대한 코드 가정이 항상 정확하지는 않습니다.
Sam

왜 그것이 나를 위해 작동하지 않는지, 매니페스트를 통해 방송을 등록하는 것 외에는 똑같이했습니다.
Farhan

신청 수업 등록, 지금까지 근무 중 .. +1, 잡힌 게 뭐지? 나는 우리가 원래 어떤 경우 누락 될 의미 .. : ^)
인 Farhan

1
가끔 intent.getStringExtra (SYSTEM_DIALOG_REASON_KEY); null을 반환합니다. 무슨 일이 일어나고 있는지 알고 싶습니다 ??
Fakher

1
긴 보도 이유는 지금이라고합니다final String SYSTEM_DIALOG_REASON_LONG_PRESS = "assist"
JWqvist

49

이것은 오래된 질문이지만 누군가에게 도움이 될 수 있습니다.

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

문서에 따르면 onUserLeaveHint () 메서드는 사용자가 홈 버튼을 클릭하거나 무언가가 애플리케이션을 중단 할 때 (예 : 수신 전화) 호출됩니다.

이것은 나를 위해 작동합니다 .. :)


26
맞지 않습니다 !!! 그것은 홈 버튼을 눌렀을 때 작동하지만 의도로 활동을 전환 할 때도 작동합니다 !!
Nikunj Paradva

다른 활동이 상단에 제공하거나 사용자가 강제 활동이나 클릭 홈 버튼을 떠날 경우에도 이것은 항상) (이동 중지하기 전에 실행합니다 ...
나바스는 PK

7

Android 앱 내에서 홈 버튼을 감지 및 / 또는 가로채는 것은 불가능합니다. 종료 할 수없는 악성 앱을 방지하기 위해 시스템에 내장되어 있습니다.


수락 된 답변을 확인하면 가능합니다. 아직 많은 장치에서 테스트되지 않았습니다.
Dean Wild

네 ... 내 앱이 다운되었습니다.
제레미 로건

런처 / 홈 교체 앱은 어떻습니까? 나는 하나를 짓고 있어요 나는 첫 화면으로 이동 할 때 사용자가 클릭 홈
lisovaccaro

런처의 경우 다음을 사용하십시오. @Override protected void onNewIntent (Intent intent) {super.onNewIntent (intent); / * 당신이 원하는 것을하십시오 * /}
Ton

@lisovaccaro 런처 및 / 또는 홈 교체는 여전히 Google (src diane hackborn)에서 지원되지 않으므로 사용자가 홈 버튼을 클릭하는 것을 막을 수 없습니다. 여전히 모든 것을 오버레이하는 시스템 경고 대화 상자로보기를 추가 할 수 있습니다. 그러나 홈 버튼 클릭이 통과합니다.
JacksOnF1re

7

첫 번째 활동이 열리고 닫힐 때 또는 홈 버튼으로 활동이 일시 중지 된 다음 작업 관리자에서 다시 시작될 때 애플리케이션에서 배경 음악을 시작 / 중지해야했습니다. 순수 재생에 다시 시작 / 중지 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
  }
}

응용 프로그램 (모든 활동)이 닫히거나 홈 버튼을 누를 때만 재생을 중단합니다. Unfortunatelly 난의 통화의 변화 순서로 관리하지 않은 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"/>

홈 버튼 누를 때만 반응하는이 코드를 수정하는 것은 매우 어렵습니다.


4

onUserLeaveHint()활동에서 재정의 합니다. 새로운 활동이 오거나 사용자가 뒤로 누를 때 활동에 대한 콜백이 없습니다.


4
응용 프로그램 내에서 다른 하나 개의 활동에서 갈 때 그것은 또한라고도
아미르 Uval

3

onUserLeaveHint ();

이 액티비티 클래스 메서드를 재정의하면 홈 키 클릭을 감지합니다. 이 메서드는 액티비티의 onPause () 콜백 직전에 호출되지만, 사용자가 홈 키를 클릭 할 때 호출하는 인터럽트를 제외하고는 인콜 액티비티가 포 그라운드로 들어오는 것처럼 액티비티가 중단 될 때 호출되지 않습니다.

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

2

각 화면에 대한 카운터를 만들어보십시오. 사용자가 홈을 터치하면 카운터는 0이됩니다.

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

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

3
전역 응용 프로그램 카운터를 의미하는 경우 한 활동이 백 스택으로 이동되고 다른 활동이 맨 위로 이동되거나 최상위 활동이 완료되고 백 스택 활동이 다음과 같은 일반적인 위치로 이동되는 순간에 0이됩니다. 홈 버튼 누름에 반응하고 싶습니다. 활동 전체 카운터를 의미하는 경우 활동이 표시되지 않을 때마다 0이됩니다 (반드시 홈 버튼 누름으로 인한 것은 아님). 유일한 해결책은이 전환을 건너 뛰기 위해 타이머를 사용하여 반응을 연기하는 것이지만 필요한 지연은 예측할 수 없거나 바람직하지 않을 수 있습니다.
Blackhex 2013 년


1

나는이 문제가 있었고 기본 안드로이드 시스템 이이 메서드를 호출하지 않았기 때문에 onKeyDown () 메서드를 재정의해도 아무것도 달성하지 못했기 때문에 onBackPressed () 재정의 로이 문제를 해결했으며 부울 값을 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"); }
    }

그래서 이것이 작동하는 이유는이 활동 외부를 탐색하는 유일한 방법은 뒤로 또는 집을 누르는 것이므로 뒤로를 누르면 원인이 집이 아니라는 것을 알지만 그렇지 않으면 원인이 집에 있었으므로 기본 부울을 설정했습니다. homePressed 값은 true입니다. 그러나 이것은 애플리케이션의 단일 활동 인스턴스에서만 작동합니다. 그렇지 않으면 onPause () 메소드가 호출 될 가능성이 더 많기 때문입니다.


실제로 다른 활동으로 이동하면 onpause 메소드가 호출됩니다.
Fakher

그렇기 때문에 애플리케이션이 단일 활동 만 통합하는 경우에만 이것이 작동한다고 명시 적으로 언급 한 것입니다!
Moshe Rabaev

그리고 관련없는 여러 활동이 동시에 실행되고 사용자가 단순히 이들 사이를 전환하는 경우에는 어떻게 될까요? 최신 Android 기기는 멀티 태스킹을 지원합니다. 이 코드를 사용하면 앱으로 다시 전환 homePressed하면 true로 설정 되고 다른 앱으로 전환하면 실제로 그렇지 않은 경우 홈을 눌렀다 고 생각할 수 있습니다.
Remy Lebeau 2016 년

1

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 -에/


1
좋은 기사 - 유용한 대안은 아마 대부분의 사람들이 필요로한다는 것을
딘 와일드에게

좋은 솔루션입니다. 응용 프로그램이 백그라운드에서 돌아올 때 플래그를 재설정하는 방법을 알고 있습니까? 예를 들어 부울 isInBackground를 만들면 백그라운드에서 돌아 오면로 재설정하고 싶습니다.
MikeOscarEcho


0

앱이 시작될 때 루트 활동 만 다시 표시되기를 원하기 때문에 매니페스트에서 시작 모드 등을 변경하여이 동작을 얻을 수 있습니까?

예를 들어, 시작 활동에 android : clearTaskOnLaunch = "true" 속성을 적용 해 보셨습니까 ? 아마도 android : launchMode = "singleInstance" 와 함께 사용 하시겠습니까?

작업 및 백 스택 은 이러한 종류의 동작을 미세 조정하는 데 유용한 리소스입니다.


이것은 가장 우아한 솔루션처럼 보이지만 상당히 신뢰할 수없는 것으로 나타났습니다. 몇 번의 열기 / 닫기 / 일시 중지주기 후에 앱이 완전히 다시 시작되지 않고 다시 시작됩니다.
Dean Wild

0

홈 키의 동작을 변경하는 것은 나쁜 생각입니다. 이것이 Google에서 홈 키 재정의를 허용하지 않는 이유입니다. 나는 일반적으로 홈 키를 엉망으로 만들지 않을 것입니다. 어떤 이유로 든 앱이 잡초에 빠지면 사용자에게 앱에서 벗어날 수있는 방법을 제공해야합니다.

나는 주위의 모든 작업이 원치 않는 부작용을 가질 것이라고 상상할 것입니다.


1
당신은 절대적으로 자리를 잡았지만 일부 고객은 대답을 거부하고 지침을 어기면 안되는 이유를 이해하지 못합니다.
딘 와일드

문제는 홈 버튼 동작을 변경하고 싶지 않더라도 홈 버튼 누름으로 인해 애플리케이션이 뒤로 이동하는 상황에 대해 현재 활동이 wathever 동안 일시 중지 된 상황과 다르게 때때로 다르게 반응해야한다는 것입니다. 이유. 동일한 문제는 Application.onDestroy ()를 poduction 빌드에 사용할 수 없다는 사실입니다. 이러한 예로는, 배경 음악을 중지, 사용자가 appication을 숨 깁니다 게임을 일시 중지한다
Blackhex

0

최근에 " onBackPressed () " 메서드와 동일한 작업을 수행해야했기 때문에 홈 프레스 버튼을 감지하려고했습니다 . 이를 위해 다음 과 같이 " onSupportNavigateUp () " 메서드를 재정의해야 했습니다.

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

완벽하게 작동했습니다. =)


0

Jack의 대답은 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()
                }
            }
        }
    } 
}

0

여기에 이미지 설명 입력 프레임 워크 레이어에서 처리하는 Android 홈 키는 애플리케이션 레이어 수준에서 처리 할 수 ​​없습니다. 홈 버튼 동작은 이미 아래 수준에서 정의되어 있기 때문입니다. 그러나 사용자 정의 ROM을 개발하는 경우 가능할 수 있습니다. Google은 보안상의 이유로 홈 버튼 재정의 기능을 제한했습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.