web-dev-qa-db-ja.com

Android-PendingIntentで機能しないタスクフラグをクリアする

A> B> Cのタスクスタックがあります。現在Cを使用しているので、ホームボタンを押します。アクティビティAに移動する意図で通知を受け取ります。通知を押すと、Aにいますが、押すと、C、B、Aの順に移動します。

私はPendingIntentをそのように設定しています。明らかに何か問題がありますか?

final Intent notificationIntent = new Intent(mContext, ActivityA.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);


        PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);

編集1:

ここで提案を試しました: タスク内のすべてのアクティビティをクリアしますか?

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

しかし、それでも同じ結果が得られます。アクティビティAはアプリケーションタスクスタックで開始します。押し戻してC、B、Aの順に移動します。

これはAndroid)では不可能であるか、保留中のインテントを使用している場合は不可能であると私は考え始めています。

編集2:これはどのフラグが必要かという問題ではありません。何がうまくいかないのかという問題の多くは、フラグが効果がないように見えることです。

16
user2676468

ソリューション1を使用している場合は、マニフェストからlaunchMode="singleTask"を削除するだけです。

1)

 final Intent notificationIntent = new Intent(mContext, ActivityA.class);

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

 PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);

OR

2)

       <activity 
       Android:name=".ActivityA" 
       Android:theme="@style/theme_noActionBar" 
       Android:noHistory="true">

OR

3)

<activity Android:name=".ActivityA" Android:launchMode="singleTop">
16

あなたが直面している問題は、Android PendingIntentと必要なIntent.FLAG_ACTIVITY_NEW_TASKを使用して新しいタスクを作成することと関係があります。言い換えれば、あなたがしたいフラグは使用は、特定のタスクスタックのコンテキスト内でアクティビティを開始することと関係があります。通常、PendingIntentにはコンテキストがないため、表示されているのは、アクティビティAの保留中のインテント用に作成されているタスクです。

ドキュメントへの参照は次のとおりです。

AndroidのPendingIntent

一連のPendingIntentsの最初のIntent.FLAG_ACTIVITY_NEW_TASKが必要なのが問題です。一連の保留中のインテントは、「getActivities」メソッドを使用して、最初の保留中のインテントと同じコンテキストを持つことができることに注意してください。

フラグだけを使ってやりたいことをすることはできないというのは正しいです。コードは正しいので、必要な動作を得るには、インテントフラグを超えて調べる必要があります。

マニフェストの使用、サービスの実行、静的フィールドの使用など、他にも多くの方法で、関心のあることを管理しようとします。さらに、マニフェストを使用するルートに進むことにした場合は、TaskStackBuilderを使用して問題を解決できる可能性があります。フラグを含まない他の多くの解決策もありますが、フラグの使用について具体的に質問しました。

6
Jim

マニフェストファイルでは、ActivityAのlaunchModesingleTaskに設定できます。 ActivityAはアプリケーションのルートであるため、機能します。

から ドキュメント

システムは、新しいタスクのルートにアクティビティを作成し、インテントをそのタスクにルーティングします。ただし、アクティビティのインスタンスがすでに存在する場合、システムは、新しいインスタンスを作成するのではなく、onNewIntent()メソッドの呼び出しを介してインテントを既存のインスタンスにルーティングします。

        <activity
            Android:name=".MainActivity"
            Android:label="@string/app_name"
            Android:launchMode="singleTask" >
            <intent-filter>
                <action Android:name="Android.intent.action.MAIN" />

                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

編集1:

マニフェストファイルを変更したくないので、私が見ることができる唯一のオプションは、 Intent.makeRestartActivityTask メソッドを使用してインテントを生成することです。ただし、これにより、既存のインスタンスが再開されるのではなく、ActivityAが再起動されます。

Intent intent = Intent.makeRestartActivityTask(new ComponentName(this, ActivityA.class));
PendingIntent rIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
5
Manish Mulimani

私はこれに関してたくさんの問題を抱えていました、そして私が私のアプリをアンインストール/再インストールするまで私は夢中になっていると思っていました、そしてちょっとプレスト、コードはスタックオーバーフローの多くの投稿に従って動作します。私は次のことをしていました:

Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);

そして、アプリの2つのバージョンを継続的に取得していました。一方のデバイスでアンインストールし、もう一方のデバイスを再起動すると、すべてが1つのインスタンスで期待どおりに動作するようになります。これがお役に立てば幸いです。

3
Simon Huckett

インテントフラグに関する解決策は次のとおりです。

  1. マニフェストで、アクティビティAに_launchMode:singleTask_を追加します
  2. 次のコードブロックを使用します。

    _final Intent notificationIntent = new Intent(mContext, ActivityA.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);
    _

ここで何が起こるかというと、_Intent.FLAG_ACTIVITY_NEW_TASK_の定義により、アクティビティAが通知を使用して起動されると、Aを含むタスクA> B> Cが存在するため、このタスクが進められ、アクティビティB、C、およびAも破棄されます。 _onNewIntent --> onRestart --> onStart --> onResume_で始まります

現在開始しているアクティビティに対してタスクがすでに実行されている場合、そのタスクは最後の状態が復元された状態でフォアグラウンドになり、アクティビティはonNewIntent()で新しいインテントを受け取ります。

インテントフラグだけではうまく動作しない理由は、アクティビティAがsingleTaskモードで起動されず、Androidどういうわけか維持されないためです。それの状態。

2
Laks

インテントフラグを使用してみてくださいFLAG_ACTIVITY_CLEAR_TOPタスクをクリアする代わりに。 インテントドキュメント から:

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

たとえば、アクティビティA、B、C、Dで構成されるタスクについて考えてみます。DがアクティビティBのコンポーネントに解決されるインテントでstartActivity()を呼び出すと、CとDは終了し、Bは指定されたインテントを受け取ります。 、結果としてスタックはA、Bになります。

1
Dan Amato

私のソリューションコード:

    public class MyApplication extends Application{
    private static int activityCounter;
    public Activity A,B,C;
    public void incrementActivityCounter()
    {
        activityCounter++;
    }
    public void decrementActivityCounter()
    {
        activityCounter--;
        if (activityCounter == 0)
        {
            A.finish();
            B.finish();
            C.finish();
        }
    }
}


public class A extends Activity{
   @Override
    protected void onStart()
    {
        super.onStart();
        application.incrementActivityCounter();
    }

    @Override
    protected void onStop()
    {
        application.decrementActivityCounter();
        super.onStop();
    }
}
1
Khamchunovog

私はあなたの説明としてデモプロジェクトを作成しました、そしてそれはあなたが望むように機能します。

通知を取得する方法がわからないため、私のプロジェクトでは、BroadcastReceiverを使用してブロードキャストを取得し、ReceiverのonReceive()メソッドで通知を表示します。私のデモをプロジェクトと比較して、問題を見つけることができると思います。ところで、私のテストはAPI16で実行されます。

これが私のデモです: https://github.com/leoguo123/AndroidDemo

リポジトリ内:

テストプロジェクトには3つのアクティビティ(A> B> C)が含まれており、適切なブロードキャストを受信すると通知を表示できます。 SendBroadcastプロジェクトは、ブロードキャストの送信を担当します。

通知を生成するためのコード:

    public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        showNotification(context);
    }

    private void showNotification(Context context) {
        Intent intent = new Intent(context, ActivityA.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP
                | Intent.FLAG_ACTIVITY_NEW_TASK);
        NotificationManager nmr = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
        Notification.Builder builder = new Notification.Builder(context);
        builder.setContentTitle("Open A with B and C being closed");
        builder.setContentText("Open A with B and C being closed");
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentIntent(pi);
        builder.setAutoCancel(true);
        Notification nt = builder.build();
        nmr.notify(0, nt);
    }
}
1
Lei Guo

上記のすべての提案を試しましたが失敗し、 https://stackoverflow.com/a/24999724/4271334 および https://stackoverflow.com)のガイドラインから解決策を考え出しました。/a/26592562/4271334 。マニフェストに次の2行を追加

Android:launchMode="singleTask"
Android:clearTaskOnLaunch="true"

を使用してNotificationCompat.BuilderでPendingIntentを設定します

mBuilder.setContentIntent(addBackStack(mContext,intent));

どこ

public static PendingIntent addBackStack(final Context context, final Intent intent) {
    TaskStackBuilder stackBuilder = TaskStackBuilder.create (context.getApplicationContext ());
    stackBuilder.addNextIntentWithParentStack (intent);
    intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
    return stackBuilder.getPendingIntent (0,PendingIntent.FLAG_UPDATE_CURRENT);
}

誰かが助けられることを願っています。

0
Sabet Chowdhury