web-dev-qa-db-ja.com

再開するのではなくアプリを再起動する

解決策ではないにしても、少なくとも行動の説明があれば、誰かが助けてくれることを願っています。

問題:

一部のデバイスでは、ランチャーアイコンを押すと現在のタスクが再開され、他のデバイスでは最初の起動インテントが起動されます(アプリを効果的に再起動します)。なぜこれが起こるのですか?

詳細:

「ランチャーアイコン」を押すと、アプリが正常に起動します。つまり、アクション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"を追加するか、ActivitylaunchMode="singleTop"を使用することは答えではないという多くの答えを読みました。

編集:

このアプリの最新の起動後、最初の再起動後にallデバイスでこの動作が発生し始めていることがわかります。それは私には夢中に思えますが、再起動プロセスを調べて、実際に何が間違っているのかを見つけることができません。

158
Graeme

あぁ! (tldr;下部の太字のステートメントを参照)

私は問題を見つけた...私は思う。

だから、私は仮定から始めましょう。ランチャーを押すと、デフォルトのActivityが開始されるか、前の起動で開始されたTaskが開いている場合は、それが前面に表示されます。別の言い方をすると-ナビゲーションのいずれかの段階で、新しいTaskfinishを作成すると、ランチャーはアプリを再開しなくなります。

その仮定が本当なら、各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と組み合わせて有効に使用することもできます。タスクのルートアクティビティを開始するために使用すると、そのタスクの現在実行中のインスタンスがフォアグラウンドに移動し、ルート状態にクリアされます。これは、たとえば、通知マネージャーからアクティビティを起動する場合に特に便利です。

だから、私は以下のような状況にありました:

  • AFLAG_ACTIVITY_CLEAR_TOPBを起動し、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も再作成します
14
Graeme

発生している動作は、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;
    }
193
starkej2

この質問は2016年にも関連があります。本日、QAテスターが私のアプリを再開するのではなく再起動することを報告しました在庫ランチャーから in Android M.

実際には、システムは起動されたアクティビティを現​​在の task-stack に追加していましたが、それはユーザーに表示されました再起動が発生して作業を失ったかのように。シーケンスは次のとおりです。

  1. Playストアからダウンロード(またはサイドロードapk)
  2. Playストアダイアログからアプリを起動:アクティビティAが表示されます[task stack:A]
  3. アクティビティBに移動します[タスクスタック:A-> B]
  4. 「ホーム」ボタンを押します
  5. アプリドロワーからアプリを起動:アクティビティAが表示されます! [タスクスタック:A-> B-> A](ユーザーは[戻る]ボタンを押して、ここからアクティビティ 'B'に移動できます)

注:この問題は、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ストアからの起動など)を使用して予測およびテストすることは困難です。

46
Rich Ehmer

Samsungデバイスでも同じ問題が発生しました。たくさん検索した後、これらの答えはどれも私にとってはうまくいきませんでした。 AndroidManifest.xmlファイルで、launchModesingleInstanceAndroid:launchMode="singleInstance")に設定されていることがわかりました。 launchMode属性を削除すると、問題が解決しました。

6
Ali

私のCat s60では、開発者オプションで「アクティビティを保持しない」を有効にしました。これを再度無効にすると、アプリの状態を失うことなくアプリを切り替えることができました...

1
ptp

このソリューションは私のために働いた:

    @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アプリケーションを最小化する必要があります

すべてのデバイスで動作するわけではありませんが、戻るボタンが押されたときにホームボタンの動作を正常に作成し、アクティビティを終了するのではなく停止します。

0