2012-10-12 59 views
5

目標:如果滿足某些條件,通知每天在下午2點出現一次。在Android上重複發送通知4

例如:爲了簡單起見,我們考慮每天都會檢查通過Internet連接檢查的條件。如果今天下午2點以後,我們會從明天開始通知。例如,用戶在週一下午4點開始應用,他會在週二下午2點,週三下午2點,週四下午2點等收到通知。

問題:在下午2點有第一個通知,但隨後一次又一次地得到相同的通知,隨機時間。

問題似乎只在Android> = 4.0。它在早期的Android上運行良好。

這是我如何發送通知:因爲AlarmManager

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()被稱爲凌晨2時許,:

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()從2個地方叫。首先,在應用程序的開始。其次,從上面的代碼,當手機重新啓動(onReceive()收到BOOT_COMPLETED)。我這樣做,因爲當用戶關閉手機時,AlarmManager會清除其警報。

所以一切都應該工作,因爲alarmManager.setRepeating()覆蓋以前的報警。

我發現有人有同樣的問題,但也沒有答案:
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/t_tDU4PwR3g

而且我在這裏發現了類似的問題: http://comments.gmane.org/gmane.comp.handhelds.android.devel/171471

前段時間我問到如何創建這樣的通知,所以這是相關的:
Everyday notifications at certain time

+1

在'sendNotification',替換'getApplication()''與this',替換'getBaseContext()''與this',並與一些屬於有取代'Intent.FLAG_ACTIVITY_NEW_TASK',如'Intent'標誌不會進入PendingIntent的靜態方法。另外,不要將'RTC_WAKEUP'與'getService()''PendingIntent'一起使用,因爲這是不可靠的 - 使用[我的'WakefulIntentService'](https://github.com/commonsguy/cwac-wakeful)或其他東西這是一個'getBroadcast()''PendingIntent'。 – CommonsWare

+1

除此之外,使用'adb shell dumpsys alarm'來檢查你的預定警報,使用斷點來查看觸發你的'sendNotification()'方法等。 – CommonsWare

+1

非常感謝@CommonsWare,我遵循你的建議。但是,使用Android 4的手機仍然會出現問題。他們的API實施中是否存在一些錯誤?因爲我已經閱讀過Android 4,所以他們推出了「豐富的通知」,所以他們已經改變了一些代碼。 –

回答

1

使用AlarmManager.RTC_WAKEUP inste在System.currentTimeMillis的AlarmManager.RTC

的d在AlarmManager.RTC

報警時間()(以UTC掛鐘時間)。該警報不會喚醒設備;如果它在設備睡着的時候熄滅,它將不會在設備下一次喚醒之前交付。

其中如在AlarmManager.RTC_WAKEUP

在System.currentTimeMillis的鬧鈴時間()(以UTC掛鐘時間)中,當它熄滅,這將喚醒設備。

+0

這是錯誤的,根據@CommonsWare對我發佈的第一條評論。 「另外,請勿將RTC_WAKEUP與getService()PendingIntent一起使用,因爲這是不可靠的。」 –

1

在ICS +設備上有同樣的問題。我的解決方法非常簡單 - >在顯示通知時將當前時間放入共享首選項中。在此之前,請始終檢查間隔是否確實通過,如果不是中止。

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