2

This is similar to this and this - but they don't answer my issue, and over a year ago.

I wrote a simple code to schedule a periodic job but also when the device is idle.

Note: I'm not using the Android-Job library.

Simple activity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d("TEST123", "onCreate: ");
        JobScheduler j = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
        j.schedule(new JobInfo.Builder(1, new ComponentName(this, MyJobService.class))
                .setPeriodic(10 * 60 * 1000)
                .setRequiresDeviceIdle(true)
                .build());
    }
}

The service itself:

public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.d("TEST123", "onStartJob: ");
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }
}

Manifest part:

        <service
        android:name=".MyJobService"
        android:permission="android.permission.BIND_JOB_SERVICE"></service>

With this running on an Android O 8.0 x86 emulator, the job never fires. Things I've already tried:

  • I waited and waited (hours)
  • "turned off" the emulator screen
  • put the app in background
  • closed the app completely (FYI: since it's periodic the job service itself keeps running it)
  • put the emulator in 'force-idle'... (although the docs say explicitly it's not the same type of 'idle')
    • ran the app without the debugger attached

output of the command: sysdump jobscheduler that's relevant to my job:

JOB #u0a83/1: e1e90f com.example.myapplication/.MyJobService
u0a83 tag=*job*/com.example.myapplication/.MyJobService
Source: uid=u0a83 user=0 pkg=com.example.myapplication
JobInfo:
  Service: com.example.myapplication/.MyJobService
  PERIODIC: interval=+15m0s0ms flex=+10m0s0ms
  Requires: charging=false batteryNotLow=false deviceIdle=true
  Backoff: policy=1 initial=+30s0ms
  Has early constraint
  Has late constraint
Required constraints: TIMING_DELAY DEADLINE IDLE
Satisfied constraints: TIMING_DELAY DEADLINE APP_NOT_IDLE DEVICE_NOT_DOZING
Unsatisfied constraints: IDLE
Tracking: IDLE TIME
Enqueue time: -1h0m0s393ms
Run time: earliest=-55m0s393ms, latest=-45m0s393ms
Ready: false (job=false user=true !pending=true !active=true !backingup=true comp=true)

As you can read, it seems the job should have fired long ago, but doesn't and only because of the idle constraint. Can anyone reproduce this or understand why it's happening?

Syscall
  • 19,327
  • 10
  • 37
  • 52
Rob.B
  • 21
  • 2

1 Answers1

0

You are forcing your emulator into doze mode, I'm assuming for testing purposes. The equivalent command for a device is adb shell dumpsys deviceidle force-idle & to wake up the device use adb shell dumpsys deviceidle unforce. While in doze mode, the system will not allow JobScheduler to run. Take a look at some of the other restrictions.

See this documentation:

Doze restrictions
The following restrictions apply to your apps while in Doze:

  • Network access is suspended.
  • The system ignores wake locks.
  • Standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window.
  • If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
  • Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.
  • The system does not perform Wi-Fi scans.
  • The system does not allow sync adapters to run.
  • The system does not allow JobScheduler to run.

If you need a scheduler to execute while in doze mode, you will need to use AlarmManager's setAndAllowWhileIdle() or setExactAndAllowWhileIdle() APIs.

Asad Mahmood
  • 532
  • 1
  • 5
  • 15
Steve Miskovetz
  • 2,360
  • 13
  • 29