101

これはしばらくの間、私を夢中にさせてきました。

Androidアプリケーションでホームボタンが押されたかどうかを確実に検出する方法はありますか?

それができない場合、アクティビティが onPause になった原因を確実に伝える方法はありますか? つまり、新しいアクティビティの起動が原因なのか、戻る/ホームを押したことが原因なのかを検出できますか。

私が見た 1 つの提案は、onPause() をオーバーライドして isFinishing() を呼び出すことですが、新しいアクティビティが開始された場合と同じように、ホーム ボタンを押すと false が返されるため、2 つを区別できません。

どんな助けでも大歓迎です。

**更新**:このリンクについて@android-hungryに感謝します: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 を返し、ホーム キーが何もしないようにすることができます。

更新: 予想どおり、これにはいくつかの副作用があります。このモードを有効にすると、埋め込みビデオと Google マップが表示されないようです。

更新: おそらく、このハックは Android 4.0 以降では機能しなくなりました

4

17 に答える 17

149

次のコードは私のために働きます:)

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();
}
于 2015-01-15T03:16:37.130 に答える
54

これは古い質問ですが、誰かを助けるかもしれません。

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

ドキュメントによると、onUserLeaveHint() メソッドは、ユーザーがホーム ボタンをクリックしたとき、または何かがアプリケーションを中断したとき (電話の着信など) に呼び出されます。

これは私のために働く.. :)

于 2015-07-07T14:28:40.500 に答える
8

Android アプリ内から HOME ボタンを検出および/または傍受することは不可能です。これは、終了できない悪意のあるアプリを防ぐためにシステムに組み込まれています。

于 2012-01-16T15:20:24.330 に答える
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
  }
}

これは、アプリケーション(そのすべてのアクティビティ)が閉じられたとき、またはホームボタンが押されたときにのみ再生を中断します。onPause()残念ながら、開始アクティビティのメソッドの呼び出しの順序と、呼び出されonResume()たときに開始されたアクティビティの呼び出しの順序を変更できなかったためActivity.startActivity()(または、onPause()そのアクティビティで別のアクティビティが開始されていることを検出)、このケースは特別に処理する必要があります。

private boolean mIsStarting;

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

もう1つの欠点は、次の機能にGET_TASKSアクセス許可を追加する必要があることAndroidManifest.xmlです。

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

ホームボタンを押したときにのみ反応するようにこのコードを変更するのは簡単です。

于 2013-03-14T19:57:04.097 に答える
5

onUserLeaveHint();

このアクティビティ クラス メソッドをオーバーライドします。これにより、ホーム キーのクリックが検出されます。このメソッドは、アクティビティの onPause() コールバックの直前に呼び出されます。ただし、ユーザーがホーム キーをクリックしたときに呼び出される中断を除いて、呼び出し中のアクティビティがフォアグラウンドになるなど、アクティビティが中断された場合には呼び出されません。

@Override
protected void onUserLeaveHint() {
    super.onUserLeaveHint();
    Log.d(TAG, "home key clicked");
}
于 2017-10-06T14:18:35.210 に答える
2

画面ごとにカウンターを作成してみてください。ユーザーが HOME をタッチすると、カウンターはゼロになります。

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

public void onStop() {
  super.onStop();
  counter--;    
  if (counter == 0) {
      // Do..
  }
}
于 2012-08-14T18:04:58.577 に答える
1

私はこの問題を抱えていましたが、基礎となる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() メソッドが呼び出される可能性が高くなるからです。

于 2015-07-30T22:49:32.223 に答える
0

アプリケーションのオプションは、android.intent.category.HOME インテントを使用して代替ホーム画面を作成することです。このタイプのインテントは、ホーム ボタンが表示されると思います。

詳細:

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

于 2012-01-16T15:48:29.050 に答える
0

アプリの起動時にルート アクティビティを再表示したいだけなので、マニフェストで起動モードなどを変更することでこの動作を取得できますか?

たとえば、おそらくandroid:launchMode="singleInstance"と連携して、 android:clearTaskOnLaunch="true"属性を起動アクティビティに適用しようとしましたか?

タスクとバック スタックは、この種の動作を微調整するための優れたリソースです。

于 2012-01-16T16:43:31.900 に答える
0

ホームキーの動作を変更するのは悪い考えです。これが、Google がホーム キーの上書きを許可していない理由です。一般的に言えば、ホームキーを台無しにすることはありません。なんらかの理由でアプリが雑草になった場合に、ユーザーがアプリから抜け出す方法を提供する必要があります。

回避策には望ましくない副作用があると思います。

于 2012-07-18T20:26:54.313 に答える