2012-10-12 32 views
5

Mục tiêu: Thông báo xuất hiện hàng ngày một lần, lúc 2 giờ chiều, nếu điều kiện nhất định được đáp ứng.Thông báo lặp lại trên Android 4

Ví dụ: Để đơn giản, hãy xem xét điều kiện, được kiểm tra bằng kết nối Internet, được đáp ứng hàng ngày. Nếu hôm nay là sau 2 giờ chiều, chúng tôi sẽ bắt đầu thông báo từ ngày mai. Ví dụ: người dùng bắt đầu ứng dụng lúc 4 giờ chiều vào Thứ Hai và anh ấy nhận được thông báo vào Thứ Hai 2 giờ chiều, Thứ Tư 2 giờ chiều, Thứ Năm 2 giờ chiều và cứ tiếp tục như vậy.

Sự cố: Lúc 2 giờ chiều, có thông báo đầu tiên, nhưng sau đó tôi nhận được cùng một thông báo lặp đi lặp lại, vào các thời điểm ngẫu nhiên.

Sự cố dường như chỉ xuất hiện trên Android> = 4.0. Nó hoạt động tốt trên Android trước đó.

Đây là cách tôi gửi thông báo:

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() được gọi lúc 2 PM, vì 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() được gọi từ 2 nơi. Đầu tiên, khi bắt đầu ứng dụng. Thứ hai, từ mã trên, khi điện thoại khởi động lại (onReceive() nhận được BOOT_COMPLETED). Tôi làm điều đó, bởi vì khi người dùng tắt điện thoại, AlarmManager sẽ xóa báo thức.

Vì vậy, tất cả sẽ hoạt động, vì alarmManager.setRepeating() ghi đè báo thức trước đó.

Tôi đã phát hiện ra rằng ai đó có cùng một vấn đề, nhưng cũng không có câu trả lời:
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/t_tDU4PwR3g

Cũng ở đây tôi thấy vấn đề tương tự: http://comments.gmane.org/gmane.comp.handhelds.android.devel/171471

Một thời gian trước, tôi hỏi làm thế nào để tạo ra các thông báo như vậy , vì vậy, điều này có liên quan:
Everyday notifications at certain time

+1

trong 'sendNotification', thay thế' getApplication() 'với' this', thay thế 'getBaseContext()' với 'this', và thay thế' Intent.FLAG_ACTIVITY_NEW_TASK' với cái gì đó thuộc về đó, là 'Intent' cờ không đi theo phương thức tĩnh trên 'PendingIntent'. Ngoài ra, không sử dụng 'RTC_WAKEUP' với' getService() '' PendingIntent', vì điều đó không đáng tin cậy - sử dụng [my 'WakefulIntentService'] (https://github.com/commonsguy/cwac-wakeful) hoặc cái gì khác hoạt động từ 'getBroadcast()' 'PendingIntent'. – CommonsWare

+1

Ngoài ra, sử dụng 'adb shell dumpsys alarm' để kiểm tra các báo động đã lên lịch, sử dụng các điểm ngắt để xem điều gì đang kích hoạt phương thức' sendNotification() ', v.v. – CommonsWare

+1

Cảm ơn bạn rất nhiều @CommonsWare, tôi đã làm theo lời khuyên của bạn. Tuy nhiên, vấn đề vẫn xảy ra trên điện thoại di động với Android 4. Có thể có một số lỗi trong việc triển khai API của họ không? Bởi vì tôi đã đọc điều đó trong Android 4, họ đã giới thiệu "thông báo phong phú", vì vậy họ đã thay đổi mã một chút. –

Trả lời

1

Sử dụng AlarmManager.RTC_WAKEUP inste d AlarmManager.RTC

Trong AlarmManager.RTC

thời gian báo thức trong System.currentTimeMillis() (thời gian đồng hồ treo tường theo giờ UTC). Báo thức này không đánh thức thiết bị lên; nếu nó tắt trong khi thiết bị đang ngủ, nó sẽ không được gửi đến lần sau khi thiết bị tỉnh dậy.

nơi như trong AlarmManager.RTC_WAKEUP

thời gian báo thức trong System.currentTimeMillis() (tường đồng hồ thời gian theo giờ UTC), mà sẽ thức dậy điện thoại khi nó đi ra.

+0

Điều này là sai, theo nhận xét đầu tiên cho bài đăng của tôi được tạo bởi @CommonsWare. "Ngoài ra, không sử dụng RTC_WAKEUP với getService() PendingIntent, vì điều đó không đáng tin cậy." –

1

Đã xảy ra sự cố tương tự trên thiết bị ICS +. Cách giải quyết của tôi rất đơn giản-> Đặt thời gian hiện tại vào tùy chọn được chia sẻ khi thông báo được hiển thị. Trước đó luôn kiểm tra xem khoảng thời gian có thực sự trôi qua hay không và nếu không chỉ hủy bỏ.

  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(); 
        } 
      } 
Các vấn đề liên quan