生成int unique id作为android通知id

Zen*_*mer 51 java android push-notification

当我发送多个推送通知时,我需要它们全部显示在发送时间desc的通知栏中.我知道我应该使用独特的通知 - 我试图生成随机数,但这并没有解决我的问题,因为我需要它们被订购.我试图使用AtomicInt,但仍然没有达到预期的效果.

package com.mypackage.lebadagency;
import java.util.concurrent.atomic.AtomicInteger;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;



import android.widget.RemoteViews;

import com.google.android.gms.gcm.GoogleCloudMessaging;

public class GCMNotificationIntentService extends IntentService {

  private AtomicInteger c = new AtomicInteger(0);
  public int NOTIFICATION_ID = c.incrementAndGet(); 

  private NotificationManager mNotificationManager;
  NotificationCompat.Builder builder;

  public GCMNotificationIntentService() {
    super("GcmIntentService");
  }

  public static final String TAG = "GCMNotificationIntentService";

  @Override
  protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

    String messageType = gcm.getMessageType(intent);

    if (!extras.isEmpty()) {
      if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
          .equals(messageType)) {
        sendNotification("Send error: " + extras.toString());
      } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
          .equals(messageType)) {
        sendNotification("Deleted messages on server: "
            + extras.toString());
      } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
          .equals(messageType)) {

        for (int i = 0; i < 3; i++) {
          Log.i(TAG,
              "Working... " + (i + 1) + "/5 @ "
                  + SystemClock.elapsedRealtime());
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
          }

        }
        Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());

        sendNotification(""
            + extras.get(Config.MESSAGE_KEY));
        Log.i(TAG, "Received: " + extras.toString());
      }
    }
    GcmBroadcastReceiver.completeWakefulIntent(intent);
  }

  private void sendNotification(String msg) {

    Log.d(TAG, "Preparing to send notification...: " + msg);
    mNotificationManager = (NotificationManager) this
        .getSystemService(Context.NOTIFICATION_SERVICE);
    //here start
    Intent gcmintent = new Intent(this, AppGcmStation.class);
    gcmintent.putExtra("ntitle", msg);
    gcmintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    int requestID = (int) System.currentTimeMillis();
    //here end
    PendingIntent contentIntent = PendingIntent.getActivity(this, requestID,
        gcmintent, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
        this).setSmallIcon(R.drawable.ic_launcher)
        .setContentTitle("my title")
        .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
        .setContentText(msg);
    mBuilder.setAutoCancel(true);
    mBuilder.setTicker(msg);
    mBuilder.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 }); 
    mBuilder.setLights(Color.RED, 3000, 3000);
    mBuilder.setContentIntent(contentIntent);
    mBuilder.setDefaults(Notification.DEFAULT_SOUND);



    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    Log.d(TAG, "Notification sent successfully.");
  }
}
Run Code Online (Sandbox Code Playgroud)

我需要最好和最简单的方法来生成一个int id,它是增量的,将它指定为通知ID.

Ted*_*opp 87

您为所有通知使用相同的通知ID(值始终为1).您可能应该将通知ID分成单独的单例类:

public class NotificationID {
    private final static AtomicInteger c = new AtomicInteger(0);
    public static int getID() {
        return c.incrementAndGet();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用NotificationID.getID()而不是NOTIFICATION_ID代码.

编辑:正如@racs在评论中指出的那样,如果你的应用程序进程被杀死,上述方法还不足以确保正确的行为.至少AtomicInteger应该从某个活动的已保存状态初始化该值的初始值,而不是从0开始.如果通知ID在应用程序重新启动时需要是唯一的(同样,应用程序进程可能会被终止),那么每个增量后应将最新值保存到某个地方(可能是共享的首选项),并在应用程序启动时恢复.

  • 这不是一个合适的解决方案:如果您的应用程序被终止,那么ID将重新启动,除非您将之前的状态保存到应用程序启动之间的某个位置(例如,共享的首选项). (11认同)
  • 您的代码只调用一次 `incrementAndGet`:初始化 `NOTIFICATION_ID` 时。此后,您只需使用指定的值。此外,每次重新创建服务时,它都会将 `NOTIFICATION_ID` 初始化为 1。通过将 id 生成器移动到一个单独的类,它会创建一个值,该值在服务本身的生命周期之外持续存在(并持续到服务的持续时间)内存中的应用程序)。为了真正确保您的应用程序生成的每个通知都是唯一的,您可能应该将值保留在共享首选项(或其他方便的地方)中,以便它在整个过程关闭后仍然存在。 (2认同)

小智 25

对于仍然环顾四周的人.我生成了一个时间戳并将其用作id.

import java.util.Date;
import java.util.Locale;

public int createID(){
   Date now = new Date();
   int id = Integer.parseInt(new SimpleDateFormat("ddHHmmss",  Locale.US).format(now));
   return id;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它

int id = createID();
mNotifyManager.notify(id, mBuilder.build());
Run Code Online (Sandbox Code Playgroud)

  • 如果你在同一毫秒内收到多个通知,@ PaulFreez也是如此,但我同意赔率很小.在这种情况下,你也只需要:```int id =(int)System.currentTimeMillis();```保存任何解析处理. (6认同)
  • 我不推荐这种方法。用户可能会更改系统时钟(或在时区之间移动,或采用夏令时)并意外地导致 ID 冲突。并且同一秒内发送的多个通知将具有相同的 id。 (4认同)
  • @RaphaelC你可能想要为该格式添加毫秒,所以它是"ddHHmmssSS" (2认同)
  • @Paul Freez 当然有效。它只会被截断。 (2认同)

Rap*_*l C 14

private static final String PREFERENCE_LAST_NOTIF_ID = "PREFERENCE_LAST_NOTIF_ID";

private static int getNextNotifId(Context context) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    int id = sharedPreferences.getInt(PREFERENCE_LAST_NOTIF_ID, 0) + 1;
    if (id == Integer.MAX_VALUE) { id = 0; } // isn't this over kill ??? hahaha!!  ^_^
    sharedPreferences.edit().putInt(PREFERENCE_LAST_NOTIF_ID, id).apply();
    return id;
}
Run Code Online (Sandbox Code Playgroud)

  • @AndreiBogdan并非如此:当调用`apply`时,对磁盘的提交是异步的,而内存中的数据会立即更新.如果此SharedPreferences上的另一个编辑器在apply()尚未完成时执行常规commit(),则commit()将阻塞,直到完成所有异步提交以及提交本身.简而言之,https://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply(),不会发生这种情况.我还针对这个特殊情况进行了单元测试,您可以轻松地检查自己是否会发生这种情况. (6认同)
  • 我发布此内容可能只是为了好玩,但我们必须尊重,您的答案在这种情况下不起作用,您的应用程序发送了数字 Integer.MAX_VALUE 的通知,然后您的 id 将重置为值 0,因此它将覆盖第一个通知id 0。但是这种情况真的永远不会达到,因为你可能无法在android中收到这么多通知,但理论上......算了,我只是在开玩笑XD谢谢你的好答案!PS 不错的评论^_^ (2认同)

Age*_*t_L 6

也许不是最好的方法,但是绝对最简单的方法是使用当前时间。

int oneTimeID = (int) SystemClock.uptimeMillis();
mNotificationManager.notify(oneTimeID, mBuilder.build());
Run Code Online (Sandbox Code Playgroud)

好处:这是获取ID增加的最简单方法。

坏处是:时间是a long,我们将其缩短为一半。这意味着计数器将每隔2'147'483'647个回绕/ 1000(ms-> s)/ 60(s-> m)/ 60(m-> h)/ 24(h-> d)=〜 25天

SystemClock.uptimeMillis()与以下两个优点相比currentTimeMillis

  1. 减少了深度睡眠所花费的所有毫秒数,从而减少了环绕次数。
  2. 重新启动手机时,从0开始。


Chu*_*y47 5

您可以使用计数器并将其存储在 SharedPreferences 中。这是 kotlin 中的一个例子:

fun getNextNotificationId(context: Context) : Int {
    val sp = context.getSharedPreferences("your_shared_preferences_key", MODE_PRIVATE)
    val id = sp.getInt("notification_id_key", 0)
    sp.edit().putInt("notification_id_key", (id + 1) % Int.MAX_VALUE).apply()

    return id
}
Run Code Online (Sandbox Code Playgroud)

它将获取 id 并存储下一个 id(加 1),而且如果 id 达到整数的最大值,它将重置为 0。

你可以这样使用它:

val notificationId = getNextNotificationId(applicationContext)
notificationManager.notify(notificationId, yourNotification)
Run Code Online (Sandbox Code Playgroud)


ImB*_*man 5

您需要设置唯一标签(字符串)/ id(整数)

这个方法可以参考官方文档

我建议在通知时使用任何时间戳(SystemClock.uptimeMillis() / System.currentTimeMillis())作为标签。

 notificationManager.notify(String.valueOf(System.currentTimeMillis()), 0, notification);
Run Code Online (Sandbox Code Playgroud)