为什么在此警报设置中两次调用onReceive()?

时间:2018-07-31 12:56:26

标签: java android broadcastreceiver alarmmanager bootcompleted

我正在构建一个Android计步器应用程序,该应用程序使用AlarmManager每隔30分钟将数据发送到SQLite数据库;如果应该进行转移时手机处于关机状态,则在重新开机时会立即进行转移。

(30分钟用于测试-实际间隔为1周)。

有人告诉我,除非我在清单中使用“ intent.action.BOOT_COMPLETED”,否则警报将不会持续,因此我将其作为Alarm.java类的过滤器。

我设置警报的代码(在MainActivity.java中)如下:

public void insertData(View view) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    long time= System.currentTimeMillis();
    Date d = new Date(time);
    editor.putLong("alarmtime", time); //the next ring time for the alarm is put in SharedPreferences
    editor.apply();

    Intent intent = new Intent(this, Alarm.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            this,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_DAY, pendingIntent);
    Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_LONG).show();
}

Alarm.java类(扩展了BroadcastReceiver)中的代码如下:

Context context; //plus other declared variables

@Override
public void onReceive(Context context, Intent intent) {
    this.context = context;
    preferences = context.getSharedPreferences("MyPreferences", context.MODE_PRIVATE);
    editor = preferences.edit();
    long startedtime = preferences.getLong("alarmtime", 0); //get the next ring time
    Date nextRingTime = new Date(startedtime);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    String action = intent.getAction();
    //sometimes the onReceive() is called by the phone turning on
    if (action != null && action.equals(Intent.ACTION_BOOT_COMPLETED)) {

        //if phone turned on again before the alarm, just re-create the alarm for the same time, don't transfer data
        Date currenttime = new Date(System.currentTimeMillis());
        if ((currenttime.compareTo(nextRingTime) < 0)) {  
            Intent newintent = new Intent(context, Alarm.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    context,
                    0,
                    newintent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            alarmManager.setRepeating(AlarmManager.RTC, startedtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
            return;
        }

        else if ((currenttime.compareTo(nextRingTime) > 0)) {
        //if the phone was off when the alarm was supposed to make the transfer, set the alarm to the next intended ring time and insert data to db immediately

            Calendar d = Calendar.getInstance();
            d.setTime(nextRingTime);
            d.add(Calendar.MINUTE, 30);
            long newtime = d.getTimeInMillis();
            Intent newintent = new Intent(context, Alarm.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    context,
                    0,
                    newintent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            alarmManager.setRepeating(AlarmManager.RTC, newtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
        }
    }
    myDb = new DatabaseHelper(context);
    // code for inserting data into database

    //finally, update next intended ring time in SharedPreferences now that this particular transfer is done:
    Calendar c = Calendar.getInstance();
    c.setTime(nextRingTime);
    c.add(Calendar.MINUTE, 30);
    Log.v("insertdone, alarrm now", c.getTime().toString());
    long nexttime = c.getTimeInMillis();
    editor.putLong("alarmtime", nextime);
    editor.apply();
}

不幸的是,如果在预定的警报时手机处于关机状态,那么当我随后将其打开时,它将调用onReceive()TWICE,这意味着它将两次插入数据。

如何停止?

一个解决方案可能是使用RTC_WAKEUP,但我真的不希望这样做,除非绝对不得已。

我有一个单独的bootBroadcastReceiver类,该类使用“ intent.action.BOOT_COMPLETED”重新启动计步器服务,并且想知道启动时启动了2种不同的东西是否会引起问题...

0 个答案:

没有答案