これは私をしばらく動かしてきました。
Androidアプリケーションでホームボタンが押されたかどうかを確実に検出する方法はありますか?
それに失敗すると、アクティビティがonPauseになった原因を特定するための堅牢な方法がありますか?つまり、新しいアクティビティの起動によるものか、戻る/ホームボタンを押すことによるものかを検出できますか?.
私が見た提案の1つは、onPause()をオーバーライドしてisFinishing()を呼び出すことですが、新しいアクティビティが開始されている場合と同様にホームボタンを押すとfalseを返しますので、2つを区別できません。
助けていただければ幸いです。
**更新**:このリンクについて@ 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を返し、ホームキーに何もさせないことができます。
Update:予想どおり、これにはいくつかの副次的な影響があります-このモードが有効になっていると、埋め込みビデオとGoogleマップが表示されないようです。
Update:おそらく、このハックはAndroid 4.0以降では動作しなくなったと思われます
次のコードは私のために働く:)
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();
}
これは古い質問ですが、誰かを助けるかもしれません。
@Override
protected void onUserLeaveHint()
{
Log.d("onUserLeaveHint","Home button pressed");
super.onUserLeaveHint();
}
ドキュメントによると、ユーザーがホームボタンORをクリックすると、onUserLeaveHint()メソッドが呼び出されます(電話の着信など)。
これは私のために働く.. :)
最初のアクティビティが開いたり閉じたりするとき、またはホームボタンでアクティビティを一時停止してからタスクマネージャから再開するときに、アプリケーションでバックグラウンドミュージックを開始/停止する必要がありました。 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()
で検出されたときに、開始アクティビティの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"/>
ホームボタンを押したときにのみ反応するようにこのコードを変更するのは簡単です。
Androidアプリ内からHOMEボタンを検出または傍受することはできません。これはシステムに組み込まれ、終了できない悪意のあるアプリを防ぎます。
アクティビティでonUserLeaveHint()
をオーバーライドします。新しいアクティビティが来るか、ユーザーがバックプレスを押すと、アクティビティへのコールバックはありません。
私はこの問題を抱えていました。また、基になるAndroidシステムがこのメソッドを呼び出さないために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()メソッドが呼び出される可能性が高くなります。
各画面のカウンターを作成してみてください。ユーザーが[ホーム]をタッチすると、カウンターはゼロになります。
public void onStart() {
super.onStart();
counter++;
}
public void onStop() {
super.onStop();
counter--;
if (counter == 0) {
// Do..
}
}
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-to /
Andreas Shradeによる Androidでの作業用キオスクモードの作成方法 に関する投稿で解決策を検討できます。それは少しハックですが、ホームボタンの傍受が防止される理由を考えると、そうでなければなりません;)
onUserLeaveHint();
このアクティビティクラスメソッドをオーバーライドします。これにより、ホームキーのクリックが検出されます。このメソッドは、アクティビティのonPause()コールバックの直前に呼び出されますが、ユーザーがホームキーをクリックしたときに呼び出される割り込みとは別に、インコールアクティビティがフォアグラウンドに入るようにアクティビティが中断された場合は呼び出されません。
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
Log.d(TAG, "home key clicked");
}
「onBackPressed()」メソッドと同じことを行う必要があるため、最近、ホームプレスボタンを検出しようとしました。これを行うには、次のようにメソッド "onSupportNavigateUp()"をオーバーライドする必要がありました。
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}
完璧に機能しました。 =)
ホームキーの動作を変更することはお勧めできません。これが、Googleがホームキーのオーバーライドを許可しない理由です。一般的に言えば、ホームキーを台無しにしないでください。何らかの理由で雑草が発生した場合、アプリから抜け出す方法をユーザーに提供する必要があります。
回避策があると、望ましくない副作用が生じると思います。
アプリケーションのオプションは、Android.intent.category.HOMEインテントを使用して、代替ホーム画面を作成することです。このタイプのインテントには、ホームボタンが表示されると思います。
詳細:
http://developer.Android.com/guide/topics/intents/intents-filters.html#imatch
アプリの起動時にルートアクティビティを再表示することのみを希望するため、マニフェストで起動モードなどを変更することでこの動作を取得できますか?
たとえば、 Android:clearTaskOnLaunch = "true" 属性を起動アクティビティに適用しようとしましたか? Android:launchMode = "singleInstance" ?
タスクとバックスタック は、このような動作を微調整するための優れたリソースです。
ジャックの答えは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()
}
}
}
}
}
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.
}