通知クリックからアクティビティにパラメーターを送信する方法は?


206

通知からアクティビティにパラメータを送信する方法を見つけることができます。

通知を作成するサービスがあります。ユーザーが通知をクリックすると、いくつかの特別なパラメーターを使用してメインアクティビティを開きます。たとえば、アイテムIDを使用すると、私のアクティビティで特別なアイテムの詳細ビューを読み込んで表示できます。具体的には、ファイルをダウンロードしています。ファイルがダウンロードされたら、クリックすると特別なモードでアクティビティが開かれるように通知するようにしたいと思います。私はputExtra自分の意図で使用しようとしましたが、それを抽出できないようですので、間違っていると思います。

通知を作成する私のサービスのコード:

        // construct the Notification object.
     final Notification notif = new Notification(R.drawable.icon, tickerText, System.currentTimeMillis());


    final RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
    contentView.setImageViewResource(R.id.image, R.drawable.icon);
    contentView.setTextViewText(R.id.text, tickerText);
    contentView.setProgressBar(R.id.progress,100,0, false);
    notif.contentView = contentView;        

    Intent notificationIntent = new Intent(context, Main.class);
    notificationIntent.putExtra("item_id", "1001"); // <-- HERE I PUT THE EXTRA VALUE
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notif.contentIntent = contentIntent;

    nm.notify(id, notif);

通知から追加のパラメーターを取得しようとする私のアクティビティからのコード:

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

    setContentView(R.layout.main);


    Bundle extras = getIntent().getExtras();
    if(extras != null){
        Log.i( "dd","Extra:" + extras.getString("item_id") );
    }

extrasは常にnullであり、ログに何も記録しません。

ところで...はonCreate私のアクティビティが開始されたときにのみ実行されます。私のアクティビティがすでに開始されている場合は、エキストラも収集して、受け取ったitem_idに基づいてアクティビティを表示します。

何か案は?

回答:


241

このガイド(通知の作成)とApiDemosのサンプル "StatusBarNotifications"および "NotificationDisplay"をご覧ください。

アクティビティが既に実行されているかどうかを管理するには、2つの方法があります。

  1. アクティビティの起動時にFLAG_ACTIVITY_SINGLE_TOPフラグをインテントに追加し 、次にアクティビティクラスの実装 onNewIntent(Intent intent)イベントハンドラーで、アクティビティに対して呼び出された新しいインテントにアクセスできます(これはgetIntentを呼び出すだけとは異なります) ()、これは常にアクティビティを開始した最初のインテントを返します。

  2. 番号1と同じですが、インテントにフラグを追加する代わりに、アクティビティAndroidManifest.xmlに「singleTop」を追加する必要があります。

インテントエクストラを使用する場合PendingIntent.getActivity()は、フラグを付けて呼び出すことを忘れPendingIntent.FLAG_UPDATE_CURRENTないでください。それ以外の場合は、通知ごとに同じエクストラが再利用されます。


95
エキストラがnullであるというユーザーの質問に答えるにはPendingIntent.getActivity()、フラグを使用して呼び出す必要があります。PendingIntent.FLAG_UPDATE_CURRENTそうしないと、すべての通知で同じエキストラが再利用されます。
Matthias

2
uは私の日を救ったが、なぜこのように単純なデータをAndroidで非常に複雑に転送しているのか
違法な議論

8
異なる通知が必要な場合は、とでのPendingIntent.getActivity()設定FLAG_ACTIVITY_SINGLE_TOPに加えて、呼び出し時に異なるリクエストIDを使用してください。stackoverflow.com/questions/7370324/…を参照してくださいIntentFLAG_UPDATE_CURRENTPendingIntent
schnatterer 2014

101

私のアプリケーションがメッセージ通知を表示する同様の問題がありました。複数の通知があり、各通知をクリックすると、メッセージ通知アクティビティにその通知の詳細が表示されます。ビューメッセージインテントで同じ追加のパラメーターが受信される問題を解決しました。

これを修正したコードは次のとおりです。通知インテントを作成するためのコード。

 Intent notificationIntent = new Intent(getApplicationContext(), viewmessage.class);
    notificationIntent.putExtra("NotificationMessage", notificationMessage);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingNotificationIntent = PendingIntent.getActivity(getApplicationContext(),notificationIndex,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.setLatestEventInfo(getApplicationContext(), notificationTitle, notificationMessage, pendingNotificationIntent);

メッセージアクティビティを表示するためのコード。

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

    onNewIntent(getIntent());
}

@Override
public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    if(extras != null){
        if(extras.containsKey("NotificationMessage"))
        {
            setContentView(R.layout.viewmain);
            // extract the extra-data in the Notification
            String msg = extras.getString("NotificationMessage");
            txtView = (TextView) findViewById(R.id.txtMessage);
            txtView.setText(msg);
        }
    }


}

29

多分少し遅れますが、これの代わりに:

public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    Log.i( "dbg","onNewIntent");

    if(extras != null){
        Log.i( "dbg", "Extra6 bool: "+ extras.containsKey("net.dbg.android.fjol"));
        Log.i( "dbg", "Extra6 val : "+ extras.getString("net.dbg.android.fjol"));

    }
    mTabsController.setActiveTab(TabsController.TAB_DOWNLOADS);
}

これを使って:

Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("keyName");
}

20
多分OPに遅れますが、インターネットの他の人に遅れることはありません:)
espinchi

19

ここで同じ問題に遭遇します。PendingIntentの作成中に、別の要求コードを使用して解決し、通知と同じIDを使用します。しかし、なぜこれを行う必要があるのか​​はまだわかりません。

PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);

14

いくつかのメーリングリストや他のフォーラムを読んだ後、そのトリックがsom固有のデータをインテントに追加しているように見えることがわかりました。

このような:

   Intent notificationIntent = new Intent(Main.this, Main.class);
   notificationIntent.putExtra("sport_id", "sport"+id);
   notificationIntent.putExtra("game_url", "gameURL"+id);

   notificationIntent.setData((Uri.parse("foobar://"+SystemClock.elapsedRealtime()))); 

なぜこれを行う必要があるのか​​理解できません。イントラと何か関係があるので、エキストラだけでは識別できません...


8
Anroidはインテントを再利用します。インテントアクションとリクエストコードはそれを一意にしますが、追加のデータは一意にしません。したがって、一意のリクエストIDを設定するか、別のインテントアクションを使用する必要があります。
バチ

10

私はすべてを試しましたが、何もうまくいきませんでした。

最終的に次の解決策が思い付きました。

1-アクティビティandroid:launchMode = "singleTop"のマニフェスト追加

2-保留中のインテントに次のことをさせる間、直接intent.putString()またはintent.putInt()を使用する代わりにバンドルを使用します

                    Intent notificationIntent = new Intent(getApplicationContext(), CourseActivity.class);

                    Bundle bundle = new Bundle();
                    bundle.putString(Constants.EXAM_ID,String.valueOf(lectureDownloadStatus.getExamId()));
                    bundle.putInt(Constants.COURSE_ID,(int)lectureDownloadStatus.getCourseId());
                    bundle.putString(Constants.IMAGE_URL,lectureDownloadStatus.getImageUrl());

                    notificationIntent.putExtras(bundle);

                    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                            Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),
                            new Random().nextInt(), notificationIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT); 

3
わたしにはできる。異なるrequestCode値とPendingIntent.FLAG_UPDATE_CURRENTフラグを使用する必要があります。
phuongle 2015年

4

AndroidManifest.xml

launchMode = "singleTop"を含めます

<activity android:name=".MessagesDetailsActivity"
        android:launchMode="singleTop"
        android:excludeFromRecents="true"
        />

SMSReceiver.java

IntentおよびPendingIntentのフラグを設定します

Intent intent = new Intent(context, MessagesDetailsActivity.class);
    intent.putExtra("smsMsg", smsObject.getMsg());
    intent.putExtra("smsAddress", smsObject.getAddress());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    PendingIntent contentIntent = PendingIntent.getActivity(context, notification_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

MessageDetailsActivity.java

onResume()-毎回呼び出され、エクストラをロードします。

Intent intent = getIntent();
    String extraAddress = intent.getStringExtra("smsAddress");
    String extraBody = intent.getStringExtra("smsMsg");

それが役に立てば幸い、それはstackoverflowに関する他の回答に基づいていましたが、これは私のために働いた最も更新されたものです


3

それは簡単です、これはオブジェクトを使用した私の解決策です!

私のPOJO

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

メソッド通知

  Person person = new Person();
  person.setName("david hackro");
  person.setAge(10);

    Intent notificationIntent = new Intent(this, Person.class);
    notificationIntent.putExtra("person",person);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.notification_icon)
                .setAutoCancel(true)
                .setColor(getResources().getColor(R.color.ColorTipografiaAdeudos))
                .setPriority(2)
                .setLargeIcon(bm)
                .setTicker(fotomulta.getTitle())
                .setContentText(fotomulta.getMessage())
                .setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT))
                .setWhen(System.currentTimeMillis())
                .setContentTitle(fotomulta.getTicketText())
                .setDefaults(Notification.DEFAULT_ALL);

新しい活動

 private Person person;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification_push);
    person = (Person) getIntent().getSerializableExtra("person");
}

幸運を!!


3

いくつかの検索を行った後、Android開発者ガイドから解決策を得ました

PendingIntent contentIntent ;
Intent intent = new Intent(this,TestActivity.class);
intent.putExtra("extra","Test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

stackBuilder.addParentStack(ArticleDetailedActivity.class);

contentIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

Test ActivityクラスでIntentの追加の値を取得するには、次のコードを記述する必要があります。

 Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;

3
何のstackBuilderため?
AlexioVay 2017年

1

通知の実装では、次のようなコードを使用します。

NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
...
Intent intent = new Intent(this, ExampleActivity.class);
intent.putExtra("EXTRA_KEY", "value");

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
nBuilder.setContentIntent(pendingIntent);
...

ExampleActivityでIntentの追加の値を取得するには、次のコードを使用します。

...
Intent intent = getIntent();
if(intent!=null) {
    String extraKey = intent.getStringExtra("EXTRA_KEY");
}
...

非常に重要な注意:テント:: putExtra()メソッドはオーバーロード1です。追加のキーを取得するには、Intent :: get [Type] Extra()メソッドを使用する必要があります。

注:NOTIFICATION_IDおよびNOTIFICATION_CHANNEL_IDは、ExampleActivityで宣言された定数です。


1

私もこれらの投稿で言及されたすべてを試し、他の場所からいくつか試しました。私にとっての最大の問題は、新しいインテントには常にnullバンドルがあったことです。私の問題は、「。thisまたは.thatを含めたか」の詳細に焦点を合わせすぎていたことです。私の解決策は、詳細から一歩戻り、通知の全体的な構造を見ることでした。それを行ったとき、コードの重要な部分を正しい順序で配置することができました。したがって、同様の問題が発生している場合は、次の点を確認してください。

1. Intent notificationIntent = new Intent(MainActivity.this, NotificationActivity.class);

2a. Bundle bundle = new Bundle();

//データタイプをより適切に指定したい。例:bundle.putInt

2b. notificationIntent.putExtras(bundle);
3. PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, WIZARD_NOTIFICATION_ID, notificationIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
4. NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
5.          NotificationCompat.Builder nBuilder =
                    new NotificationCompat.Builder(this)
                            .setSmallIcon(R.drawable.ic_notify)
                            .setContentTitle(title)
                            .setContentText(content)
                            .setContentIntent(contentIntent)
                            .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                            .setAutoCancel(false)//false is standard. true == automatically removes the notification when the user taps it.
                            .setColor(getResources().getColor(R.color.colorPrimary))
                            .setCategory(Notification.CATEGORY_REMINDER)
                            .setPriority(Notification.PRIORITY_HIGH)
                            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
            notificationManager.notify(WIZARD_NOTIFICATION_ID, nBuilder.build());

このシーケンスで、有効なバンドルを取得します。


0

使用する場合

android:taskAffinity="myApp.widget.notify.activity"
android:excludeFromRecents="true"

AndroidManifest.xmlファイルでアクティビティを起動するには、インテントで以下を使用する必要があります。

Intent notificationClick = new Intent(context, NotifyActivity.class);
    Bundle bdl = new Bundle();
    bdl.putSerializable(NotifyActivity.Bundle_myItem, myItem);
    notificationClick.putExtras(bdl);
    notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
    notificationClick.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);  // schließt tasks der app und startet einen seperaten neuen

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(NotifyActivity.class);
    stackBuilder.addNextIntent(notificationClick);

    PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(notificationPendingIntent);

重要なのは、たとえば次のような一意のIDを使用して、一意のデータを設定することです。

notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));


0

通知が表示される間はPendingIntentとして使用してください。解決されます。

PendingIntent intent = PendingIntent.getActivity(this、0、notificationIntent、PendingIntent.FLAG_UPDATE_CURRENT);

PendingIntent.FLAG_UPDATE_CURRENTを最後のフィールドとして追加します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.