【问题标题】:Android Multiple Notifications and with multiple intentsAndroid 多个通知和多个意图
【发布时间】:2019-07-18 15:51:42
【问题描述】:

我有一个相当简单的应用程序,它接受用户的输入,然后将其设置为通知。用户可以创建任意数量的通知,只要他/她喜欢。我希望用户单击通知并转到名为ResultActivity 的新活动。 ResultActivity 依次从通知意图中读取putExtras 并将其显示给用户。下面的代码几乎可以让我做任何我想做的事情,除了任何时候按下通知,我都会收到最后创建的通知的putExtra

Intent notificationIntent = new Intent(ctx, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, i,notificationIntent,PendingIntent.FLAG_CANCEL_CURRENT);

NotificationManager nm = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);

Resources res = ctx.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
builder.setContentIntent(contentIntent)
    .setSmallIcon(R.drawable.ic_launcher)
    .setLargeIcon(BitmapFactory.decodeResource(res,R.drawable.ic_launcher))
    .setTicker("Remember to " + text.getText())
    .setWhen(System.currentTimeMillis()).setAutoCancel(true)
    .setContentTitle(text.getText());

// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
String pass = text.getText().toString();

resultIntent.putExtra("title", pass);
resultIntent.putExtra("uid", i);

TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

new Uri.Builder().scheme("data").appendQueryParameter("text", "my text").build();
builder.setContentIntent(resultPendingIntent);

Notification n = builder.build();
n.flags = Notification.FLAG_NO_CLEAR;
nm.notify(i++, n);
text.setText(null);
  1. 打开应用程序

  2. 输入“一”

  3. 点击确定

  4. 通知已发送

  5. 打开应用程序

  6. 输入“二”

  7. 点击确定

  8. 通知已发送

现在您有两个通知。一个说“一”,一个说“二”。如果您单击通知“二”,它会将您带到一个显示“二”的屏幕。完美!

如果您点击通知“一”,它会将您带到一个显示“二”的屏幕。坏了!

ResultActivity.java

public class ResultActivity extends Activity {
    String title = null;
    TextView text;

    int i=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity);
        text = (TextView) findViewById(R.id.textView1);



        title = getIntent().getStringExtra("title");
         i = getIntent().getIntExtra("uid", 0);


        text.setText(title);

    }

【问题讨论】:

  • 请不要重新发布问题,即使您删除了旧问题。

标签: java android android-notifications


【解决方案1】:

我知道这是很久以前的事了,但我觉得答案并没有说明您代码中的问题。 所以问题就在这里 PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

因此,您从带有 update_current 标志的 stackbuilder 创建了一个pendingIntent。如果您查看 FLAG_UPDATE_CURRENT 它会说

 /**
 * Flag indicating that if the described PendingIntent already exists,
 * then keep it but replace its extra data with what is in this new
 * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
 * {@link #getService}. <p>This can be used if you are creating intents where only the
 * extras change, and don't care that any entities that received your
 * previous PendingIntent will be able to launch it with your new
 * extras even if they are not explicitly given to it.
 */
public static final int FLAG_UPDATE_CURRENT = 1<<27;

所以在您的用例中发生的情况是,您从 stackbuilder 创建了两个相同的 pendingintent,第二个意图覆盖了第一个。实际上,您永远不会创建第二个,您只是更新第一个的附加内容。

不幸的是,您的用例没有可用的标志,但有一个很好的技巧。您可以做的是使用 resultIntent 的 setAction 并放置一个随机字符串或对您的应用有意义的字符串。

例如。 resultIntent.setAction("dummy_action_" + notification.id);

这将使您的 resultIntent 足够独特,以便 pendingIntent 将创建它而不是更新以前的。

【讨论】:

  • 仅使用 PendingIntent.FLAG_ONE_SHOT 为我工作.. 这会产生任何其他问题吗?
  • 我为此损失了整整 4 个小时。 resultIntent.setAction 为我解决了这个问题。谢谢!
  • 我为此浪费了 4 个多小时,我不知道这是我一直遇到的问题,非常感谢这个 WA!!!
  • 针对 API 29+ 时,使用 intent.setIdentifier() 会更干净:developer.android.com/reference/android/content/…
【解决方案2】:

设置不同的requestCode 可以帮助我创建和更新当前意图。

val pendingIntent = PendingIntent.getActivity(
  this,
  notificationID,
  intent,
  PendingIntent.FLAG_UPDATE_CURRENT
)

【讨论】:

  • 我不知道为什么人们不投票赞成这个答案。如果您使用相同的请求代码,它将只创建一个待处理的意图,并且每次您使用相同的请求代码创建另一个时它都会更新。我已经尝试过这个解决方案,它就像一个魅力。谢谢哥们:)
  • 正确答案。谢谢
  • 这现在似乎对我有用。感谢您的提示!
【解决方案3】:

您创建了多个混合的意图。我清理了代码(但没有测试)

    NotificationManager nm = (NotificationManager) ctx
            .getSystemService(Context.NOTIFICATION_SERVICE);

    Resources res = ctx.getResources();

    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent(this, ResultActivity.class);
    String pass = text.getText().toString();
    resultIntent.setData(new Uri.Builder().scheme("data")
            .appendQueryParameter("text", "my text").build());
    resultIntent.putExtra("title", pass);
    resultIntent.putExtra("uid", i);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    // Adds the back stack for the Intent (but not the Intent itself)
    stackBuilder.addParentStack(ResultActivity.class);
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
    builder.setSmallIcon(R.drawable.ic_launcher)
            .setLargeIcon(
                    BitmapFactory.decodeResource(res,
                            R.drawable.ic_launcher))
            .setTicker("Remember to " + text.getText())
            .setWhen(System.currentTimeMillis()).setAutoCancel(true)
            .setContentTitle(text.getText())
            .setContentIntent(resultPendingIntent);

    Notification n = builder.build();
    n.flags = Notification.FLAG_NO_CLEAR;
    nm.notify(i++, n);

    text.setText(null);

【讨论】:

  • 我想以“正确”的方式做到这一点。我刚刚尝试了 UPDATE_CURRENT,但我遇到了同样的问题。
  • 我也尝试添加notificationIntent.setAction("ACTION_" + System.nanoTime);,但这也没有成功。
  • proper way 是让一个应用程序显示一个通知(查找“堆叠你的通知”)。如果您有多个通知,则应将它们合并为一个。如果您无论如何都需要显示多个通知,它们应该显示不同的数据。因此,在 data 参数中设置您的数据,而不是额外的。
  • 对不起,我把它和你几乎相同的问题混在一起了,我试图帮助你......
  • 标题或多或少是id,添加“ACTION_” + System.currentTimeMillis() 修复到与我设置数据相同的意图,所有意图都是唯一的。或者甚至更好地添加第二个参数,您可以将时间调用到意图 (resultIntent.setData(new Uri.Builder().scheme("data") .appendQueryParameter("text", "my text")..appendQueryParameter("time", String.valueOf(System.currentTimeMillis()).build());)
【解决方案4】:

使用一些随机的 requestCode 来分隔两个通知

PendingIntent pendingIntent = PendingIntent.getActivity(context, CommonTools.getRandomNumber(1, 100),
            notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

public int getRandomNumber(int min, int max) {
    // min (inclusive) and max (exclusive)
    Random r = new Random();
    return r.nextInt(max - min) + min;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    相关资源
    最近更新 更多