如何将参数从通知单击发送到活动?


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介绍我的活动。

有任何想法吗?

Answers:


241

查看本指南(创建通知)并示例ApiDemos“ StatusBarNotifications”和“ NotificationDisplay”。

要管理活动是否已在运行,您有两种方法:

  1. 添加 FLAG_ACTIVITY_SINGLE_TOP标志的意图开展活动时,然后在活动类实现 onNewIntent(意向意图)事件处理程序,这样你可以访问新的意图,这是所谓的活动(这是不一样的只是打电话getIntent (),它将始终返回启动您的活动的第一个Intent。

  2. 与第一名相同,但必须在活动AndroidManifest.xml中添加“ singleTop”,而不是向Intent添加标志。

如果您使用Intent Extras,请记住PendingIntent.getActivity()使用flag 调用PendingIntent.FLAG_UPDATE_CURRENT,否则相同的Extras将被重用于每个通知。


95
并回答用户有关Extras是否为null的问题:您必须PendingIntent.getActivity()使用flag 进行调用PendingIntent.FLAG_UPDATE_CURRENT,否则相同的Extras将在每个通知中重复使用。
马赛厄斯2009年

2
您保存了我的一天,但是为什么要在android中传输像这样复杂的简单数据
非法论点

8
如果您有不同的通知,请确保PendingIntent.getActivity()除了FLAG_ACTIVITY_SINGLE_TOPIntentFLAG_UPDATE_CURRENT上进行设置之外,在调用时还使用不同的请求ID PendingIntent。见stackoverflow.com/questions/7370324/...
schnatterer

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来说很晚,但是对于Internet上的其他人来说却永远不会迟到:)
espinchi 2011年

19

在这里遇到同样的问题。我通过使用不同的请求代码来解决它,在创建PendingIntent时使用与通知相同的ID。但仍然不知道为什么要这样做。

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

14

在阅读了一些电子邮件列表和其他论坛后,我发现该技巧似乎为意图添加了一些唯一数据。

像这样:

   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时执行以下操作,使用bundle而不是直接使用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);

要在测试活动类中获得Intent的额外价值,您需要编写以下代码:

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

3
stackBuilder为了什么
AlexioVay

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()方法是一个重载一个。要获取额外的密钥,您需要使用Intent :: get [Type] Extra()方法。

注意:NOTIFICATION_IDNOTIFICATION_CHANNEL_ID是在ExampleActivity中声明的常量


1

今天,我也可以说我尝试了这些帖子中提到的所有内容,还尝试了其他地方的更多内容。对我来说,第一个问题是新的Intent始终具有空捆绑包。我的问题是过多地关注“我包括.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添加为最后一个字段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.