I am working on making my alarm app compatible with a soon to be released Android 12 and lately I stumbled upon a problem. It seems that since Android 12 update, jobs scheduled in Job Scheduler during locked/direct boot are not started until after the device is unlocked. I have reviewed changes made in Android 12 and I don't find any that would apply to my situation and I found out about it during random tests.
It is a major problem, as I need to reschedule alarms for my app on devices reboot and can't wait for the user to unlock the device first, as a reboot may happen automatically overnight, leaving user without a scheduled alarm in the morning.
When running below test app (targeting Android 11), results are as below:
Any suggestions on how to work with this, beside running whole job manually, for example with a use of a WakeLock? Or maybe someone knows what changes of Android 12 are actually in effect here?
Here's a simple test class for observing this situation:
class TestScheduler : JobService() {
companion object {
fun addScheduledJob(context: Context){
JobInfo.Builder(1111, ComponentName(context, TestScheduler::class.java))
.setOverrideDeadline(TimeUnit.SECONDS.toMillis(1))
.build().let {
val result = (context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler).schedule(it)
when(result){
JobScheduler.RESULT_SUCCESS -> "success"
else -> "failure"
}.also {
Log.d("MyTAG", "jobScheduled: $it")
}
}
}
}
override fun onStartJob(params: JobParameters?): Boolean {
Log.d("MyTAG", "onStartJob: ${params?.jobId}")
jobFinished(params, false)
return true
}
override fun onStopJob(params: JobParameters?): Boolean {
Log.d("MyTAG", "onStopJob: ${params?.jobId}")
return true
}
}
Job is scheduled from a boot receiver:
class OnBootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
TestScheduler.addScheduleJob(context)
}
}
Both clasess are directBootAware (manifest's content):
<receiver
android:name=".OnBootReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".TestScheduler"
android:directBootAware="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
I am having the same issue, and believe I have tracked down the change to the AOSP build which appear to cause the problem:
Looking at the android-12 history, there was a change to JobSchedulerService.java
to prevent jobs from running when the at the lock screen.
Merge "Wait for unlock to start jobs." into sc-dev
@Override
public void onUserUnlocked(@NonNull TargetUser user) {
synchronized (mLock) {
// Note that the user has started after its unlocked instead of when the user
// actually starts because the storage won't be decrypted until unlock.
mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
}
// Let's kick any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
And that change was later backed out:
Partial revert "Wait for unlock to start jobs."
@Override
public void onUserStarting(@NonNull TargetUser user) {
synchronized (mLock) {
mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
}
// The user is starting but credential encrypted storage is still locked.
// Only direct-boot-aware jobs can safely run.
// Let's kick off any eligible jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@Override
public void onUserUnlocked(@NonNull TargetUser user) {
// The user is fully unlocked and credential encrypted storage is now decrypted.
// Direct-boot-UNaware jobs can now safely run.
// Let's kick off any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
I have back-ported this change to to my source and it appears to have resolved the issue.
For those with the option to take a newer AOSP release, android-12.1.0_26 has this change present.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With