13

私はこのソリューションを使用しています:新しいインテントを作成するのではなく、通知インテントを再開するにはどうすればよいですか?

アプリを正常に実行すると正常に動作しますが、アプリには共有機能があります。

ギャラリー アプリから共有したい画像を選択してアクティビティで開くと、アクティビティに通知が作成されます。ユーザーが通知をクリックすると、既存のアクティビティが開きます(ギャラリーアプリによって開かれます)

問題は、通知をクリックすると、そのアクティビティが再開されず、代わりにアクティビティの新しいインスタンスまたは以前に開かれた別のインスタンスが開かれることです

編集:より多くの説明

私のアプリは ShareApp と呼ばれ、アクティビティは ShareActivity と呼ばれます。問題は、ギャラリー アプリを介して ShareActivity を開くと、ShareActivity のインスタンスがギャラリー アプリ タスクのスタックの一番上に作成されることです。ShareActivity を指す通知を作成するときは、次のインテントを使用します。

Intent intent = new Intent(this, ShareActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

問題は、通知をクリックすると、ギャラリー アプリ タスクのスタックではなく、ShareApp タスクのスタック内の ShareActivity のインスタンスを指すことです。

正しいタスクのスタックを指す方法はありますか??

編集2:私のコード

        int defaults = Notification.FLAG_NO_CLEAR;
        NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle(getString(R.string.app_name))
                        .setContentText(text)
                        .setDefaults(defaults);
        Intent intent = new Intent(this, this.getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

        mBuilder.setContentIntent(pendingIntent);
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(_ID, mBuilder.build());

編集 3: adb shell dumpsys activity (David https://stackoverflow.com/a/16901603/1334268によるコードを適用した後)

私のアプリはshareAppと呼ばれ、私のアクティビティはShareActivityです

通知をクリックする前に:

Main stack:
    TaskRecord{41965708 #6 A com.android.gallery3d}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]}
      Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity}
        Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) }
        ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116}
      Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] }

通知をクリックした後:

 Main stack:
    TaskRecord{41965708 #6 A com.android.gallery3d}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]}
      Hist #3: ActivityRecord{4169f358 com.android.gallery3d/.app.Gallery}
        Intent { flg=0x20000000 cmp=com.android.gallery3d/.app.Gallery bnds=[0,205][480,301] }
        ProcessRecord{4175dd28 5808:com.android.gallery3d/10036}
      Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity}
        Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) }
        ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116}
      Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] }
4

5 に答える 5

31
    Notification.Builder mBuilder =
            new Notification.Builder(this)
            .setSmallIcon(R.drawable.cmplayer)
            .setContentTitle("CoderoMusicPlayer")
            .setContentText("PLayer0!");

    Intent resultIntent = new Intent(this, AndroidBuildingMusicPlayerActivity.class);
    resultIntent.setAction(Intent.ACTION_MAIN);
    resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            resultIntent, 0);

    mBuilder.setContentIntent(pendingIntent);
    NotificationManager mNotificationManager =
        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotificationManager.notify(1, mBuilder.build());

コードをコピーして、メインのランチャー アクティビティに貼り付けるだけです。

于 2014-01-29T07:43:47.407 に答える
5

設定

android:launchMode="singleTop"

あなたmanifest.xmlの主な活動のために、それが役立つかどうかを確認してください。

于 2013-06-02T18:20:38.037 に答える
3

これは、私が何年も使用してきたソリューションです。

あなたの問題は、あなたの PendingIntent が appless コンテンツからターゲットを開始することです。

最初のステップは、インテントの結果をアプリ コンテキスト内に取り込むことです。これを行うには、「ForwardingReceiver」へのブロードキャストを通知で呼び出します。

Intent newIntent = new Intent(context, ForwardingReceiver.class);
...
mBuilder.setContentIntent(PendingIntent.getBroadcast(context, category, newIntent, PendingIntent.FLAG_UPDATE_CURRENT));

ForwardingReceiver拡張BroadcastReceiverし、そのメソッドでアプリの現在のコンテキストを取得し、次のようにonReceive()使用できます。sendOrderedBroadcast()

Intent forwardIntent = new Intent();
forwardIntent.putExtras(intent.getExtras());
forwardIntent.setAction(GenericReceiver.class.getCanonicalName());
context.sendOrderedBroadcast(forwardIntent, null);

さて、楽しい部分です。共通のアクティビティの親からすべてのアプリのアクティビティを拡張する必要があります。ロギングまたは分析のためにすでにこれを行っている可能性があります。この CommonActivityParent では、ブロードキャストonResume()を 0 より上の優先度 (10 など) で受信するように登録する必要があります。

mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        performActionUsingIntent(intent);
    }
};

IntentFilter filter = new IntentFilter();
filter.addAction(GenericReceiver.class.getCanonicalName());
filter.setPriority(10);
registerReceiver(mReceiver, filter);

(これを onPause() で忘れずに登録解除してください)

これは、アプリがフォアグラウンドにある場合、通知クリックを (間接的に) 受け取り、アクションを実行できることを意味します。

ただし、Activity がバックグラウンドにある場合、このレシーバーは登録されません。問題ありません。「GenericReceiver」は次のようになります。

@Override
public void onReceive(Context context, Intent intent) {
    PackageManager pm = context.getPackageManager();
    Intent newIntent = pm.getLaunchIntentForPackage(context.getPackageName());
    newIntent.putExtras(intent.getExtras());
    context.startActivity(newIntent);
}

これにより、起動アクティビティが開始されます。この起動アクティビティの onCreate() には、それがタスク ルートであるかどうかを検出するためのコードが含まれている必要があります。そうでない場合は、すぐに閉じる必要があります (したがって、ユーザーには表示されません)。これにより、最後に開いていたタスクが効果的にフォアグラウンドに強制されます。

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

    if (!isTaskRoot()
            && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
            && getIntent().getAction() != null
            && getIntent().getAction().equals(Intent.ACTION_MAIN)) {

        // Use this space to add the intent to a static singleton. This will be used in CommonActivityParent to perform an action.
        CommonActivityParent.sIntent = getIntent();
        finish();
        return;
    }
}

最後に、上記の CommonActivityParent での呼び出しの直後にregisterReceiver()、次のチェックを実行してください。

if(sIntent != null) {
     Intent tempIntent = sIntent;
     sIntent = null;
     performActionUsingIntent(tempIntent);
}

お知らせ - アプリは、通知のクリックが実際にはアプリ内からのクリックであるかのように動作するようになりました。そして、それは非常に多くの作業でした!

うまくいけば、誰かがこれを行うための複雑でない方法を持っています。

于 2016-05-27T14:39:58.780 に答える
0

追加情報については、 onNewIntent が機能するように保留中のインテント フラグを追加することを忘れないでください。

真実:

PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT)

間違い:

PendingIntent.getActivity(context, 0, resultIntent, 0)
于 2020-05-12T00:43:01.957 に答える