永続的な通知を使用して、ユーザーが実行中のAndroidアプリに戻ることができるようにします
-
01-10-2019 - |
質問
私は多くのアクティビティを備えたアプリを開発しています。 (多かれ少なかれ)「AppName -AppNameに戻る」と言っている永続的な通知を作成したいと思います。 通知の作成と廃棄は問題ありませんでした。
これで、ユーザーはいくつかの画面/アクティビティのいずれかに参加し、アプリケーションを残してから、通知を介してアプリに再入力したいと考えています。 問題は, 、通知には意図が必要で、 所定の活動. 。通知にアプリに再入力してもらいたい 歴史スタックの一番上にあるアクティビティが何であれ.
醜い回避策での私の最初の試みは、「oncreate」で「完成」することである唯一の仕事がアクティビティを行うことでした(「returnfromnotify」と呼びましょう)。通知は、アプリケーション履歴の範囲で「ReturnFromNotify」を開き、すぐにそれ自体を削除し、アプリケーションスタックの以前の履歴状態にユーザーを送り返します。これは機能しているようです...ユーザーが「バック」を使用してアプリから完全にバックアウトしない限り。次に、通知を押したとき、「ReturnFromNotify」ロード、終了して、ホーム画面に送り返します(アプリの履歴スタックにはアクティビティがないため)。
「returnfromnotify」の前に歴史スタックに何かがあるかどうかを検出しようとすることを検討し、そうでない場合は、私の主な活動を起動しました。私もこれを行う方法を見つけることができないようです。
Java/Android初心者の入力や提案はありますか?参考までに、私の主な歴史はスクリプトベースの言語です。
解決
私はあなたの最初のアイデアがあなたの提案されている回避策よりも「returnfromnotify」アクティビティを作成するのが好きです。 は 再安全性がスタックの下部にあるかどうかを検出できます(したがって、スタック内の唯一のアクティビティ)。
これがあなたがそれを行う方法です:
マニフェストに再開を追加し、指定します 履歴はありません 属性:
<activity android:name=".ResumeActivity" android:noHistory="true" />
Nohistoryを指定すると、このアクティビティが終了したらすぐにスタックにとどまることができなくなります。これにより、現在実行中のインスタンスのみがスタックに表示されることがわかります。
アプリケーションスタックを確認するには、get_tasksの許可を求める必要があります。
<uses-permission android:name="android.permission.GET_TASKS" />
これで使用できます ActivityManager :: getRunningTasks() 再安全性がスタック内の唯一のアクティビティであるかどうかを判断するには。
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年以上前にこの質問をしたことを知っていますが、私はこの答えを提供しています。あなたが元々取り組んでいたソリューションであなたは正しい軌道に乗っていたと思います。
他のヒント
さて、私は満足のいく仕事を見つけたと信じています 私の特定の場合. 。 「MainActivity」に静的整数を追加しましたが、「OnCreate」が発射されるたびに、整数が増加します。 「ondestroy」が解雇されるたびに、減少します。
私の「ReturnfromNotify」では、静的整数を見て、0より大きいかどうかを確認します。もしそうなら、アクティブな「MainActivity」があり、「Return fromNotify」内で「Return」内で「実行」を実行すると仮定します。それ以外の場合は、ユーザーが「バックアウト」し、それ自体を仕上げてから「Startactivity」を使用して「MainActivity」の新しいインスタンスを起動していると想定しています。
これは普遍的な解決策ではありませんが、私の目的のために、それで十分だと思います。私はまだ他の答えにオープンです。誰かが私の論理に穴を開けることができれば、そうしてください - 建設的 批判は大歓迎です. 。ありがとう。
私はこれを行う簡単な方法はないと思いますが、マインアクティビティにカウンターを追加する代わりに私は拡張します 応用:
グローバルアプリケーションの状態を維持する必要がある人のための基本クラス。 AndroidManifest.xmlのタグにその名前を指定することにより、独自の実装を提供できます。これにより、アプリケーション/パッケージのプロセスが作成されたときにそのクラスがインスタンス化されます。
私はそこにロジックをマンタインし、次のような方法を持っています。
public Intent getIntentForLastActivityShown();
通知アイテムがクリックされたときに呼び出されます。
私の最初のアプローチは使用することです SharedPreferences
そして、ようなものと呼ばれるキー値のペアを保存します lastDisplayedActivity
. 。次に、各アクティビティで onResume
(そしておそらく「oncreate」)あなたは次のような行を持っているでしょう:
sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME);
つまり、最後に表示されたアクティビティを示すアプリケーション全体の変数を保存します。次に、この変数をSharedPreferencesから取得し、対応するアクティビティを起動するだけです。
私は通常、アプリケーションの状態をチェックする「ランチャー」という名前のアクティビティを使用します モデル モデルルールに応じてアクティビティ(または他のことを行う)を開始します。置いた モデル アプリケーションクラスのオブジェクト。 モデル 使える 環境設定 その状態を保存します。私は活動の静的フィールドを避けるためにそれをします。