【问题标题】:Current best practice for timed job execution in AndroidAndroid 中定时作业执行的当前最佳实践
【发布时间】:2023-03-02 23:11:01
【问题描述】:

由于我在 Android Oreo 背景限制方面遇到了很多困难,所以我问自己是否使用 AlarmManager 甚至是安排作业执行时间的最佳方式,例如凌晨 03:00。我看到有人使用JobScheduler,但它似乎不太适合每天在特定时间执行任务。

我只是尝试 AlarmManagerBroadcastReceiver,然后将 BroadcastReceiver 插入(理论上)自启动服务中,但由于应用程序无法在后台调用 startService()也没有按应有的方式工作(而且似乎有点错误)。

我错过了什么吗?目前要走的路是什么? 显然是有办法的,否则 Messenger、游戏和其他应用程序将无法按照它们的方式工作。

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();
    }
}
 private void registerWorker(){
        unregisterWorker();
        PeriodicWorkRequest request= new PeriodicWorkRequest.Builder(BackgroundTaskWorker.class,
                20, TimeUnit.MINUTES)
                .addTag("AUFGABEN_PLANER_BACK")
                .build();
        WorkManager.getInstance().enqueueUniquePeriodicWork("AUFGABEN_PLANER_BACK", ExistingPeriodicWorkPolicy.KEEP, request);
    }
    private void unregisterWorker(){
        WorkManager.getInstance().cancelAllWorkByTag("AUFGABEN_PLANER_BACK");
    }

每次 MainActivity 启动时都会调用 registerWorker(=> 在应用启动时)

【问题讨论】:

标签: android time alarmmanager


【解决方案1】:

backgroundforeground中使用WorkManager调度任务

定期请求

示例
PeriodicWorkRequest request= new PeriodicWorkRequest.Builder(WorkerClass.class,
                            24, TimeUnit.HOURS).setInitialDelay(THE_DELAY,TimeUnit.SECONDS).addTag("TAG").build()
WorkManager.getInstance().enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, request);

创建一个工人阶级

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

 implementation 'android.arch.work:work-runtime:2.1.0-alpha02'

查看最新的发布文档 https://developer.android.com/jetpack/androidx/releases/work

你也可以转换你的时间 Android / Java convert String date to long type

【讨论】:

  • 对于重复任务?这将如何实施?
  • 立即查看我的答案
  • 所以我得计算一次offset,然后工作总是在time = current_time + offset?
  • THE_DELAY = currentTime (in Millis) - specificTimeToTrigger (in Millis)
  • 谢谢,我会尝试的,但最后一件事。 build.gradle 的行无法解析。任何想法为什么?
猜你喜欢
  • 2015-05-25
  • 1970-01-01
  • 2015-04-14
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多