实现通知服务的技术

发布于 2024-11-30 16:12:28 字数 382 浏览 3 评论 0原文

我有一个主要活动,用户可以在其中启用/禁用通知、设置通知间隔以及设置通知间隔将使用的基准时间。通知通常会间隔大约 2 小时触发。经过一定时间后,累加器将达到最大值并且不再需要通知。

实施此类通知计划的标准方法是什么?我尝试使用 postAtTime 在服务内部使用处理程序,但似乎有很多条件可能导致它永远无法运行。我查看了服务内部的计时器,但将手机置于待机状态会停止任何计时器,而且这似乎是一个坏主意。

我遇到的唯一其他选项尚未探索,但它涉及使用 AlarmManagerBroadcastReceiver。我应该放弃该服务并安排重复警报吗?一旦我的累加器达到最大值,我需要能够禁用所有剩余的警报。

感谢您的任何意见。

I have a main activity where the user can enable/disable notifications, set the notification interval, and set the base time the notification interval will use. Notifications will typically trigger about 2 hours from each other. After a certain time, an accumulator will reach a maximum value and notifications will no longer be needed.

What is the standard way of implementing such a notification scheme? I tried using a handler inside of a service using postAtTime, but it seems that there are a lot of conditions that can cause it to never run. I looked at a timer inside of the service, but putting the phone in standby will stop any timers, plus it just seems like a bad idea.

The only other option I came across I have yet to explore, but it involves using an AlarmManager and a BroadcastReceiver. Should I just ditch the service and schedule a repeating alarm instead? I need to be able to disable all remaining alarms once my accumulator has reached max value.

Thanks for any input.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

家住魔仙堡 2024-12-07 16:12:28

如果您启动一个产生这样的线程的服务会怎么样:

thread t = new thread(new Runnable(){
    public void Run(){
       boolean notified = false;
       while( !notified ){
          if( notify_time - time > 1000 ){
              Thread.sleep(999);
          else if( notify_time - time <= 0 ){
              // START NOTIFICATION ACTIVITY
              notified = true;
          }
       }
    }
}

t.start();

我个人没有做过类似的事情,所以我不确定什么服务可以通知用户或启动活动,但它确实有完整的可用选项参加一项活动,所以是的。

哦,但我突然想到,由于这里的多线程方面,您需要为此使用处理程序。

What if you start a service that spawns a thread like this:

thread t = new thread(new Runnable(){
    public void Run(){
       boolean notified = false;
       while( !notified ){
          if( notify_time - time > 1000 ){
              Thread.sleep(999);
          else if( notify_time - time <= 0 ){
              // START NOTIFICATION ACTIVITY
              notified = true;
          }
       }
    }
}

t.start();

I have not done anything like this personally, so I am not sure what service can do to notify the user or start an activity, but it does have the full panoply of options available to an activity, so yeah.

Oh but it just occured to me you'll need to use a handler for that because of the multithreaded aspect here.

挽手叙旧 2024-12-07 16:12:28

由于我总是有有限数量的通知,并且我可以提前计算经过的时间,因此 AlarmManagerBroadcastReceiver 的组合似乎工作得很好。以下是我的实现方法:

我首先创建了一个 BroadcastReceiver

public class NotificationReceiver extends BroadcastReceiver {

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

        //Get handle to system notification manager
        NotificationManager mNM = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

        //Get message from intent
        Bundle bundle = intent.getExtras();
        CharSequence text = bundle.getString("notification_message");

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.notification_icon, text, System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(context, context.getText(R.string.app_name),text, contentIntent);

        // Set Flags
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        // Send the notification.
        mNM.notify(R.string.notification, notification);

    }

}

然后创建了一个类,该类使用 AlarmManager 来创建/取消向 BroadcastReceiver 发送消息的警报

public class NotificationSender {

    private AlarmManager mAlarmManager;
    private Context mContext;
    private Intent mIntent;

    public NotificationSender(Context context){

        this.mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        this.mIntent = new Intent(context, NotificationReceiver.class);
        this.mContext = context;
    }

    public void setAlarm(Long etaMillis, int accumulator){

        //Create intent to send to Receiver
        this.mIntent.putExtra("notification_message","Message");

        //Use accumulator as requestCode so we can cancel later
        PendingIntent sender = PendingIntent.getBroadcast(this.mContext, accumulator, this.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        //Set Alarm
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, etaMillis, sender);

    }

    public void cancelAlarms(){

        //requestCode (accumulator) will always be a multiple of 10 and less than 100
        for (int x = 10; x <= 100; x += 10){
            PendingIntent operation = PendingIntent.getBroadcast(this.mContext, x, this.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            mAlarmManager.cancel(operation);
        }

    }

    public void createAlarms(PreferenceHelper prefs){

        //Calculate time notifications are due and set an alarm for each one
        //PreferenceHelper is a class to help pull values from shared preferences
        Date currentTime = new Date();

        for (int i = prefs.getNotificationInterval(); i <= 100; i += prefs.getNotificationInterval()) {

            if (i > prefs.getAccumulator()) {

                this.setAlarm(SystemClock.elapsedRealtime() + calculateETA(i, prefs).getTime() - currentTime.getTime(), i);

            }

        }

    }

    public void refreshAlarms(PreferenceHelper prefs){

        this.cancelAlarms();
        if (prefs.isNotificationsEnabled()) this.createAlarms(prefs);

    }

}

重要的部分是使用累加器作为 requestCode,以便我们稍后可以取消所有警报。

最后,我通过在 onCreate() 中调用 refreshAlarms() 以及每当用户修改与计划相关的首选项时在活动中使用 NotificationSender 类通知。重新启动手机将清除所有警报,因此必须重新启动应用程序才能开始通知。如果系统碰巧杀死了该进程,警报仍然会在适当的时间触发。

Since I will always have a finite number of notifications and I can calculate the elapsed time in advance, it seems the combination of AlarmManager and a BroadcastReceiver work pretty well. Here is how I implemented this:

I first created a BroadcastReceiver

public class NotificationReceiver extends BroadcastReceiver {

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

        //Get handle to system notification manager
        NotificationManager mNM = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

        //Get message from intent
        Bundle bundle = intent.getExtras();
        CharSequence text = bundle.getString("notification_message");

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.notification_icon, text, System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(context, context.getText(R.string.app_name),text, contentIntent);

        // Set Flags
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        // Send the notification.
        mNM.notify(R.string.notification, notification);

    }

}

I then created a class that used a AlarmManager to create/cancel alarms that send a message to the BroadcastReceiver

public class NotificationSender {

    private AlarmManager mAlarmManager;
    private Context mContext;
    private Intent mIntent;

    public NotificationSender(Context context){

        this.mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        this.mIntent = new Intent(context, NotificationReceiver.class);
        this.mContext = context;
    }

    public void setAlarm(Long etaMillis, int accumulator){

        //Create intent to send to Receiver
        this.mIntent.putExtra("notification_message","Message");

        //Use accumulator as requestCode so we can cancel later
        PendingIntent sender = PendingIntent.getBroadcast(this.mContext, accumulator, this.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        //Set Alarm
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, etaMillis, sender);

    }

    public void cancelAlarms(){

        //requestCode (accumulator) will always be a multiple of 10 and less than 100
        for (int x = 10; x <= 100; x += 10){
            PendingIntent operation = PendingIntent.getBroadcast(this.mContext, x, this.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            mAlarmManager.cancel(operation);
        }

    }

    public void createAlarms(PreferenceHelper prefs){

        //Calculate time notifications are due and set an alarm for each one
        //PreferenceHelper is a class to help pull values from shared preferences
        Date currentTime = new Date();

        for (int i = prefs.getNotificationInterval(); i <= 100; i += prefs.getNotificationInterval()) {

            if (i > prefs.getAccumulator()) {

                this.setAlarm(SystemClock.elapsedRealtime() + calculateETA(i, prefs).getTime() - currentTime.getTime(), i);

            }

        }

    }

    public void refreshAlarms(PreferenceHelper prefs){

        this.cancelAlarms();
        if (prefs.isNotificationsEnabled()) this.createAlarms(prefs);

    }

}

The important part is to use the accumulator as the requestCode so we can cancel all of our alarms later.

Finally I used the NotificationSender class in my activity by calling refreshAlarms() in onCreate() and whenever the user modifies preferences that are relevant to scheduling notifications. Rebooting the phone will clear all alarms so the app must be restarted before notifications will begin. If the system happens to kills the process, the alarms will still trigger at the appropriate time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文