解決策ではないにしても、少なくとも行動の説明があれば、誰かが助けてくれることを願っています。
問題:
一部のデバイスでは、ランチャーアイコンを押すと現在のタスクが再開され、他のデバイスでは最初の起動インテントが起動されます(アプリを効果的に再起動します)。なぜこれが起こるのですか?
詳細:
「ランチャーアイコン」を押すと、アプリが正常に起動します。つまり、アクションAndroid.intent.action.MAIN
とカテゴリAndroid.intent.category.LAUNCHER
を含む最初のActivity
の名前でIntentが起動されます。ただし、これは常に当てはまるわけではありません。
大部分のデバイスでは、アプリの実行後にランチャーアイコンを押すと、そのプロセスで現在実行されているアクティビティが再開されます(NOT the initial Activity
)。 OSメニューの[最近のタスク]から選択した場合と同じ方法で再開します。これは、allデバイスで必要な動作です。
ただし、選択した他のデバイスでは異なる動作が発生します。
モトローラXoomでは、ランチャーアイコンを押すと、アプリはalwaysで現在実行されているものに関係なく、Activity
の初期起動を開始します。ランチャーアイコンは常に「ランチャー」インテントを開始すると想定しています。
Samsung Tab 2では、ランチャーアイコンを押すと、アプリをインストールしたばかりの場合、常に最初のActivity
(Xoomと同じ)が起動します-ただし、インストール後にデバイスを再起動すると、ランチャーアイコンが代わりにアプリを再開します。これらのデバイスは、デバイスの起動時に「インストール済みのアプリ」をルックアップテーブルに追加し、ランチャーアイコンが実行中のタスクを正しく再開できると思いますか?
sound私の問題に似ていますが、単にAndroid:alwaysRetainTaskState="true"
を追加するか、Activity
にlaunchMode="singleTop"
を使用することは答えではないという多くの答えを読みました。
編集:
このアプリの最新の起動後、最初の再起動後にallデバイスでこの動作が発生し始めていることがわかります。それは私には夢中に思えますが、再起動プロセスを調べて、実際に何が間違っているのかを見つけることができません。
あぁ! (tldr;下部の太字のステートメントを参照)
私は問題を見つけた...私は思う。
だから、私は仮定から始めましょう。ランチャーを押すと、デフォルトのActivity
が開始されるか、前の起動で開始されたTask
が開いている場合は、それが前面に表示されます。別の言い方をすると-ナビゲーションのいずれかの段階で、新しいTask
とfinish
を作成すると、ランチャーはアプリを再開しなくなります。
その仮定が本当なら、各Task
が同じプロセスにあり、最初に作成されたものと同じくらい有効な履歴書候補であるということを考えると、それはバグであるはずです。
私の問題は、これらのフラグをいくつかのIntents
から削除することで修正されました。
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
FLAG_ACTIVITY_NEW_TASK
が新しいTask
を作成することは明らかですが、上記の仮定が有効であることを理解していませんでした。私はこれを犯人と見なし、テストのためにそれを削除しましたが、まだ問題が残っていたので却下しました。しかし、私はまだ以下の条件がありました:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
私のスプラッシュ画面は、上記のフラグを使用して、アプリで「メイン」Activity
を開始していました。結局、アプリを "再起動"し、Activity
がまだ実行されている場合は、その状態情報を保持したいです。
documentation で気づくでしょう。新しいTask
の開始については言及していません。
設定されていて、起動されるアクティビティが現在のタスクで既に実行されている場合、そのアクティビティの新しいインスタンスを起動する代わりに、そのアクティビティの他のすべてのアクティビティが閉じられ、このインテントが(現在top)新しいインテントとしての古いアクティビティ。
たとえば、アクティビティA、B、C、Dで構成されるタスクを考えます。DがアクティビティBのコンポーネントに解決するインテントでstartActivity()を呼び出すと、CとDは終了し、Bは指定されたインテントを受け取ります、その結果スタックはA、Bになりました。
上記の例で現在実行中のアクティビティBのインスタンスは、onNewIntent()メソッドでここから開始する新しいインテントを受け取るか、新しいインテントで終了して再起動します。起動モードが「複数」(デフォルト)であると宣言していて、同じ意図でFLAG_ACTIVITY_SINGLE_TOPを設定していない場合は、終了して再作成されます。他のすべての起動モードの場合、またはFLAG_ACTIVITY_SINGLE_TOPが設定されている場合、このインテントは現在のインスタンスのonNewIntent()に配信されます。
この起動モードは、FLAG_ACTIVITY_NEW_TASKと組み合わせて有効に使用することもできます。タスクのルートアクティビティを開始するために使用すると、そのタスクの現在実行中のインスタンスがフォアグラウンドに移動し、ルート状態にクリアされます。これは、たとえば、通知マネージャーからアクティビティを起動する場合に特に便利です。
だから、私は以下のような状況にありました:
A
はFLAG_ACTIVITY_CLEAR_TOP
でB
を起動し、A
は終了します。B
は、サービスを再起動したいので、サービスを再起動するロジックとUI(フラグなし)を持つA
にユーザーを送信します。A
はFLAG_ACTIVITY_CLEAR_TOPでB
を起動し、A
は終了します。この段階で、2番目のFLAG_ACTIVITY_CLEAR_TOP
フラグは、タスクスタックにあるB
を再起動します。これはTask
を破壊し、新しいものを開始しなければならないので、私の問題を引き起こしていると思います。
だから、私の仮定がすべて正しい場合:
Launcher
は最初に作成されたタスクのみを再開しますFLAG_ACTIVITY_CLEAR_TOP
は、残りのActivity
のみを再起動する場合、新しいTask
も再作成します発生している動作は、API 1以降の一部のAndroidランチャーに存在する問題が原因で発生します。バグの詳細と可能な解決策は、こちらで確認できます。 https:// code。 google.com/p/Android/issues/detail?id=237 。
これは、サムスンデバイスや、カスタムランチャー/スキンを使用する他のメーカーで比較的一般的な問題です。ストックAndroidランチャーで問題が発生するのを見たことはありません。
基本的に、アプリは実際には完全には再起動しませんが、ランチャーによってアプリが再開されると、起動アクティビティが起動され、アクティビティスタックの一番上に追加されます。これを確認するには、アプリを再開するときに戻るボタンをクリックして、起動アクティビティが表示されます。その後、アプリを再開したときに表示される予定のアクティビティに移動する必要があります。
この問題を解決するために実装することを選択した回避策は、初期アクティビティを開始するインテントでIntent.CATEGORY_LAUNCHERカテゴリとIntent.ACTION_MAINアクションをチェックすることです。これらの2つのフラグが存在し、アクティビティがタスクのルートにない場合(アプリが既に実行されていたことを意味します)、最初のアクティビティでfinish()を呼び出します。その正確な解決策はあなたにはうまくいかないかもしれませんが、似たような何かがそうでなければなりません。
これが、初期/起動アクティビティのonCreate()で行うことです。
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
この質問は2016年にも関連があります。本日、QAテスターが私のアプリを再開するのではなく再起動することを報告しました在庫ランチャーから in Android M.
実際には、システムは起動されたアクティビティを現在の task-stack に追加していましたが、それはユーザーに表示されました再起動が発生して作業を失ったかのように。シーケンスは次のとおりです。
注:この問題は、PlayストアからダウンロードされたAPKまたはサイドロードされたAPKでのみ、ADBを介してデプロイされたデバッグAPKには現れません。後者の場合、ステップ5の起動インテントにはフラグIntent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
が含まれていましたが、デバッグの場合には含まれていませんでした。アプリがランチャーからコールドスタートされると、問題はなくなります。私の疑いは、タスクが完全にクリアされるまで正しい起動動作を妨げる不正な(より正確には、非標準の)インテントがタスクにシードされることです。
さまざまな アクティビティ起動モード を試しましたが、これらの設定は、ユーザーが期待する標準的な動作から大きく逸脱しています。アクティビティBでタスクを再開します。 タスクとバックスタック 、ページの下部の「タスクの開始」:
この種類のインテントフィルターを使用すると、アクティビティのアイコンとラベルがアプリケーションランチャーに表示され、ユーザーはアクティビティを起動して、起動後いつでも作成したタスクに戻ることができます。
この回答 が適切であることがわかり、ユーザーがアプリケーションを開いたときに適切に再開されるように、ルートアクティビティ(A)の 'onCreate'メソッドに次を挿入しました。
/**
* Ensure the application resumes whatever task the user was performing the last time
* they opened the app from the launcher. It would be preferable to configure this
* behavior in AndroidMananifest.xml activity settings, but those settings cause drastic
* undesirable changes to the way the app opens: singleTask closes ALL other activities
* in the task every time and alwaysRetainTaskState doesn't cover this case, incredibly.
*
* The problem happens when the user first installs and opens the app from
* the Play Store or sideloaded apk (not via ADB). On this first run, if the user opens
* activity B from activity A, presses 'home' and then navigates back to the app via the
* launcher, they'd expect to see activity B. Instead they're shown activity A.
*
* The best solution is to close this activity if it isn't the task root.
*
*/
if (!isTaskRoot()) {
finish();
return;
}
更新:アクティビティがタスクのルートに直接ある場合、このソリューションをインテントフラグの解析からクエリへと移動しました。インテントフラグは、MAINアクティビティを開くためのさまざまな方法(ホームからの起動、「アップ」ボタンからの起動、Playストアからの起動など)を使用して予測およびテストすることは困難です。
Samsungデバイスでも同じ問題が発生しました。たくさん検索した後、これらの答えはどれも私にとってはうまくいきませんでした。 AndroidManifest.xmlファイルで、launchMode
がsingleInstance
(Android:launchMode="singleInstance"
)に設定されていることがわかりました。 launchMode
属性を削除すると、問題が解決しました。
私のCat s60では、開発者オプションで「アクティビティを保持しない」を有効にしました。これを再度無効にすると、アプリの状態を失うことなくアプリを切り替えることができました...
このソリューションは私のために働いた:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
return false;
}
else
return super.onKeyUp(keyCode, event);
}
クレジット: 戻るボタンのクリック時にAndroidアプリケーションを最小化する必要があります
すべてのデバイスで動作するわけではありませんが、戻るボタンが押されたときにホームボタンの動作を正常に作成し、アクティビティを終了するのではなく停止します。