2012-10-12 19 views
5

Obiettivo: La notifica viene visualizzata ogni giorno una volta, alle 14:00, se vengono soddisfatte determinate condizioni.Ripetizione delle notifiche su Android 4

Esempio: Per semplicità, consideriamo che la condizione, verificata con connessione Internet, viene soddisfatta ogni giorno. Se oggi è già dopo le 14:00, inizieremo le notifiche da domani. Ad esempio, l'utente avvia l'app alle 16:00 di lunedì e riceve le notifiche martedì 2, mercoledì 2, giovedì 2 e così via.

Problema: Alle 14:00 c'è una prima notifica, ma poi ricevo la stessa notifica più e più volte, in momenti casuali.

Il problema sembra essere solo su Android> = 4.0. Funziona bene con gli androidi precedenti.

Questo è come mi invia la notifica:

public class NotifyService extends Service 
{  
static final int NOTIFICATION_ID = 1; 
// ... 

@Override 
public IBinder onBind(Intent intent) 
{ 
    return null; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) 
{ 
    try 
    { 
     Symbol biggest = getBiggestMover(); 
     if (biggest != null) 
     { 
      String title = getString(R.string.app_name); 
      String text = getNotificationText(biggest.symbol, biggest.change); 
      sendNotification(title, text); 
     } 
    } 
    catch (Exception e) 
    { 
     // If there is Internet problem we do nothing, don't want to disturb the user. 
     e.printStackTrace(); 
    } 

    return super.onStartCommand(intent, flags, startId); 
} 

/** @return Symbol which is the biggest mover today. If there is no big mover - null is returned. 
* @throws Exception If there is Internet problem. */ 
private Symbol getBiggestMover() throws Exception 
{ 
    Symbol biggest = null; 
    Symbol[] equities = Network.getTraded(SymbolType.EQUITY); 
    for (Symbol equity : equities) 
    { 
     if (Utilities.isToday(equity.lastTraded) && isBigMove(equity.change) && isBigger(equity, biggest)) 
     { 
      biggest = equity; 
     } 
    } 
    return biggest; 
} 

private void sendNotification(String title, String text) 
{ 
    Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis()); 
    notification.flags = Notification.FLAG_AUTO_CANCEL; 

    Intent clickIntent = new Intent(this, MainActivity.class); 
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); 

    notification.setLatestEventInfo(this, title, text, pendingIntent); 

    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
    manager.notify(NOTIFICATION_ID, notification); 
} 
// ... 
} 

sendNotification() è chiamato alle 14:00, a causa della AlarmManager:

public class ServiceStarter extends BroadcastReceiver 
{ 

@Override 
public void onReceive(Context context, Intent intent) 
{ 
    setNotificationAlarm(context); 
} 

/** Set repeating notifications every 24 hours. */ 
public static void setNotificationAlarm(Context context) 
{ 
    Intent intent = new Intent(context, NotifyService.class); 
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
    PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 

    final int oneDay = 24 * 60 * 60 * 1000; 
    alarmManager.setRepeating(AlarmManager.RTC, getTriggerTime(), oneDay, pendingIntent); 
} 

private static long getTriggerTime() 
{ 
    GregorianCalendar calendar = new GregorianCalendar(); 
    calendar.set(GregorianCalendar.HOUR_OF_DAY, 14); 
    calendar.set(GregorianCalendar.MINUTE, 0); 
    calendar.set(GregorianCalendar.SECOND, 0); 
    calendar.set(GregorianCalendar.MILLISECOND, 0); 

    if (calendar.before(new GregorianCalendar())) 
    { 
     calendar.add(GregorianCalendar.DAY_OF_MONTH, 1); 
    } 

    return calendar.getTimeInMillis(); 
} 

} 

setNotificationAlarm() viene chiamato da 2 posti. Innanzitutto, all'inizio dell'app. In secondo luogo, dal codice sopra, quando il telefono si riavvia (onReceive() riceve BOOT_COMPLETED). Lo faccio, perché quando l'utente spegne il telefono, AlarmManager cancella i suoi allarmi.

Quindi tutto dovrebbe funzionare, perché alarmManager.setRepeating() sovrascrive l'allarme precedente.

ho scoperto che qualcuno ha avuto lo stesso problema, ma anche nessuna risposta:
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/t_tDU4PwR3g

Anche qui ho trovato problema simile: http://comments.gmane.org/gmane.comp.handhelds.android.devel/171471

Qualche tempo fa ho chiesto come creare tali notifiche , quindi questo è legato:
Everyday notifications at certain time

+1

Nel 'sendNotification', sostituire' getApplication() '' con this', sostituire 'getBaseContext()' 'con this', e sostituire' Intent.FLAG_ACTIVITY_NEW_TASK' con qualcosa che vi appartiene, come 'Intent' i flag non vanno in metodi statici su 'PendingIntent'. Inoltre, non usare 'RTC_WAKEUP' con un' getService() '' PendingIntent', come quello è inaffidabile - usa [il mio 'WakefulIntentService'] (https://github.com/commonsguy/cwac-wakeful) o qualcos'altro che funziona su un 'getBroadcast()' 'PendingIntent'. – CommonsWare

+1

Oltre a ciò, utilizzare 'dumpsys adb shell alarm' per esaminare i vostri allarmi programmati, utilizzare i punti di interruzione per vedere che cosa sta provocando il tuo metodo' sendNotification(), ecc – CommonsWare

+1

La ringrazio molto @CommonsWare, ho seguito il vostro consigli. Tuttavia, il problema si verifica ancora sui dispositivi mobili con Android 4. È possibile che ci sia qualche bug nella loro implementazione API? Perché ho letto che in Android 4 hanno introdotto "notifiche ricche", quindi hanno cambiato un po 'il codice. –

risposta

1

Usa AlarmManager.RTC_WAKEUP inste d di AlarmManager.RTC

In AlarmManager.RTC

tempo di allarme in System.currentTimeMillis() (tempo di orologio da parete in UTC). Questo allarme non riattiva il dispositivo; se si spegne mentre il dispositivo è in sospensione, non verrà consegnato fino al prossimo riavvio del dispositivo.

dove come in AlarmManager.RTC_WAKEUP

tempo di allarme in System.currentTimeMillis() (tempo di orologio da parete in UTC), che si sveglia il dispositivo quando si spegne.

+0

Questo è sbagliato, secondo il primo commento al mio post che è stato fatto da @CommonsWare. "Inoltre, non utilizzare RTC_WAKEUP con getService() PendingIntent, poiché non è affidabile." –

1

Aveva lo stesso problema sul dispositivo ICS +. La mia soluzione era molto semplice-> Metti l'ora corrente nelle preferenze condivise quando viene mostrata la notifica. Prima controlla sempre se l'intervallo è realmente passato e se non solo abortisci.

  long lastnotification = sharedPrefs.getLong("lnnd", -1); 
      Calendar now = Calendar.getInstance(); 
      if (!namedayalarmEnabled) { 
        return; 
      } 
      if (lastnotification > 1) { 
        Calendar last = Calendar.getInstance(); 
        last.setTimeInMillis(lastnotification); 
        long distance = (now.getTimeInMillis() - last 
            .getTimeInMillis()); 
        if (distance < YOURINTERVAL) { 
          return; 
        } else { 
          SharedPreferences.Editor editor = sharedPrefs.edit(); 
          editor.putLong("lnnd", now.getTimeInMillis()); 
          editor.commit(); 
        } 
      } 
Problemi correlati