Beginning with Android Lollipop, JobScheduler is able to schedule tasks with complex conditions and execute them when those conditions are met. Consider FirebaseJobDispatcher instead for greater backwards compatibility.
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); // Get a JobScheduler
JobInfo job = new JobInfo.Builder( // Build a new JobInfo object
MY_BACKGROUND_JOB, new ComponentName(context, MyJobService.class)) // Point to your JobService class
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // Only trigger when on an unmetered network e.g. Wifi
.setRequiresCharging(true) // Only trigger when being charged
.setBackOffCriteria(TWO_MINUTES,BACKOFF_POLICY_EXPONENTIAL) // After first fail, wait 2 minutes, and increase wait time exponentially with every subsequent fail
.setMinimumLatency(FIFTEEN_MINUTES) // Minimum wait before triggering is 15 minutes
.build();
js.schedule(job) // Call the job using this code
