it-roy-ru.com

Создайте уникальный идентификатор int как идентификатор уведомления Android

Когда я отправляю несколько Push-уведомлений, мне нужно, чтобы все они отображались в панели уведомлений, упорядоченной по времени отправки. Я знаю, что должен использовать уникальное уведомление - я попытался сгенерировать случайное число, но это не решило мою проблему, так как мне нужно, чтобы они были заказаны. Я пытался использовать 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.");
  }
}

Мне нужен ЛУЧШИЙ и самый простой способ для генерации внутреннего идентификатора, который является инкрементным, чтобы назначить его в качестве идентификатора уведомления.

37
Zenogrammer

Вы используете один и тот же идентификатор уведомления (значение всегда равно 1) для всех ваших уведомлений. Вы, вероятно, должны выделить идентификатор уведомления в отдельный синглтон-класс:

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

Затем используйте NotificationID.getID() вместо NOTIFICATION_ID в вашем коде.

Правка: Как отмечает @racs в комментарии, вышеупомянутого подхода недостаточно для обеспечения правильного поведения, если ваш процесс приложения оказывается убитым. Как минимум, начальное значение AtomicInteger должно быть инициализировано из сохраненного состояния некоторой активности, а не начинаться с 0. Если идентификаторы уведомлений должны быть уникальными при перезапуске приложения (опять же, где процесс приложения может быть прерван), затем последнее значение должно быть сохранено где-то (возможно, в общих префиксах) после каждого приращения и восстанавливаться при запуске приложения.

71
Ted Hopp

Для тех, кто все еще смотрит вокруг. Я сгенерировал метку времени и использовал ее в качестве идентификатора.

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;
}

Используйте это так

int id = createID();
mNotifyManager.notify(id, mBuilder.build());
19
Adetunji Mohammed
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;
}
11
Raphael C

Вы можете использовать счетчик и сохранить его в 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
}

он получит идентификатор и сохранит следующий идентификатор (увеличенный на 1); также, если идентификатор достигает максимального значения для целого числа, он будет сброшен до 0.

Вы можете использовать это так:

val notificationId = getNextNotificationId(applicationContext)
notificationManager.notify(notificationId, yourNotification)
1
Chuy47

Может быть, не самый лучший, но определенно самый простой использовать текущее время. 

int oneTimeID = (int) SystemClock.uptimeMillis();
mNotificationManager.notify(oneTimeID, mBuilder.build());

Хорошее: это самый простой способ получить идентификаторы.

Плохое: время long, и мы сокращаем его до половины этого. Это означает, что счетчик будет отображаться каждые 2'147'483'647/1000 (мс-> с)/60 (с-> м)/60 (м-> ч)/24 (ч-> д) = ~ 25 дней.

SystemClock.uptimeMillis() имеет 2 преимущества перед currentTimeMillis:

  1. скидка на все миллисекунды, затраченные на глубокий сон, что уменьшает количество циклов.
  2. начинается с 0, когда телефон перезагружается.
1
Agent_L

Если кто-то читает это, есть метод здесь . Лучше указывать имя tag также с помощью id, так что это поможет, если вы объединяете деталь как модуль, чтобы поделиться с разработчиками.

ПРИМЕЧАНИЕ. Проблема с назначением некоторого случайного целого идентификатора состоит в том, что, если какой-либо модуль или библиотека использует тот же идентификатор, ваше уведомление будет заменено новыми данными уведомления.

// here createID method means any generic method of creating an integer id
int id = createID();
// it will uniqly identify your module with uniq tag name & update if present.
mNotifyManager.notify("com.packagename.app", id, mBuilder.build());
0
I Am Batman