2014-09-07 3 views
27

Когда я отправляю несколько push-уведомлений, мне нужно, чтобы все они отображались в панели уведомлений, упорядоченной по расписанию отправления. Я знаю, что должен использовать уникальное уведомление - я попытался создать случайное число, но это не решило мою проблему, так как мне нужно, чтобы они были заказаны. Я пытался использовать AtomicInt и до сих пор не имеет желаемого результата.Сгенерировать уникальный идентификатор int как идентификатор уведомления о android

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."); 
    } 
} 

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

+0

_ «Я попытался использовать атомиту и не получил желаемого результата» - Какой результат вы получили и чем он отличается от желаемого результата? –

+0

, когда я использовал атомарное устройство, устройство Android восстанавливает все уведомления, но в списке уведомлений отображается только последнее отправленное уведомление. – Zenogrammer

ответ

51

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

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. Если идентификаторы уведомлений должны быть уникальными для перезапуска приложения (опять же, когда процесс приложения может быть убит) то последнее значение должно быть сохранено где-нибудь (возможно, для общих привилегий) после каждого приращения и восстанавливаться при запуске приложения.

+0

Большое спасибо, я постараюсь первым делом с утра. – Zenogrammer

+0

еще раз спасибо вам, но вы можете объяснить мне, почему он работает, когда он находится в отдельном классе и не работает в моем коде? – Zenogrammer

+0

Ваш код вызывает 'incrementAndGet' ровно один раз: при инициализации' NOTIFICATION_ID'. После этого вы просто используете назначенное значение. Кроме того, каждый раз, когда служба воссоздается, она инициализирует «NOTIFICATION_ID» до 1. Путем перемещения генератора идентификаторов в отдельный класс он создает значение, которое сохраняется за пределами срока службы самой службы (и длится дольше приложение в памяти). Чтобы быть действительно безопасным, чтобы каждое уведомление, созданное вашим приложением, было уникальным, вы, возможно, должны сохранять значение в общих предпочтениях (или где-то еще удобном), чтобы он оставался полностью закрытым процессом. –

13

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

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()); 
+0

, поэтому, если вы получаете несколько уведомлений за одну секунду, оно все равно отменяет предыдущий? –

+0

@RaphaelC вы можете добавить миллисекунды в этот формат, так что это будет «ddHHmmssSS» –

+3

@PaulFreez то же самое, если вы получаете несколько уведомлений за одну миллисекунду, но я согласен, что шансы малы. И в этом случае вы также просто переходите к: '' 'int id = (int) System.currentTimeMillis();' '' сохраняет любую обработку синтаксического анализа. –

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

Если кто-то читает это, есть метод here. лучше указать имя 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()); 
+1

Укажите, что такое 'createID()', это путает, если вы не прочитали другие ответы. – user905686

+0

@ user905686 обновленные комментарии –

+0

@ I Am Batman. Спасибо. Теперь интересно, как это отвечает на вопрос? Как добавление тега влияет на порядок? И это не решает исходную проблему необходимости уникальных идентификаторов. Если вы хотите добавить это как дополнительную информацию, подумайте о том, чтобы заменить свой ответ комментарием к ответу. – user905686

Смежные вопросы