【问题标题】:Prevent repeating alarm from occurring on weekend防止周末重复报警
【发布时间】:2015-10-15 00:22:26
【问题描述】:

我有一个使用 AlarmManager 类的闹钟应用程序,它允许用户设置一次性闹钟或重复闹钟。我想扩展功能,以便用户可以排除警报响起,例如在周末。

我已将用于在周末阻止警报的代码放入 AlarmReceiver.java。

  1. 我不确定 AlarmReceiver.java 是否是放置周末阻止警报的代码的正确位置。
  2. 我不确定用于在周末阻止警报的代码是否正确。基本上,如果今天是星期六或星期日,我会告诉 AlarmReceiver 什么都不做。否则,请关闭警报。

设置闹钟的AlarmActivity.java代码:

  //Set a one time alarm
            if (repeatInterval == 0) {
                    alarmManager.set(AlarmManager.RTC, alarmTime.getTimeInMillis(), pendingIntent);
                    AlarmReceiver alarmReceiver = new AlarmReceiver(this); //http://stackoverflow.com/questions/16678763/the-method-getapplicationcontext-is-undefined

                    Toast.makeText(AlarmActivity.this, "Your one time reminder is now set for " + hourSet + ":" + minuteSetString + amPmlabel, Toast
                            .LENGTH_LONG)
                            .show();
            }

            //Set a repeating alarm
            else {
                alarmManager.setRepeating(AlarmManager.RTC, alarmTime.getTimeInMillis(), repeatIntervalMilliseconds, pendingIntent);
                AlarmReceiver alarmReceiver = new AlarmReceiver(this); //http://stackoverflow.com/questions/16678763/the-method-getapplicationcontext-is-undefined

                    Toast.makeText(AlarmActivity.this, "Your reminder is now set for " + hourSet + ":" + minuteSetString + amPmlabel + " and will " +
                            "repeat " +
                            "every " +
                            repeatInterval + " minutes.", Toast.LENGTH_LONG).show();
        }

AlarmService.Java:

package com.joshbgold.move.backend;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;

import com.joshbgold.move.R;
import com.joshbgold.move.main.AlarmActivity;

public class AlarmService extends IntentService {
    private NotificationManager alarmNotificationManager;

    public AlarmService() {
        super("AlarmService");
    }

    @Override
    public void onHandleIntent(Intent intent) {

            sendNotification("Move reminder");

    }

    private void sendNotification(String msg) {
        alarmNotificationManager = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, AlarmActivity.class), 0);

        NotificationCompat.Builder alarmNotificationBuilder = new NotificationCompat.Builder(
                this).setContentTitle("Reminder").setSmallIcon(R.mipmap.ic_launcher)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText(msg);


        alarmNotificationBuilder.setContentIntent(contentIntent);
        alarmNotificationManager.notify(1, alarmNotificationBuilder.build());
    }

}

AlarmReceiver.Java:

package com.joshbgold.move.backend;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.WakefulBroadcastReceiver;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class AlarmReceiver extends WakefulBroadcastReceiver {

    Context myContext;
    public AlarmReceiver(Context context){
        myContext = context;
    }

    public AlarmReceiver(){

    }

    //get the current day
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE");
    Date date = new Date();
    String dayOfTheWeek = simpleDateFormat.format(date);

    Calendar calendar = Calendar.getInstance();
    int currentHour = calendar.HOUR_OF_DAY;

    boolean noWeekends = true;
    boolean workHoursOnly = true;

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


        try {  //this value could be null if user has not set it...
            noWeekends = loadPrefs("noWeekends", noWeekends);
            workHoursOnly = loadPrefs("workHoursOnly", workHoursOnly);
        } catch (Exception e) {
            e.printStackTrace();
        }


        if(dayOfTheWeek == "Saturday" || dayOfTheWeek == "Sunday"  && noWeekends == true) {
            //Alarm is not wanted on the weekend
            try {
                wait(1);  //waits for one-thousandth of a millisecond
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        else if ((currentHour < 9 || currentHour > 17)  && workHoursOnly == true){
            //Alarm outside of work hours
            try {
                wait(1);  //waits for one-thousandth of a millisecond
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        else {

            Intent myIntent = new Intent();
            myIntent.setClassName("com.joshbgold.move", "com.joshbgold.move.main.ReminderActivity");
            myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(myIntent);
        }
    }

    //get prefs
    private boolean loadPrefs(String key,boolean value) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(myContext);
        boolean data = sharedPreferences.getBoolean(key, value);
        return data;
    }
}

AlarmReceiver.java(修正代码)

package com.joshbgold.move.backend;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.WakefulBroadcastReceiver;
import java.util.Calendar;

public class AlarmReceiver extends WakefulBroadcastReceiver {

    Context myContext;
    public AlarmReceiver(Context context){
        myContext = context;
    }

    public AlarmReceiver() {

    }

    private boolean workHoursOnly = false;
    private boolean noWeekends = false;

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

        Calendar calendar = Calendar.getInstance();
        int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
        int today = calendar.get(Calendar.DAY_OF_WEEK);
        boolean isWeekend = (today == Calendar.SUNDAY) || (today == Calendar.SATURDAY);
        boolean isOutsideWorkHours = (currentHour < 9) || (currentHour > 16);

        //checkPrefs checks whether a preferences key exists
        if (checkPrefs("workHoursOnlyKey")){
            workHoursOnly = loadPrefs("workHoursOnlyKey", workHoursOnly);
        }

        if(checkPrefs("noWeekendsKey")){
            noWeekends = loadPrefs("noWeekendsKey", noWeekends);
        }

        /* try {  //this value could be null if user has not set it...
            workHoursOnly = loadPrefs("workHoursOnly", workHoursOnly);
        } catch (Exception e) {
            e.printStackTrace();
        }
       */

        /*try {  //this value could be null if user has not set it...
        noWeekends = loadPrefs("noWeekends", noWeekends);
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        if(isWeekend && noWeekends) {
            //Alarm is not wanted on the weekend
            try {
                Thread.sleep(1);  //waits for millisecond
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        else if (isOutsideWorkHours  && workHoursOnly){
            //Alarm not wanted outside of work hours
            try {
                Thread.sleep(1);  //waits for millisecond
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        else {
            //Alarm is wanted, and should go off
            Intent myIntent = new Intent();
            myIntent.setClassName("com.joshbgold.move", "com.joshbgold.move.main.ReminderActivity");
            myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(myIntent);
        }
    }

    //check if a prefs key exists
    private boolean checkPrefs(String key){
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(myContext);
        boolean exists = sharedPreferences.contains(key);
        return exists;
    }

    //get prefs
    private boolean loadPrefs(String key,boolean value) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(myContext);
        boolean data = sharedPreferences.getBoolean(key, value);
        return data;
    }
}

【问题讨论】:

  • 总挑剔。 wait(1) 是一毫秒,而不是千分之一毫秒。
  • 出了什么问题?你有没有在周末测试它并发出警报?您是否在周末对其进行了调试并检查了“dayOfTheWeek”的值以查看其中的内容? repeatIntervalMilliseconds 的值是多少?

标签: android alarmmanager


【解决方案1】:

你的方法很好。无论如何,我建议您避免使用硬编码字符串进行周末检查。您已经在代码中定义了一个 Calendar 对象,只需使用它:

Calendar calendar = Calendar.getInstance();
//..
int today  = calendar.get(Calendar.DAY_OF_WEEK);
boolean isWeekend = (today == Calendar.SUNDAY) || (today == Calendar.SATURDAY);

并相应地更新您的代码:

  //...
  int today  = calendar.get(Calendar.DAY_OF_WEEK);
  boolean isWeekend = (today == Calendar.SUNDAY) || (today == Calendar.SATURDAY);
  if(isWeekend && noWeekends == true) {
        //Alarm is not wanted on the weekend
        try {
            Thread.sleep(1);  
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  //...

【讨论】:

  • 我成功地触发了一个警报请求,然后现在使用您在上面发布的代码过滤掉 AlarmReceiver 中的请求。由于错误“IllegalMonitorStateException:对象未在 wait() 之前被线程锁定”,我将 wait() 方法更改为 Thread.sleep。因为现在不是周末,所以我设置了一个虚拟 if 条件进行测试。以前当任一 if 条件为真时,应用程序崩溃,但现在可以了。
  • 从使用 try catch 块检查 sharedPreferences 是否存在,改为使用内置 sharedPreferences 方法 contains() 检查 sharedPreferences 键是否存在。
  • 我在 sharedPreferences 中发现的另一个问题是,由于 AlarmReceiver 扩展了 wakefulBroadcastReceiver,它不会自动接收应用程序上下文。我必须将应用程序上下文从 mainactivity 传递到 onReceive 方法,从 onReceive 方法传递到 sharedPrefences 方法
【解决方案2】:

除了 dnellis74 的回答之外,您还需要一些括号:

if(dayOfTheWeek == "Saturday" || dayOfTheWeek == "Sunday"  && noWeekends == true)

变成

if((dayOfTheWeek == "Saturday" || dayOfTheWeek == "Sunday")  && noWeekends == true)

我也觉得你不需要

 try {
      wait(1);  //waits for one-thousandth of a millisecond
     } catch (InterruptedException e) {
                e.printStackTrace();
     }

【讨论】:

    【解决方案3】:

    1.) 触发一个事件然后在订阅者(BroadcastReceiver)中过滤/处理它是非常好的。这就是它们的用途。

    2.)

    if((dayOfTheWeek == "Saturday" || dayOfTheWeek == "Sunday")  && noWeekends == true)
    

    注意括号修正。

    【讨论】:

      【解决方案4】:

      在这里完全吐槽,我不是 Android 开发人员。您的星期几变量:

      Date date = new Date();
      String dayOfTheWeek = simpleDateFormat.format(date);
      

      是类的成员变量。它只会在类被实例化时被设置。如果这只发生在某种启动周期中,dayOfTheWeek 将永远不会改变。因此,如果我是正确的,如果您将闹钟设置在星期三,则此代码将始终认为是星期三,即使在星期六也是如此。

      将这两行代码移到实际函数 onReceive() 中,我敢打赌,一周中的那一天将开始被接受。

      【讨论】:

        猜你喜欢
        • 2016-05-28
        • 2013-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-29
        • 1970-01-01
        • 2022-11-10
        相关资源
        最近更新 更多