如何使用Alarms以外的其他方式安排任务,它应该很容易测试,甚至在设备重启后也应该运行?

时间:2017-08-22 11:00:09

标签: android broadcastreceiver sharedpreferences

我必须运行一个接收器,该接收器仅在一周中的特定日期的特定持续时间内接收action USER_PRESENT。此处,持续时间和工作日由用户选择。

我尝试过使用PreferencesAlarmManager来实现此目标,我非常希望使用Alarms以外的Preferences来实现此目的。在用户选择的持续时间和用户选择的工作日之后运行的每周警报测试警报变得非常困难。

除了使用AlarmsPreferences之外,还有其他方法可以完成这项工作吗?代码示例真有用!!

有关详细信息,请参阅Alarms使用Preferences的方法:

现在我首先计算开始时间,让用户通过DialogFragment选择小时和分钟,其中TimePickerDialog被夸大,以便用户可以选择开始时间,我得到{{1}在hrs回调中找到min,然后找出接收器启动的开始时间。

代码片段用于从onTimeSet()hrs计算以毫秒为单位的开始时间:

min

然后我以 Calendar calSet = Calendar.getInstance(); //setting alarm from current day so that it starts from today onwards int day = calSet.get(Calendar.DAY_OF_WEEK); calSet.set(Calendar.DAY_OF_WEEK, day); calSet.set(Calendar.HOUR_OF_DAY, hrs); calSet.set(Calendar.MINUTE, min); calSet.set(Calendar.SECOND, 0); calSet.set(Calendar.MILLISECOND, 0); Long milliseconds = calSet.getTimeInMillis(); //check if the time is already passed Long daily = 24L * 60L * 60L * 1000L; if (milliseconds < System.currentTimeMillis()) { //if already passed then push it for next day by adding just 24 hrs milliseconds = milliseconds + daily; } preference说:SharedPreferences.Editor.putLong("PeriodicLockStartTimeInMillis", milliseconds);

以毫秒为单位保存这个计算时间

现在,我使用checkBoxes存储用户选择的日期,并为每一天的复选框设置preferences

SharedPreferences.Editor.putBoolean("DAYNAME", true);

还存储用户希望接收者工作的持续时间:

SharedPreferences.Editor.putLong("LockDurationInMillis", minutesinmillis);

然后使用AlarmManager设置一个警报,该警报会将BroadcastReceiver的名称PeriodicLockService设置为PendingIntent作为Intent reminderIntent = new Intent(getActivity(), PeriodicLockService.class); reminderIntent.setAction("ACTION_REPEATING_ALARM_RECEIVER"); pendingIntent = PendingIntent.getBroadcast(getActivity(), PeriodicLockService.REPEATING_ALARM_UNIQUE_ID, reminderIntent, PendingIntent.FLAG_UPDATE_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { alarmManager.setExact(AlarmManager.RTC_WAKEUP, milliseconds, pendingIntent); } else { alarmManager.set(AlarmManager.RTC_WAKEUP, milliseconds, pendingIntent); } ,然后点击其接收方。

此处设置闹钟的代码:

PeriodicLockService

现在onReceive点击preference时,我首先使用//Fetching today's day from Calendar to compare if user has set lock for today Calendar calendar = Calendar.getInstance(); int day = calendar.get(Calendar.DAY_OF_WEEK); switch (day) { case Calendar.SUNDAY: if (Preferences.getBooleanPreference(context, SUN_DAY)) { startLockNow(context); } break; case Calendar.MONDAY: if (Preferences.getBooleanPreference(context, MON_DAY)) { startLockNow(context); } break; case Calendar.TUESDAY: if (Preferences.getBooleanPreference(context, TUES_DAY)) { startLockNow(context); } break; case Calendar.WEDNESDAY: if (Preferences.getBooleanPreference(context, WED_DAY)) { startLockNow(context); } break; case Calendar.THURSDAY: if (Preferences.getBooleanPreference(context, THURS_DAY)) { startLockNow(context); } break; case Calendar.FRIDAY: if (Preferences.getBooleanPreference(context, FRI_DAY)) { startLockNow(context); } break; case Calendar.SATURDAY: if (Preferences.getBooleanPreference(context, SAT_DAY)) { startLockNow(context); } break; } private void startLockNow(Context context) { Long lockStartTimeInMillis = Preferences.getLongPreference(context, "PeriodicLockStartTimeInMillis"); //Update Unlock Time Long LockDurationInMillis = Preferences.getLongPreference(context, "LockDurationInMillis"); //End time to stop the Receiver for action USER_PRESENT Long newEndTime = lockStartTimeInMillis + LockDurationInMillis; //Set Unlocked notification broadcast which also disables the receiver for action `USER_PRESENT` Intent intent = new Intent(context, FinalUnlockedBroadcast.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { alarmManager.setExact(AlarmManager.RTC_WAKEUP, newEndTime + 1000, pendingIntent); } else { alarmManager.set(AlarmManager.RTC_WAKEUP, newEndTime + 1000, pendingIntent); } //update the time for next lock by adding a day milliseconds = Preferences.getLongPreference(context, "PeriodicLockStartTimeInMillis") + 24L * 60L * 60L * 1000L; Intent reminderIntent = new Intent(context, PeriodicLockService.class); reminderIntent.setAction("ACTION_REPEATING_ALARM_RECEIVER"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REPEATING_ALARM_UNIQUE_ID, reminderIntent, PendingIntent.FLAG_UPDATE_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { alarmManager.setExact(AlarmManager.RTC_WAKEUP, milliseconds , pendingIntent); } else { alarmManager.set(AlarmManager.RTC_WAKEUP, milliseconds , pendingIntent); } } 检查用户是否设置了今天要运行的内容:

Alarms

但问题是,这似乎并不总是有用,而且很难从运行我的应用的用户设备获取日志。

除了使用PreferencesHuman human1 = new Human(); human1.name = "John";

之外,还有其他方法可以完成这项工作

3 个答案:

答案 0 :(得分:1)

Android-Job Android-Job repo

  • Android-Job抽象出您要用于执行后台工作的实现。
  • 根据要求,此库决定用于运行作业的API。
  • 它提供了JobScheduler,GCMNetworkManager和AlarmManager的所有功能的超集。
  • Android Nougat的所有功能都向后兼容。
  • 较少的样板。

实施Android-Job非常简单。

API包括以下类/接口。

  1. 作业:您的作业需要扩展此类并覆盖onRunJob方法。繁重的工作在这里完成。您必须从此方法返回结果,以便系统知道是否稍后尝试运行您的作业。
  2. JobRequest:您可以使用其构建器构造函数创建JobRequest并传递Job标记来计划作业。
  3. JobCreator:JobCreator就像工厂一样,根据工作标签提供工作。您的具体JobCreator类必须实现JobCreator接口并覆盖create方法。
  4. JobManager:JobManager类用作入口点。在使用此类之前,必须将其初始化为单例。 JobManager采用上下文。创建实例后,您必须将JobCreator添加到JobManager。
  5. 如果你有兴趣阅读更多plz,请参阅这篇精彩的文章Easy Job Scheduling with Android-Job

    感谢 Rajesh Pattanaik 撰写本文的人

答案 1 :(得分:0)

我建议你使用Firebase Job Dispatcher。它是一个用于在Android应用中安排后台作业的库。它提供了与JobScheduler兼容的API,适用于安装了Google Play服务的所有最新版本的Android(API级别9+)。

有关如何在您的应用中使用它的说明,请点击here

答案 2 :(得分:0)

您可以使用Job Scheduler

public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        Toast.makeText(this, "testing", Toast.LENGTH_LONG).show();
        Log.i("sid", "Job scheduler called");
        jobFinished(params, true);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }
}

在您的活动中调用以下方法

private void constructJob(){
        JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, new ComponentName(this, MyJobService.class));

        builder.setMinimumLatency(60000)
                .setBackoffCriteria(10000,JobInfo.BACKOFF_POLICY_LINEAR)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                .setPersisted(true);

        mJobScheduler.schedule(builder.build());
    }

确保调用builder.setPersisted(true)以便在重新启动后运行该服务。另外要看一下这个代码在Android N(API 24)或更高版本的API上可以正常工作,但是,对于API 21 - 23,它调用builder.setPeriodic(60000)而不是builder.setMinimumLatency(60000)

<强>更新 要在API 15及更高版本上运行Job Scheduler,请使用JobSchedulerCompat。

在您的gradle文件中添加以下依赖项 -

compile 'me.tatarka.support:jobscheduler:0.1.1'