如何将参数从通知点击发送到活动?
Posted
技术标签:
【中文标题】如何将参数从通知点击发送到活动?【英文标题】:How to send parameters from a notification-click to an activity? 【发布时间】:2010-11-14 23:24:14 【问题描述】:我可以从我的通知中找到向我的活动发送参数的方法。
我有一个创建通知的服务。当用户单击通知时,我想使用一些特殊参数打开我的主要活动。例如一个项目 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);
我的 Activity 中尝试从通知中获取额外参数的代码:
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") );
额外的总是空的,我从来没有在我的日志中得到任何东西。
顺便说一句...onCreate
仅在我的活动开始时运行,如果我的活动已经开始,我还想收集额外内容并根据收到的 item_id 展示我的活动。
有什么想法吗?
【问题讨论】:
【参考方案1】:查看本指南 (creating a notification) 并查看 ApiDemos“StatusBarNotifications”和“NotificationDisplay”示例。
要管理活动是否已在运行,您有两种方法:
在启动activity时在Intent中添加FLAG_ACTIVITY_SINGLE_TOP标志,然后在activity类中实现onNewIntent(Intent intent)事件处理器,这样就可以访问为 Activity 调用的新 Intent(这与仅调用 getIntent() 不同,这将始终返回启动您的 Activity 的第一个 Intent。
与第一个相同,但您必须在活动 androidManifest.xml 中添加 "singleTop",而不是向 Intent 添加标志。
如果您使用 Intent Extras,请记住使用标志 PendingIntent.FLAG_UPDATE_CURRENT
调用 PendingIntent.getActivity()
,否则每个通知都会重复使用相同的 extras。
【讨论】:
并回答用户关于 extras 为 null 的问题:您必须使用标志PendingIntent.FLAG_UPDATE_CURRENT
调用 PendingIntent.getActivity()
,否则每个通知都会重复使用相同的 extras。
你拯救了我的一天,但为什么在 android 中传输这样简单的数据如此复杂
如果您应该有不同的通知,请确保在调用 PendingIntent.getActivity()
时使用不同的请求 ID,除了在 Intent
上设置 FLAG_ACTIVITY_SINGLE_TOP
和在 PendingIntent
上设置 FLAG_UPDATE_CURRENT
。见***.com/questions/7370324/…
@Matthias 看来onNewIntent()
已不再使用。和.. PendingIntent.getActivity()
和标志 PendingIntent.FLAG_UPDATE_CURRENT
拯救了我的一天!谢谢。
很好的答案。我花了几个小时调试试图弄清楚为什么意图没有通过额外的东西,PendingIntent.FLAG_UPDATE_CURRENT
正是我所需要的。谢谢。【参考方案2】:
我的应用程序显示消息通知时遇到了类似问题。 当有多个通知并单击每个通知时,它会在查看消息活动中显示该通知详细信息。我解决了在视图消息意图中收到相同额外参数的问题。
这是解决此问题的代码。 用于创建通知 Intent 的代码。
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);
【讨论】:
【参考方案3】:可能有点晚了,但是: 而不是这个:
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");
【讨论】:
对于 OP 来说也许迟到了,但对于互联网上的其他人来说永远不会迟到 :)【参考方案4】:在这里遇到同样的问题。 我通过使用不同的请求代码来解决它,使用相同的 id 作为通知,同时创建 PendingIntent。但仍然不知道为什么要这样做。
PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);
【讨论】:
【参考方案5】:在阅读了一些电子邮件列表和其他论坛后,我发现这个技巧似乎在意图中添加了一些独特的数据。
像这样:
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())));
我不明白为什么需要这样做,它与意图有关,不能仅通过其额外内容来识别......
【讨论】:
Anroid 重用意图,意图动作和请求代码使其唯一,但不是额外的数据。所以你需要设置一个唯一的请求 id 或者使用不同的意图操作。【参考方案6】:我尝试了所有方法,但没有任何效果。
最终想出了以下解决方案。
1- 在清单中为活动添加 android:launchMode="singleTop"
2- 在使待处理意图执行以下操作时,使用 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);
【讨论】:
它对我有用。必须使用不同的 requestCode 值和 PendingIntent.FLAG_UPDATE_CURRENT 标志。【参考方案7】: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");
希望它有所帮助,它基于 *** 上的其他答案,但这是对我有用的最新更新。
【讨论】:
【参考方案8】:很简单,这是我使用对象的解决方案!
我的 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");
祝你好运!!
【讨论】:
【参考方案9】:在您的通知实现中,使用如下代码:
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");
...
非常重要的提示: Intent::putExtra() 方法是一个重载方法。要获取额外的密钥,您需要使用 Intent::get[Type]Extra() 方法。
注意:NOTIFICATION_ID 和 NOTIFICATION_CHANNEL_ID 是在 ExampleActivity 中声明的常量
【讨论】:
【参考方案10】:在做了一些搜索后,我从 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") ;
【讨论】:
stackBuilder
是干什么用的?【参考方案11】:
请在显示通知时用作 PendingIntent,否则它将被解决。
PendingIntent 意图 = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
添加 PendingIntent.FLAG_UPDATE_CURRENT 作为最后一个字段。
【讨论】:
在 Android 10 上测试。工作。【参考方案12】:节日, 我也可以说我尝试了这些帖子中提到的所有内容以及其他一些帖子。 对我来说,第一个问题是新的 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());
有了这个序列,我得到了一个有效的捆绑包。
【讨论】:
【参考方案13】:如果你使用
android:taskAffinity="myApp.widget.notify.activity"
android:excludeFromRecents="true"
在要启动 Activity 的 AndroidManifest.xml 文件中,您必须在 Intent 中使用以下内容:
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()));
【讨论】:
以上是关于如何将参数从通知点击发送到活动?的主要内容,如果未能解决你的问题,请参考以下文章
将 Angular 中的点击发送到 Google Pub/Sub