0

Since I'm struggling a lot with the Android Oreo background restriction, I was asking myself if working with the AlarmManager is even the best way of timing Job execution to e.g. 03:00 AM. I saw some people use JobScheduler, but it seems it's not that suitable for executing tasks every day at a given time.

I was trying just AlarmManager with a BroadcastReceiver, then inserted the BroadcastReceiver in a (in theory) self-starting service, but since an app isn't able to call startService() when in background this also doesn't work the way it should (and also seems kinda wrong).

Am I missing something? What's the current way to go? Obviously there are ways, because otherwise Messengers, Games and other Apps won't be able to work the way they do.

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");
    }

registerWorker is called everytime MainActivity gets started (=> at the app start)

1 Answers1

1

Use WorkManager for Scheduling task in background and foreground

Example for Periodic Request

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);

Create a worker class

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.)
    }
}

Now call this class by

Example for One Time request

OneTimeWorkRequest request= new OneTimeWorkRequest.Builder(WorkerClass .class)
.setInitialDelay(delayedTime, TimeUnit.MILLISECONDS)
.addTag("TAG")
.build();
 WorkManager.getInstance().enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, request);

where delayedTime is calculated time to do task

add this in build.gradle

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

check the latest release doc https://developer.android.com/jetpack/androidx/releases/work

also you can convert your time Android / Java convert String date to long type

Quick learner
  • 10,632
  • 4
  • 45
  • 55