9

多数のアクティビティを含むアプリを開発しています。バックグラウンドサービスが実行されているときはいつでも存在する「AppName - AppName に戻る」という (多かれ少なかれ) 永続的な通知を作成したいと思います。 通知の作成と破棄は問題ありませんでした。

現在、ユーザーはいくつかの画面/アクティビティのいずれかで、アプリケーションを離れてから、通知を介してアプリに再度入ることができます。 問題は、通知には、所定の Activityを起動する意図が必要です。Activity が history stack の一番上にあるときに、通知がアプリに再入力されるようにします。

醜い回避策での私の最初の試みは、「onCreate」でそれ自体を「終了」することだけを行うアクティビティ(「returnFromNotify」と呼びましょう)を作成することでした。通知は、アプリケーション履歴のスコープで「returnFromNotify」を開き、すぐにそれ自体を削除して、ユーザーをアプリケーション スタック内の以前の履歴状態に戻します。これは機能しているようです...ユーザーが「戻る」を使用してアプリを完全に元に戻していない限り。次に、通知がヒットすると、「returnFromNotify」がロードされて終了し、ホーム画面に送り返されます (アプリの履歴スタックにアクティビティがないため)。

「returnFromNotify」の前に履歴スタックに何かがあったかどうかを検出しようと考えました。そうでない場合は、メインのアクティビティを起動します。私もこれを行う方法を見つけることができないようです。

Java/Android 初心者への意見や提案はありますか? 参考までに、私の主な歴史はスクリプトベースの言語です。

4

5 に答える 5

6

ResumeActivity がスタックの一番下にある (したがって、スタック内の唯一のアクティビティである) かどうかを検出できるため提案された回避策よりも優れた「returnFromNotify」アクティビティを作成するという最初のアイデアが気に入っています。

方法は次のとおりです。

ResumeActivity をマニフェストに追加し、noHistory属性を指定します。

<activity android:name=".ResumeActivity" android:noHistory="true" />

noHistory を指定すると、このアクティビティが終了してもすぐにスタックに残らないようになります。これにより、ResumeActivity の現在実行中のインスタンスのみがスタックに表示されることがわかります。

アプリケーション スタックを確認するには、GET_TASKS パーミッションも要求する必要があります。

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

これで、ActivityManager::getRunningTasks()を使用して、ResumeActivity がスタック内の唯一のアクティビティであるかどうかを判断できます。

public class ResumeActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(isOnlyActivityInStack()) { //check the application stack
            //This activity is the only activity in the application stack, so we need to launch the main activity
            Intent main = new Intent(this, MainActivity.class);
            main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(main);
        } else {
            //Return the user to the last activity they had open
            this.finish();
        }
    }

    /**
     * Checks the currently running tasks. If this activity is the base activity, we know it's the only activity in the stack
     *
     * @return  boolean  This activity is the only activity in the stack?
     **/
    private boolean isOnlyActivityInStack() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        boolean onlyActivityInStack = false;

        for(RunningTaskInfo tasks : manager.getRunningTasks(Integer.MAX_VALUE)) {
            if(tasks.baseActivity.getPackageName().equals(this.getPackageName())) { //find this package's application stack
                if(tasks.baseActivity.getClassName().equals(this.getClass().getName())) {
                    //If the ResumeActivity is the base activity, we know that it is the only activity in the stack
                    onlyActivityInStack = true;
                    break;
                }
            }
        }

        return onlyActivityInStack;
    }

}

2年以上前にこの質問をしたことは知っていますが、他の誰かがこの特定の状況に遭遇した場合に備えて、この回答を提供しています(私がしたように)。当初目指していたソリューションで正しい軌道に乗っていたと思います。

于 2012-09-21T20:03:38.757 に答える
3

わかりました。特定のケースに対して満足のいく回避策を見つけたと思います。「mainActivity」に静的整数を追加しました。「onCreate」が起動されるたびに、整数がインクリメントされます。「onDestroy」が起動されるたびに、デクリメントします。

私の "returnFromNotify" では、静的な整数を調べて、それが 0 より大きいかどうかを確認します。そうであれば、アクティブな "mainActivity" があり、"returnFromNotify" 内で "finish" を実行するとそこに戻ると仮定します。それ以外の場合は、ユーザーが「バックアウト」したと想定し、それ自体を終了してから、「startActivity」を使用して「mainActivity」の新しいインスタンスを起動します。

これは普遍的な解決策ではありませんが、私の目的には十分だと思います。私はまだ他の答えを受け入れています.誰かが私の論理に穴を開けることができるなら、そうしてください-建設的な批判は大歓迎です. ありがとう。

于 2010-08-26T18:46:39.100 に答える
1

これを行う簡単な方法はないと思いますが、mainActivityにカウンターを追加する代わりに、Applicationを拡張します。

グローバルアプリケーションの状態を維持する必要がある人のための基本クラス。AndroidManifest.xmlのタグでその名前を指定することにより、独自の実装を提供できます。これにより、アプリケーション/パッケージのプロセスが作成されたときに、そのクラスがインスタンス化されます。

私はそこでロジックをマンテインし、次のようなメソッドを使用します。

public Intent getIntentForLastActivityShown();

通知項目がクリックされたときに呼び出されます。

于 2010-08-30T18:24:23.380 に答える
1

私の最初のアプローチはSharedPreferences、のようなキーと値のペアを使用して保存することですlastDisplayedActivity。次に、各アクティビティonResume(および場合によっては「onCreate」) で、次のような行を作成します。

sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME);

つまり、最後に表示されたアクティビティを示すアプリケーション全体の変数を保存します。次に、この変数を SharedPreferences から取得して、対応するアクティビティを起動します。

于 2010-08-31T01:43:25.923 に答える
0

私は通常、アプリケーションモデルの状態をチェックし、モデル ルールに応じてアクティビティを開始する (または他のことを行う) 「ランチャー」という名前のアクティビティを使用します。Modelオブジェクトを Application クラスに入れました。モデルは設定を使用してその状態を保存できます。アクティビティの静的フィールドを避けるためにそれを行います。

于 2011-07-20T07:29:05.857 に答える