Android中定时作业执行的当前最佳实践

Android中定时作业执行的当前最佳实践,android,time,alarmmanager,Android,Time,Alarmmanager,由于我一直在与Android Oreo后台限制作斗争,我问自己,使用AlarmManager是否是将作业执行时间安排到凌晨03:00的最佳方式。我看到一些人使用JobScheduler,但它似乎不太适合每天在给定时间执行任务 我试着在AlarmManager上安装一个BroadcastReceiver,然后将BroadcastReceiver插入理论上的自启动服务中,但由于应用程序在后台无法调用startService,这也不能正常工作,而且似乎有点错误 我错过什么了吗?目前的做法是什么? 显然

由于我一直在与Android Oreo后台限制作斗争,我问自己,使用AlarmManager是否是将作业执行时间安排到凌晨03:00的最佳方式。我看到一些人使用JobScheduler,但它似乎不太适合每天在给定时间执行任务

我试着在AlarmManager上安装一个BroadcastReceiver,然后将BroadcastReceiver插入理论上的自启动服务中,但由于应用程序在后台无法调用startService,这也不能正常工作,而且似乎有点错误

我错过什么了吗?目前的做法是什么? 显然是有办法的,否则信使、游戏和其他应用程序将无法像他们那样工作

public class BackgroundTaskWorker extends Worker {

    public BackgroundTaskWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }
    @Override
    public Result doWork() {
        Log.i("WORKING","DOING SOME WORK");
        Context con = getApplicationContext();
        SharedPreferences preferences = con.getSharedPreferences(MainActivity.sharedPrefs, Context.MODE_PRIVATE);
        SharedPreferences.Editor editPrefs = preferences.edit();
        int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
        String s_day = preferences.getString("DAY","0");
        int old_day = Integer.parseInt(s_day);
        if(old_day == 0){
            Log.i("WORKING","old_day default");
            editPrefs.putString("DAY",Integer.toString(day));
            editPrefs.commit();
            return Result.success();
        }
        else if(day == old_day) {
            Log.i("WORKING", "day=old_day default");
            return Result.success();
        }
        else {
            Log.i("WORKING","old_day change");
            editPrefs.putString("DAY",Integer.toString(day));
            editPrefs.commit();
            Log.d("BISASAM","triggered");


            DateFormat date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.GERMANY);
            Date dat = new Date();
            Log.d("TRIGGERDATE",date.format(dat));
            editPrefs.putString("REC", "Receiver called "+date.format(dat));


            NotificationCompat.Builder builder= new NotificationCompat.Builder(con,"ID");
            builder.setContentTitle("ALARM FIRED");
            builder.setContentText("WORKER");
            builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
            builder.setSmallIcon(R.drawable.kreuz);
            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
                Log.d("BUILDCHECK","correct");
                CharSequence name = "NotChannel";
                String desc = "Test Channel for Planer";
                int importance = NotificationManager.IMPORTANCE_DEFAULT;
                NotificationChannel channel = new NotificationChannel("NOT",name,importance);
                channel.setDescription(desc);
                NotificationManager notManager = con.getSystemService(NotificationManager.class);
                notManager.createNotificationChannel(channel);
                NotificationManagerCompat notificationManager = NotificationManagerCompat.from(con);
                builder.setChannelId("NOT");
                notificationManager.notify(1,builder.build());
            }
            //TODO Test Tageswechsel Wiederholende Tasks
            String today = preferences.getString("0",null);
            String tomorrow = preferences.getString("1",null);
            String next_week = preferences.getString("7",null);
            String next_month = preferences.getString("30",null);
            if(today != null) {
                String[] repetitive = today.split(" ");
                for (int j = 1; j < repetitive.length; j += 2) {
                    Log.d("PIKACHU",repetitive[j-1]);
                    switch(repetitive[j]){
                        case "1":
                            if(tomorrow!=null)
                                tomorrow += ","+ repetitive[j-1]+" "+repetitive[j];
                            else
                                tomorrow=repetitive[j-1]+" "+repetitive[j];
                            break;
                        case "7":
                            if(next_week!=null)
                                next_week += ","+ repetitive[j-1]+" "+repetitive[j];
                            else
                                next_week=repetitive[j-1]+" "+repetitive[j];
                            break;
                        case "30":
                            if(next_month!=null)
                                next_month += ","+ repetitive[j-1]+" "+repetitive[j];
                            else
                                next_month=repetitive[j-1]+" "+repetitive[j];
                            break;
                        default:
                    }

                }
            }
            Log.d("PUTTING",tomorrow);
            Log.d("PUTTING",next_week);
            Log.d("PUTTING",next_month);
            editPrefs.putString("1",tomorrow);
            editPrefs.putString("7",next_week);
            editPrefs.putString("30",next_month);
            editPrefs.commit();
            ArrayList<String> month = new ArrayList<>();
            for (int i = 0; i < Jobs.month_length; i++) {
                month.add(preferences.getString(Integer.toString(i),""));
            }
            for (int i=1;i<Jobs.month_length;i++){
                month.set(i-1,month.get(i));
            }
            month.set(30,"");
            for(int i=0;i<Jobs.month_length;i++){
                editPrefs.putString(Integer.toString(i),month.get(i));
            }
            Log.d("COMMITED",month.toString());
            editPrefs.commit();
        }
        // Indicate success or failure with your return value:
        return Result.success();
    }
}
每次启动应用程序时调用registerWorker=>使用WorkManager在后台和前台调度任务

定期请求示例

创建一个工人类

public class WorkerClass extends Worker {
    @Override
    public Worker.WorkerResult doWork() {

        // Do the work here

        // Indicate success or failure with your return value:
        return WorkerResult.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}
现在叫这个班

一次性请求的示例

OneTimeWorkRequest request= new OneTimeWorkRequest.Builder(WorkerClass .class)
.setInitialDelay(delayedTime, TimeUnit.MILLISECONDS)
.addTag("TAG")
.build();
 WorkManager.getInstance().enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, request);
其中delayedTime是计算完成任务的时间

将此添加到build.gradle中

查看最新的发布文档

你也可以转换你的时间

WorkManager是否可以这样做?将任务设置为始终在给定时间执行?对于Android Oreo和更高版本来说,这是背景安全的吗?是的,它将在这里工作。似乎不可能在特定时间运行它,也不可能重新执行任务?这将如何实现?现在检查我的答案,我要计算一次偏移量,然后工作将始终在时间=当前时间+偏移量?延迟=当前时间,单位为毫秒-特定时间触发单位为毫秒谢谢,我会尝试,但最后一件事。无法解析build.gradle的行。你知道为什么吗?
public class WorkerClass extends Worker {
    @Override
    public Worker.WorkerResult doWork() {

        // Do the work here

        // Indicate success or failure with your return value:
        return WorkerResult.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}
OneTimeWorkRequest request= new OneTimeWorkRequest.Builder(WorkerClass .class)
.setInitialDelay(delayedTime, TimeUnit.MILLISECONDS)
.addTag("TAG")
.build();
 WorkManager.getInstance().enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, request);
 implementation 'android.arch.work:work-runtime:2.1.0-alpha02'