web-dev-qa-db-ja.com

通知からアクティビティを再開する

アプリのステータスバーに通知があります。

    Notification notification = new Notification(R.drawable.icon, null, System.currentTimeMillis());

    Intent notificationIntent = new Intent(this.parent, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this.parent, 0, notificationIntent, 0);

    ...

    notification.flags = Notification.FLAG_ONGOING_EVENT;        
    mNotificationManager.notify(NOTIFICATION_ID, notification);

これに伴う問題は、アプリからホームボタンを押して(バックグラウンドにプッシュして)、ステータスバーからアクセスしたリストの通知を押すと、アクティビティの新しいコピーが開始されることです。私がやりたいのは、アプリを再開することだけです(ホームボタンを長押ししてアプリのアイコンを押すときなど)。これを行うためのインテントを作成する方法はありますか?

35
mazbox

AndroidManifest.xmlファイルでアクティビティのlaunchModesingleTaskに変更することで、この問題を解決しました。

このプロパティのデフォルト値はstandardで、これにより任意の数のインスタンスを実行できます。

「singleTask」および「singleInstance」アクティビティは、タスクを開始することしかできません。それらは常にアクティビティスタックのルートにあります。さらに、デバイスは一度に1つのアクティビティのインスタンスのみを保持できます—そのようなタスクは1つだけです。 [...]

「singleTask」モードと「singleInstance」モードも、1つの点でのみ互いに​​異なります。「singleTask」アクティビティを使用すると、他のアクティビティをそのタスクの一部にすることができます。それは常にそのタスクのルートにありますが、他のアクティビティ(必然的に「標準」および「singleTop」アクティビティ)をそのタスクに起動できます。一方、「singleInstance」アクティビティでは、他のアクティビティをそのタスクの一部にすることはできません。これは、タスクの唯一のアクティビティです。別のアクティビティを開始すると、そのアクティビティは別のタスクに割り当てられます—FLAG_ACTIVITY_NEW_TASKが意図されているかのように。

詳細な説明は Android開発者ガイド にあります。

これがお役に立てば幸いです

32
rekaszeru

一部のインテントがエクストラを失い、MainActivityのOnNewIntentメソッドとonCreateメソッドの両方が呼び出されているデバイス間で一貫性のない動作がありました。

何をしましたか機能しません

マニフェスト:

    <activity Android:name=".MainActivity"
        Android:launchMode="singleTask">

サービス:

    Intent notificationIntent = new Intent(this.getBaseContext(), MainActivity.class);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    notificationIntent.putExtra("TEST", 1);

動作しました

マニフェスト:

    <activity Android:name=".MainActivity"
        Android:launchMode="singleTask">

サービス:

    PackageManager pm = getPackageManager();
    Intent launchIntent = m.getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);
    launchIntent.putExtra("TEST", 2);
1
user2965003

私は同様の問題を抱えていました。これを処理する適切な方法は、フラグを使用することです:Intent.FLAG_ACTIVITY_CLEAR_TOPおよびIntent.FLAG_ACTIVITY_SINGLE_TOP

notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

ドキュメントから、これは次のようになります。

FLAG_ACTIVITY_CLEAR_TOP

設定されていて、起動中のアクティビティが現在のタスクですでに実行されている場合、そのアクティビティの新しいインスタンスを起動する代わりに、その上にある他のすべてのアクティビティが閉じられ、このインテントが(現在上)新しいインテントとしての古いアクティビティ。

FLAG_ACTIVITY_SINGLE_TOP

設定されている場合、アクティビティは履歴スタックの最上位ですでに実行されていると起動されません。

1
Nick.D

この行を、アプリのマニフェストファイルの対応するアクティビティに追加します。

Android:launchMode="singleTask"

例えば:

<activity
    Android:name=".Main_Activity"
    Android:label="@string/title_main_activity"
    Android:theme="@style/AppTheme.NoActionBar"
    Android:launchMode="singleTask" />

起動インテントをシミュレート(ユーザーがアプリアイコンをクリックして起動したかのように):

val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)

val contentIntent = PendingIntent.getActivity(context, 0, launchIntent, 0)

このようにして、notマニフェストでアプリを「singleTask」または「singleInstance」としてマークする必要があります(これにより他の問題が発生します)。したがって、これは適切な解決策になるはずです。

ただし、Androidバグが疑われるため、上記の解決策が直接機能しない場合があります。Androidバグと回避策を見つけることができます この質問で

0
user1032613

私はこの問題の解決策を見つけました:私はgetPreviousIntentメソッドを作成し、それをPendingIntentに渡しました。

private Intent getPreviousIntent(Intent newIntent) {
    final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    final List<ActivityManager.RecentTaskInfo> recentTaskInfos = am.getRecentTasks(1024,0);
    String myPkgNm = getPackageName();

    if (!recentTaskInfos.isEmpty()) {
        ActivityManager.RecentTaskInfo recentTaskInfo;
        for (int i = 0; i < recentTaskInfos.size(); i++) {
            recentTaskInfo = recentTaskInfos.get(i);
            if (recentTaskInfo.baseIntent.getComponent().getPackageName().equals(myPkgNm)) {
                newIntent = recentTaskInfo.baseIntent;
                newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
        }
    }
    return newIntent;
}
0
nAkhmedov