场景:
生产线工人每隔一定时间进行检查。在我的应用程序上,用户将此时间间隔输入到文本框中。有日期和时间选择器,以便用户可以选择何时开始该过程。我正尝试在下一次检查到期5分钟前发出警报。

例如:
过程从2.30开始。用户输入的时间间隔为20分钟。因此,下一次检查应在2.50进行。警报应在2.45响起。然后将重复此过程,因此下一次检查应为3.10,并且闹钟应在3.05响起。

这是我的代码:

 MainActivity.calculate();
        commencedTime = new Date();
        mTime = Calendar.getInstance();
        mTime.setTime(alarmTime);
        timeCommenced = trimSecsAndMillisecs(mTime).getTimeInMillis();

        currentTime = new Date();
        currentTime.getTime();

        alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
        //set alert
        alertDialogBuilder
                .setTitle("IP Check frequency: " + time.getText() + " minutes")
                .setMessage("Processing commenced at \n" + startTime.getText())
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        if (currentTime.after(alarmTime)) {
                            Toast.makeText(MainActivity.this, "Missed first alert", Toast.LENGTH_LONG).show();
                        }

                        i = Integer.parseInt(time.getText().toString());
                        long scTime2 = ((i * 60 * 1000)); //TIME ENTERED IN MILLISECONDS

                        intent1 = new Intent(MainActivity.this, MyBroadcastReceiver.class);
                        intent1.putExtra("timeEntered", scTime2);
                        intent1.putExtra("timeCommenced", timeCommenced);
                        sendBroadcast(intent1);

                        pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);

                        manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                        manager.setExact(AlarmManager.RTC_WAKEUP, timeCommenced, pendingIntent);

                        Toast.makeText(MainActivity.this, "Alert Set", Toast.LENGTH_SHORT).show();
                        stopped.setVisibility(View.VISIBLE);
                        commenced1.setVisibility(View.GONE);

                        //Change editText to TextView
                        time.setVisibility(View.GONE);
                        timeText.setVisibility(View.VISIBLE);
                        timeText.setText(time.getText().toString());
                        processingText.setText(R.string.processing_commenced);

                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });
        alertDialog = alertDialogBuilder.create();
        alertDialog.show();

    }
}


广播接收器:

@Override
public void onReceive(Context context, Intent intent) {
    // Vibrate the mobile phone
    vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    long[] pattern = {0, 10000, 3, 10000};
    vibrator.vibrate(pattern, -1); // vibration for 20 seconds

    //create as instance of the media player
    mediaPlayer = MediaPlayer.create(context, R.raw.alarm_sound);
    mediaPlayer.start();

   createNotification(context, "AlmaIPC", "IP check is due", "Alert");

    AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
    Intent intent2 = new Intent(context, MainActivity.class);
    PendingIntent pi2 = PendingIntent.getActivity(context, 0, intent2, 0);

    Long timeEntered =intent.getLongExtra("timeEntered", 0);


    AlarmManager.AlarmClockInfo ac=
            new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + timeEntered,
                    pi2);

    manager.setAlarmClock(ac, pi);


}


我在setExact()参数中包含的timecommenced变量正在正确调试应在何时触发警报。

然后,在我的广播接收器内部,我尝试传递此值并添加用户输入的时间间隔,以使警报时间保持完整。例如2.45,然后是3.05。

由于某些原因,为什么我单击“开始处理”而不是timecommenced状态时发出警报声,所以它会立即触发。然后,警报定时完全关闭,并且它具有自己的作用。

谁能看到我做错的事情或给我一些建议?

谢谢!

最佳答案

顾名思义,“ setExact”在Android 6+ [API 21+]上不起作用。当设备不充电且屏幕关闭时,它将大致受到打restrictions限制。 [注意:从Android 7开始,此问题更加严重,因为它具有更激进的Doze形式]

为了发出可靠的面向用户的警报,应使用AlarmManager的“ setAlarmClock”方法。

AlarmManager am =
  (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent1 = new Intent(context, myReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
Intent intent2 = new Intent(context, myActivity.class);
PendingIntent pi2 = PendingIntent.getActivity(context, 0, i2, 0);

AlarmManager.AlarmClockInfo ac=
  new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + DELAY,
    pi2);

am.setAlarmClock(ac, pi);


从文档:

setAlarmClock
在API级别21中添加

void setAlarmClock (AlarmManager.AlarmClockInfo info,
            PendingIntent operation)


安排代表闹钟的闹钟,闹钟将在关闭时通知用户。期望当该警报触发时,应用程序将进一步唤醒设备以告知用户有关警报的信息-打开屏幕,播放声音,振动等。因此,系统通常也会使用该信息如果需要,可在此处提供此信息以告知用户即将发生的警报。

由于这种警报的性质,类似于setExactAndAllowWhileIdle(int,long,PendingIntent),即使系统处于低功率空闲(也称为打ze)模式,也将允许触发这些警报

Alarm Manager Docs

要设置多个警报,请在PendingIntent中为每个警报赋予唯一的“ requestCode”:

 static PendingIntent   getBroadcast(Context context, int requestCode, Intent intent, int flags)

10-08 17:26