12

我试图在将来为某个时间设置通知。 我有创建通知的代码,但我找不到安排它的选项。如何在Android中安排通知

我该如何安排通知?

+1

这仍然是有用的贝科使用另一个问题是在此之前3年,一些潜在的行为已经改变,所以谢谢! – AfzalivE

回答

16

您需要使用PendingIntentBroadCastReceiver此 -

public void scheduleNotification(Context context, long delay, int notificationId) {//delay is after how much time(in millis) from current time you want to schedule the notification 
     NotificationCompat.Builder builder = new NotificationCompat.Builder(context) 
       .setContentTitle(context.getString(R.string.title)) 
       .setContentText(context.getString(R.string.content)) 
       .setAutoCancel(true) 
       .setSmallIcon(R.drawable.app_icon) 
       .setLargeIcon(((BitmapDrawable) context.getResources().getDrawable(R.drawable.app_icon)).getBitmap()) 
       .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); 

     Intent intent = new Intent(context, YourActivity.class); 
     PendingIntent activity = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT); 
     builder.setContentIntent(activity); 

     Notification notification = builder.build(); 

     Intent notificationIntent = new Intent(context, MyNotificationPublisher.class); 
     notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); 
     notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, notification); 
     PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT); 

     long futureInMillis = SystemClock.elapsedRealtime() + delay; 
     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
     alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent); 
    } 

此外,你需要证明你的接收机类的通知 -

public class MyNotificationPublisher extends BroadcastReceiver { 

    public static String NOTIFICATION_ID = "notification_id"; 
    public static String NOTIFICATION = "notification"; 

    @Override 
    public void onReceive(final Context context, Intent intent) { 

     NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 

     Notification notification = intent.getParcelableExtra(NOTIFICATION); 
     int notificationId = intent.getIntExtra(NOTIFICATION_ID, 0); 
     notificationManager.notify(notificationId, notification); 
    } 
} 

最后,调用scheduleNotification()用适当的参数和你很好去!

+0

非常感谢,它为我工作。 – OmerN

+0

所以每天12点例如...那些代码是在主要活动? – Si8

+0

此应用在“近期应用列表”中刷卡时,此代码预定闹钟将被取消。如何避免这个问题? – NghiaDao

24

NOT FOR USE IN奥利奥+(编辑)

以上的回答都不错 - 但不考虑用户重启设备(它清除的PendingIntent的由AlarmManager计划)的潜力。

您需要创建一个WakefulBroadcastReceiver,它将包含一个AlarmManager来计划传递一个PendingIntent。当WakefulBroadcastReceiver处理该意图时 - 发布您的通知并发信号通知WakefulBroadcastReceiver完成。

WakefulBroadcastReceiver

/** 
    * When the alarm fires, this WakefulBroadcastReceiver receives the broadcast Intent 
    * and then posts the notification. 
    */ 
    public class WakefulReceiver extends WakefulBroadcastReceiver { 
     // provides access to the system alarm services. 
     private AlarmManager mAlarmManager; 

     public void onReceive(Context context, Intent intent) { 
      //// TODO: post notification 
      WakefulReceiver.completeWakefulIntent(intent); 
     } 

     /** 
     * Sets the next alarm to run. When the alarm fires, 
     * the app broadcasts an Intent to this WakefulBroadcastReceiver. 
     * @param context the context of the app's Activity. 
     */ 
     public void setAlarm(Context context) { 
      mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
      Intent intent = new Intent(context, WakefulReceiver.class); 
      PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 

      Calendar calendar = Calendar.getInstance(); 
      calendar.setTimeInMillis(System.currentTimeMillis()); 
      //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int); 
      //calendar.add(Calendar.SECOND, 10); 

      //ALWAYS recompute the calendar after using add, set, roll 
      Date date = calendar.getTime(); 

      mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent); 

      // Enable {@code BootReceiver} to automatically restart when the 
      // device is rebooted. 
      //// TODO: you may need to reference the context by ApplicationActivity.class 
      ComponentName receiver = new ComponentName(context, BootReceiver.class); 
      PackageManager pm = context.getPackageManager(); 
      pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
        PackageManager.DONT_KILL_APP); 
     } 

     /** 
     * Cancels the next alarm from running. Removes any intents set by this 
     * WakefulBroadcastReceiver. 
     * @param context the context of the app's Activity 
     */ 
     public void cancelAlarm(Context context) { 
      Log.d("WakefulAlarmReceiver", "{cancelAlarm}"); 

      mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
      Intent intent = new Intent(context, WakefulReceiver.class); 
      PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 

      mAlarmManager.cancel(alarmIntent); 

      // Disable {@code BootReceiver} so that it doesn't automatically restart when the device is rebooted. 
      //// TODO: you may need to reference the context by ApplicationActivity.class 
      ComponentName receiver = new ComponentName(context, BootReceiver.class); 
      PackageManager pm = context.getPackageManager(); 
      pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
        PackageManager.DONT_KILL_APP); 
     } 

BootReceiver

public class BootReceiver extends BroadcastReceiver { 

     @Override 
     public void onReceive(Context context, Intent intent) { 
      if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { 
      context = ApplicationActivity.class; 
      AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
      Intent intent = new Intent(context, WakefulReceiver.class); 
      PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 

      Calendar calendar = Calendar.getInstance(); 
      calendar.setTimeInMillis(System.currentTimeMillis()); 
      //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int); 
      //calendar.add(Calendar.SECOND, 10); 

      //ALWAYS recompute the calendar after using add, set, roll 
      Date date = calendar.getTime(); 

      alarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent); 
      } 
     } 
    } 

AndroidManifest.xml中

<receiver android:name=".WakefulReceiver"/> 

<receiver android:name=".BootReceiver" 
    android:enabled="false"> 
    <intent-filter> 
     <action android:name="android.intent.action.BOOT_COMPLETED"/> 
    </intent-filter> 
</receiver> 
+0

这是黄金!很高兴找到它。 –

+2

嘿在'BootReceiver.class'你不应该使用手动类型“android.intent.action.BOOT_COMPLETED”而是使用'Intent.ACTION_BOOT_COMPLETED' – SARose

+1

好抓 - 我已经更新了!感谢您的贡献。 – apelsoczi