警报管理器不适用于Android中的多个警报

Posted

技术标签:

【中文标题】警报管理器不适用于Android中的多个警报【英文标题】:Alarm manager not working for multiple Alarm in Android 【发布时间】:2018-07-14 21:56:26 【问题描述】:

我想使用基于某些数据库时间值的警报。目前我的闹钟正在为一个闹钟工作,例如:我在上午 8:30、上午 10:20 和下午 12:20 设置了 3 个闹钟 我的闹钟只适用于一个值。这是我正在创建闹钟的提醒类

public class OwnGoalReminder extends EventReminder 
    GoalOwn goalOwn;
    int interValTime;
    int goalId;
    int hour;
    int minute;
    int requestCode;
    String type;

    public void setInterValTime(int interValTime) 
        this.interValTime = interValTime;
    

    public int getHour() 
        return hour;
    

    public void setHour(int hour) 
        this.hour = hour;
    
    public void setRequestCode(int requestCode) 
        this.requestCode = requestCode;
    
    public void setType(String type) 
        this.type = type;
    

    public int getMinute() 
        return minute;
    
    @Override
    protected int getGoalId()return this.goalId;

    public void setMinute(int minute) 
        this.minute = minute;
    

    public OwnGoalReminder(Context context , int goalId, int interValTime)
        super(context);
        this.interValTime = interValTime;
        this.goalId = goalId;
    

    @Override
    protected String getType() 
        return this.type;
    


    @Override
    protected String getMessage() 
        return "Reminder!!! You should check your goals!";
    

    @Override
    protected int getRequestCode() 
        return requestCode;
    

    @Override
    protected EventTime getEventTime() 
        int h = hour;
        int m = minute;
        return new EventTime(hour,minute,interValTime);
    

    @Override
    protected Class getBroadcastReceiver() 
        return MyBroadcastReceiver.class;
    

这是 OwnGOalReminder 的基类

public abstract class EventReminder
    protected Context context;
    protected Alarm alarm;
    PushNotificationsManager notificationsManager;


    public void remind() 
        Bundle bundle = new Bundle();
        bundle.putString("type", getType());
        bundle.putString("msg", getMessage());
        notificationsManager.sendNotification(bundle);
    

    protected abstract String getType();

    protected abstract String getMessage();

    protected abstract int getRequestCode();
    protected abstract int getGoalId();

    protected abstract EventTime getEventTime();

    protected abstract Class getBroadcastReceiver();

    protected EventReminder(Context context)
        this.context = context;
        alarm = new Alarm(context, getBroadcastReceiver());
        notificationsManager = new PushNotificationsManager(context);
    

    public void startReminder()
        alarm.startAlert(getRequestCode(), getGoalId(), getEventTime().hour, getEventTime().minute, getEventTime().intervalInMinute);
        //alarm.setAlarm(context, getEventTime().hour, getEventTime().minute);
    


    protected class EventTime
        int hour, minute, intervalInMinute;
        public EventTime(int hour, int minute, int intervalInMinute)
            this.hour = hour;
            this.minute = minute;
            this.intervalInMinute = intervalInMinute;
        
    

这是警报类,我正在创建警报管理器

public class Alarm

    private final Context context;
    private Class broadcastReceiver;

    public Alarm(Context context, Class broadcastReceiver)
        this.context = context;
        this.broadcastReceiver = broadcastReceiver;
    

    public void startAlert(int requestCode, int gid, int hour, int minute, int intervalMinute) 
        Log.d(this.getClass().getName(), "starting alert");
        int i = 10;
        Long timeToMilliSeconds = timeToMilliSeconds(hour, minute);
        Intent intent = new Intent(context, MyBroadcastReceiver.class);
        intent.putExtra("reqcode", requestCode);
        intent.putExtra("time", timeToMilliSeconds);
        intent.putExtra("gid" , gid);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, timeToMilliSeconds+
                + (i * 1000), 1000*60*intervalMinute, pendingIntent);
        //Toast.makeText(context, "Alarm set in " + i + " seconds",Toast.LENGTH_LONG).show();
    

    @NonNull
    public static long timeToMilliSeconds(int hour, int minute) 
        Date dat  = new Date();//initializes to now
        Calendar cal_alarm = Calendar.getInstance();
        Calendar cal_now = Calendar.getInstance();
        cal_now.setTime(dat);
        cal_alarm.setTime(dat);
        cal_alarm.set(Calendar.HOUR_OF_DAY,hour);//set the alarm time
        cal_alarm.set(Calendar.MINUTE, minute);
        cal_alarm.set(Calendar.SECOND,0);

        if(cal_alarm.getTimeInMillis() < System.currentTimeMillis())
            cal_alarm.add(Calendar.DAY_OF_YEAR,1);
        
        return cal_alarm.getTimeInMillis();
    


这是我根据数据库值创建多个警报对象的方法

public static void registerAlarm(Context context)
        if(!UserPreferences.isAlarmRegistered(context)) 
            GoalReminder goalReminder = new GoalReminder(context);


            AppraisalReminder appraisalReminder = new AppraisalReminder(context);
            goalReminder.startReminder();
            appraisalReminder.startReminder();
           // ownGoalReminder.startReminder();
            //UserPreferences.setIsAlarmRegistered(context,true);
            ArrayList<Goal> LIST_OF_OWN_GOALS = new ArrayList<>();

            LIST_OF_OWN_GOALS = (ArrayList<Goal>) Goal.getGoalFromOwnGoals();

            for (Goal g : LIST_OF_OWN_GOALS) 
                OwnGoalReminder ownGoalReminder = new OwnGoalReminder(context , g.getgId(),3 );
                int h = Integer.parseInt(g.getrTime())/60;
                int min = Integer.parseInt(g.getrTime())%60;
                ownGoalReminder.setHour(h);
                ownGoalReminder.setMinute(min);
                ownGoalReminder.setRequestCode(16);

                ownGoalReminder.setType("16");
                ownGoalReminder.startReminder();
                LIST_OF_OWN_REMINDERS.add(ownGoalReminder);

            



        
    

这是我的广播接收器类:

public class MyBroadcastReceiver extends BroadcastReceiver 
    private static final String[] goalMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.goals_messages);
    private static Queue<String> goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));


    private static final String[] appraisalsMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.appraisals_messages);
    private static Queue<String> appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));

    @Override
    public void onReceive(Context context, Intent intent) 
        Log.d(this.getClass().getName(), "notify");
        PushNotificationsManager notificationsManager = new PushNotificationsManager(context);
        PowerManager.WakeLock wl = acquireWakeLock(context);

        int requestCode = intent.getIntExtra("reqcode",1);
        int gId = intent.getIntExtra("gid",1);

        long time = intent.getLongExtra("time",0);
        String message = "";

        // it will create the instance of Random class
          Random randomGenerator = new Random();

        // it will generate a random number based on  goal message arrayList length
        int indexForGoalMessage = randomGenerator.nextInt(goalMessagesArray.length);

        // it will generate a random number based on  appraisalsMessagesArray length
        int indexForAppraisalsMessage = randomGenerator.nextInt(goalMessagesArray.length);
        String gid = "";


        if(isNotifyTimePassed(time))
            //return;
        


        if(requestCode == 123)

//           if(goalMessagesQueue.isEmpty())
//                goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));
//            
//            message = goalMessagesQueue.poll();

            message = goalMessagesArray[indexForGoalMessage];



        else if(requestCode == 124)

//            if(appraisalsMessagesQueue.isEmpty())
//                appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));
//            
//            message = appraisalsMessagesQueue.poll();

            message = appraisalsMessagesArray[indexForAppraisalsMessage];


        

            Bundle bundle = new Bundle();
            bundle.putString("type", Integer.toString(requestCode));
            bundle.putString("msg", message);
            bundle.putString("gid" , String.valueOf(gId));
            notificationsManager.sendNotification(bundle);

             wl.release();
    

    @NonNull
    private PowerManager.WakeLock acquireWakeLock(Context context) 
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wl.acquire();
        return wl;
    

    private boolean isNotifyTimePassed(long time) 
        return (System.currentTimeMillis()-time) > 1000L*60L*5L;
    


【问题讨论】:

AtomicInteger 也可用于获取唯一 ID,如果您在同时有多个通知时遇到任何通知排序问题。 【参考方案1】:

最好将你的事件id(唯一id)设置为PendingIntent.getBroadcast()方法的请求码。所以这里的好处是当你更新/编辑事件时,警报不会重复。

【讨论】:

【参考方案2】:

[我通过搜索谷歌找到了这个解决方案]

我通过传递取决于当前时间的唯一 id 解决了这个问题:-

final int intent_id= (int) System.currentTimeMillis(); 

  PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context, intent_id , intent,   PendingIntent.FLAG_UPDATE_CURRENT);

【讨论】:

以上是关于警报管理器不适用于Android中的多个警报的主要内容,如果未能解决你的问题,请参考以下文章

在Android警报管理器中设置时间-立即触发警报[重复]

Android在另一个完成时设置警报管理器

Xamarin 警报管理器 Android

计划的警报管理器无法正常工作 Android

Android 警报管理器 setExactAndAllowWhileIdle() 在打盹模式下的 Android 7.0 Nougat 中不起作用

用于定期后台任务的警报管理器的替代方案