Simian
Simian

Reputation: 11

Alarms and jobs being cleared when application is closed?


So, I am trying to run a service in the background that can send some app data to my server So far I've tried using AlarmManager, JobScheduler classes to run the service periodically but its no use since any alarms created and jobs scheduled ARE CLEARED as the application is closed (closed here does not mean force stopped). I looked around and have seen a lot of StackOverflow questions for similar usecases(but older android versions) and same clearing problem, but no concrete answer or implementation i found is working. (is this an issue with latest versions of android?)

My use case is small data(in/ kbs) upload once or twice a day from the application to maintain usage track of the application.

Since i can't expect user to keep his app open all day...



UPDATE-1

According to @Kabumere answer and some help from android dev docs i used WorkManager and tried this code below
Expected behaviour(for now)
continous repeating logs with 20 min interval (20 min is just for testing) regardless if app was closed(ie that 30 min interval between 6 and 7)
Actual Behaviour

  1. app is in focus on testing device(genymotion android 9)
  2. 08:47 onCreate schedules first job and it runs
  3. app is closed but present in recents
  4. 09:02 second job runs (15 min apart)
  5. app now closed from recent
  6. // no further logs for 30 mins, jobs not started
  7. 09:36 application started manually, nothing is enqueued as per logic
  8. jobs continue at 15 min interval
2020-08-05 08:47:53.260 7746-7746/com.example.workmanagerapi D/debugTag: Scheduling
2020-08-05 08:47:53.655 7746-7802/com.example.workmanagerapi D/debugTag: DOING SOME WORK !!!
2020-08-05 09:02:53.732 7746-8007/com.example.workmanagerapi D/debugTag: DOING SOME WORK !!!
2020-08-05 09:36:47.165 8347-8347/com.example.workmanagerapi D/debugTag: Already Scheduled
2020-08-05 09:36:47.193 8347-8376/com.example.workmanagerapi D/debugTag: DOING SOME WORK !!!
2020-08-05 09:51:47.269 8347-8486/com.example.workmanagerapi D/debugTag: DOING SOME WORK !!!

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SharedPreferences SP = getSharedPreferences("prefs",MODE_PRIVATE);
        SharedPreferences.Editor editor = SP.edit();
        boolean enqueue = SP.getBoolean("enqueue", false);
        if(enqueue) {
            Log.d("debugTag", "Already Scheduled");
        }
        else {
            Log.d("debugTag", "Scheduling");
            doWork();
            editor.putBoolean("enqueue",true);
            editor.apply();
        }
    }

    private void doWork() {
        PeriodicWorkRequest.Builder myWorkBuilder = new PeriodicWorkRequest.Builder(MyWorker.class, 1, TimeUnit.MINUTES);
        // i read on docs that this time limit will default to (5+15) minutes minimum
        PeriodicWorkRequest myWork = myWorkBuilder.build();
        WorkManager.getInstance(this).enqueue(myWork);
    }
}

MyWorker.java

public class MyWorker extends Worker {
    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        Log.d("debugTag", "DOING SOME WORK !!!");
        return Result.success();
    }

Upvotes: 1

Views: 242

Answers (1)

kabumere
kabumere

Reputation: 383

I'd recommend using the WorkManager API over creating a Service.

With WorkManager you can enqueue a PeriodicWorkRequest that will run at the interval you set in its Builder constructor (like run every 24 hours). Scheduled jobs through WorkManager should not be deleted when the app is closed, will be automatically rescheduled at different events like device reboot, and can run even when the app is in the background.

You can also set Constraints on WorkRequests so you can specify things like "only attempt to run this job if we have any sort of data connection" (setRequiredNetworkType(NetworkType.CONNECTED)). This is good for your use case of needing to send data, which will require some connection.

Upvotes: 1

Related Questions