このボタンがどのメソッドを呼び出すのかと思います。
私のゲームは、このボタンを使用する場合を除いて、常に正しく一時停止/再開します。このボタンが Activity のonPause()
およびonResume()
メソッドを呼び出さないようです=。ゲームを終了し、別のウィンドウ(図のようなウィンドウ)に移動して、このボタンを使用して再開すると機能します。しかし、このボタンを押すだけの場合、ゲーム内でゲームが一時停止しますが、スレッドは1回おきのように再開しません。ゲームは、画面上に静止し、ちらつきます。
説明するのは難しいですが、はっきりしていると思いますが、そうでない場合は質問してください!
「最近のアプリ」ボタンが押されたときに、標準の Activity Lifecycle メソッドは呼び出されません。最近のアプリポップアップのリストが表示された後も、アクティビティはアクティブのままです。この状況を適切に処理しなかったアニメーションでゲームを実行している場合は、このリストの半透明の左側を通して、アプリケーションアニメーションがまだ実行されていることを確認することもできます。実際、Google Playのゲームの多くはこの状況を適切に処理しませんでした。AngryBirdsのような良い状況でもそうです。
ユーザーが「最近のアプリ」リストを開いたとき(またはリストから戻ったとき)に呼び出される唯一のActivityメソッドは、ブールパラメータhasFocus
を指定した onWindowFocusChanged です。 hasFocus
で呼び出された最近のアプリメソッドonWindowFocusChanged()
のリストを開くとfalse
と等しくなり、hasFocus
で呼び出された同じメソッドはtrue
と等しくなります。ユーザーはこのリストで[戻る]を押します。
「最近のアプリ」ボタンが押されたことを検出するには、ユーザー補助サービスを使用できます。独自のユーザー補助サービスを実行し、タイプ「TYPE_WINDOW_STATE_CHANGED」のイベントを受信して、イベントのクラス名を確認する必要があります。
onAccessibilityEvent()
AccessibilityEvent event
オブジェクト。このオブジェクトには、デバイスで発生したイベントに関する必要な情報がすべて含まれています。ClassNameに興味があります。 ClassNameはnullになることがあるので、!= nullチェックを忘れないでください。最近のアプリウィンドウのパッケージ名は、Androidのバージョンによって異なります。
古いデバイスのクラス名はわからないが、誰かが2017年にそれらを維持しているとは思わない;)
だからあなたはこのようなものを持つでしょう:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || event.getClassName() == null)
return;
String className = String.valueOf(event.getClassName());
if (className.equals("com.Android.internal.policy.impl.RecentApplicationsDialog")
|| className.equals("com.Android.systemui.recent.RecentsActivity")
|| className.equals("com.Android.systemui.recents.RecentsActivity")){
//Recent button was pressed. Do something.
}
}
次の実際のデバイスでテストしました:LG、Nexus、Sony、および仮想デバイス:Motorola、Samsung。
誰かがこれらのクラス名の例外を知っている場合は、私にpingしてください。
私は同じ問題を抱えています、私はこの問題を以下のように解決しました。
HomeとRecentAppのブロードキャストボタンクリックブロードキャスト
InnerReceiver mReceiver = new InnerReceiver();
IntentFilter mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mReceiver, mFilter);
BroadcastReceiverコード
class InnerReceiver extends BroadcastReceiver {
final String SYSTEM_DIALOG_REASON_KEY = "reason";
final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (reason != null) {
if (mListener != null) {
if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
// Home Button click
} else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
// RecentApp or Overview Button click
}
}
}
}
}
}
しかし、unregisterReceiver
BroadcastReceiverを忘れないでください
私は同様の問題に直面したので、ユーザーが最近のアプリボタン(古いバージョンのAndroidのメニューキーボタン)をいつ押したかを知る必要がありました。数時間の調査の後、ホームボタンまたはメニューボタンが押されたときにキャッチするイベントを見つけられませんでした。ユーザーがホームボタンを押したときにonStop()を呼び出すのに時間がかかることがわかったので、応答時間に関連するこれらの2つのボタンを区別し、2つのメソッドをオーバーライドする方法を考えます。
@オーバーライド
public void onUserLeaveHint() {
// do stuff
super.onUserLeaveHint();
userLeaveTime = System.currentTimeMillis() ;
isNotPower = true;
}
@オーバーライド
public void onStop() {
super.onStop();
if (isNotPower) {
defStop = System.currentTimeMillis() - userLeaveTime;
if (defStop > 200 ) {
//home button
}
if (defStop < 200) {
//recent apps button
}
}
isNotPower = false;
}
私が見つけた最良の方法は、「ACTION_CLOSE_SYSTEM_DIALOGS」と呼ばれるブロードキャストアクションをリストすることです。Googleドキュメントから:
ブロードキャストアクション:これは、ユーザーアクションが一時的なシステムダイアログを閉じるよう要求する必要があるときにブロードキャストされます。一時的なシステムダイアログのいくつかの例は、通知ウィンドウシェードと最近のタスクダイアログ。です。
作業コード:
IntentFilter intentFilterACSD = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
//do what you want here
}
}
};
this.registerReceiver(broadcastReceiver, intentFilterACSD);
これはこの特定のゲームの問題だけですか?それとも、あなたがプレイするすべてのゲームでそれはありますか?
onPause()
とonResume()
のほかに、onStop()
と呼ばれる別のサイクルがあります。多分ここで行われているいくつかの基本的なことがあります。その「windows-open」ボタンを押すと、ゲームは「ホーム」ボタンを押すのとは異なり、おそらくonStop
- stateに入りません。
アクティビティとフラグメントの両方に関して、recent-apps/recents keyの動作を明確に示すアプリを作成しました。
(通常のライフサイクルイベントがこのキーによってトリガーされないという主張はすべて、明らかに誤りです。)
onCreate()
のメインActivityは、すべての既知のActivityライフサイクルイベントのログを記録するための配列を初期化し、メインフラグメントをそれ自体と一緒に起動します2番目のFrameLayout。
onAttach()
のメインFragmentは、既知のすべてのFragmentライフサイクルイベントのログを記録するための個別の配列を初期化します。
ロギングの目的で、ActivityとFragmentはどちらもonWindowFocusChanged()
を別のライフサイクルイベントとして扱います。
ログに記録されたイベントにはタイムスタンプが付けられるため、レンダリング時にユーザーの「一時停止」を示すことができます(そして、レンダリングはonWindowFocusChanged()
内で発生し、hasFocus==true
)。
以下は、テストアプリが起動したときにユーザーに表示されるものです。
数秒後、ユーザーはrecent-appsを押し、数秒待ってからもう一度押して、真実を確認します。
注:[最近のアプリ]ボタンを使用する代わりに、(a)タブレットのオフ/オンボタンを押す(b)[2番目のアクティビティを開始]ボタンを押す(c)などで実験を繰り返すと、同じ結果が得られます。
OPへの回答:
どうやら、recent-appsキーが実際に押されたことを検出できるコードはありません。
ただし、アプリは関連するライフサイクルイベントを正しく処理する必要があるため、問題ではありません。