Fixed
Status Update
Comments
il...@google.com <il...@google.com> #2
Bringing setMaxSchedulerLimit to say 49 doesn't help. Same error.
du...@gmail.com <du...@gmail.com> #3
If you are using work-firebase then you should not be using JobScheduler directly. Can you please send us the full bug report so we can investigate ?
il...@google.com <il...@google.com> #4
java.lang.IllegalStateException: Apps may not schedule more than 100 distinct jobs
at android.os.Parcel.readException(Parcel.java:1692)
at android.os.Parcel.readException(Parcel.java:1637)
at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:158)
at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:42)
at androidx.work.impl.background.systemjob.SystemJobScheduler.scheduleInternal(SystemJobScheduler.java:126)
at androidx.work.impl.background.systemjob.SystemJobScheduler.schedule(SystemJobScheduler.java:95)
at androidx.work.impl.Schedulers.scheduleInternal(Schedulers.java:104)
at androidx.work.impl.Schedulers.schedule(Schedulers.java:73)
at androidx.work.impl.WorkerWrapper.setSucceededAndNotify(WorkerWrapper.java:393)
at androidx.work.impl.WorkerWrapper.handleResult(WorkerWrapper.java:255)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:181)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
at android.os.Parcel.readException(Parcel.java:1692)
at android.os.Parcel.readException(Parcel.java:1637)
at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:158)
at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:42)
at androidx.work.impl.background.systemjob.SystemJobScheduler.scheduleInternal(SystemJobScheduler.java:126)
at androidx.work.impl.background.systemjob.SystemJobScheduler.schedule(SystemJobScheduler.java:95)
at androidx.work.impl.Schedulers.scheduleInternal(Schedulers.java:104)
at androidx.work.impl.Schedulers.schedule(Schedulers.java:73)
at androidx.work.impl.WorkerWrapper.setSucceededAndNotify(WorkerWrapper.java:393)
at androidx.work.impl.WorkerWrapper.handleResult(WorkerWrapper.java:255)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:181)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #5
What do you mean I shouldn't use JobScheduler directly? Isn't work-firebase is just for <21 devices, otherwise JobScheduler always used?
il...@google.com <il...@google.com> #6
I think i was confused by your previous comment. You are right, we only use work-firebase for API < 23.
JobScheduler is used for API >= 23.
This issue should have been resolved in `alpha03` and `alpha04` (we addressed different parts of the problem). If you can reproduce this on a device, then can you do:
1. adb shell dumpsys jobscheduler for your app.
2. Reboot your device.
3. After the reboot, can you re-run adb shell dumpsys jobscheduler ?
I want to check if you see any differences in the jobs created before and after the reboot.
Thanks for your patience.
JobScheduler is used for API >= 23.
This issue should have been resolved in `alpha03` and `alpha04` (we addressed different parts of the problem). If you can reproduce this on a device, then can you do:
1. adb shell dumpsys jobscheduler for your app.
2. Reboot your device.
3. After the reboot, can you re-run adb shell dumpsys jobscheduler ?
I want to check if you see any differences in the jobs created before and after the reboot.
Thanks for your patience.
du...@gmail.com <du...@gmail.com> #7
Actually for step 2, the easier thing to do is to force stop your app. You don't need to fo a full reboot.
ne...@gmail.com <ne...@gmail.com> #8
I don't have to to rummage through traces. Here's code snippet that sends app into a crash loop. https://pastebin.com/NcTAnwjZ
il...@google.com <il...@google.com> #9
I tried to reproduce this on alpha04. However, I cannot reproduce your issue.
For reference, this is what my activity looks like:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.scheduler_limits_testcase1).setOnClickListener {
for (i in 1..100) {
val a1 = newWorkRequest("--- A1 ---")
val b1 = newWorkRequest("--- B1 ---")
val b2 = newWorkRequest("--- B2 ---")
val c1 = newWorkRequest("--- C1 ---")
WorkManager.getInstance()!!
.beginWith(a1).then(b1).enqueue()
WorkManager.getInstance()!!
.beginWith(a1).then(b2).enqueue()
WorkManager.getInstance()!!
.beginWith(b1, b2).then(c1).enqueue()
}
}
}
companion object {
private fun newWorkRequest(message: String): OneTimeWorkRequest {
val data = mapOf(TestWorker.KEY_MESSAGE to message).toWorkData()
return OneTimeWorkRequestBuilder<TestWorker>()
.setInputData(data)
.build()
}
}
}
This is what my Worker looks like:
class TestWorker : Worker() {
companion object {
private const val TAG = "TestWorker"
private const val MESSAGE_DEFAULT = "Default"
const val KEY_MESSAGE = "KEY_MESSAGE"
}
override fun doWork(): Result {
val message = inputData.getString(KEY_MESSAGE, MESSAGE_DEFAULT)
val random = Random()
val time = 500L + random.nextInt(300)
Log.d(TAG, "Before. $message")
Thread.sleep(time)
Log.d(TAG, "After. $message")
return Result.SUCCESS
}
}
For reference, this is what my activity looks like:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.scheduler_limits_testcase1).setOnClickListener {
for (i in 1..100) {
val a1 = newWorkRequest("--- A1 ---")
val b1 = newWorkRequest("--- B1 ---")
val b2 = newWorkRequest("--- B2 ---")
val c1 = newWorkRequest("--- C1 ---")
WorkManager.getInstance()!!
.beginWith(a1).then(b1).enqueue()
WorkManager.getInstance()!!
.beginWith(a1).then(b2).enqueue()
WorkManager.getInstance()!!
.beginWith(b1, b2).then(c1).enqueue()
}
}
}
companion object {
private fun newWorkRequest(message: String): OneTimeWorkRequest {
val data = mapOf(TestWorker.KEY_MESSAGE to message).toWorkData()
return OneTimeWorkRequestBuilder<TestWorker>()
.setInputData(data)
.build()
}
}
}
This is what my Worker looks like:
class TestWorker : Worker() {
companion object {
private const val TAG = "TestWorker"
private const val MESSAGE_DEFAULT = "Default"
const val KEY_MESSAGE = "KEY_MESSAGE"
}
override fun doWork(): Result {
val message = inputData.getString(KEY_MESSAGE, MESSAGE_DEFAULT)
val random = Random()
val time = 500L + random.nextInt(300)
Log.d(TAG, "Before. $message")
Thread.sleep(time)
Log.d(TAG, "After. $message")
return Result.SUCCESS
}
}
mo...@gmail.com <mo...@gmail.com> #10
Do you have another part of your codebase that is scheduling jobs with JobScheduler?
[Deleted User] <[Deleted User]> #11 Restricted+
Restricted+
Comment has been deleted.
Description
Version used: android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha11
Devices/Android versions reproduced on: not related to device/api version, it is code generation problem
Bug description:
navigation file defined like this:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="
xmlns:app="
xmlns:tools="
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="no.amedia.newsapp.android.WebPageFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_web_page" >
<argument
android:name="web_url"
app:argType="string"
android:defaultValue="@string/url" />
</fragment>
<action android:id="@+id/action_global_homeFragment"
app:destination="@id/homeFragment" />
....
</navigation>
where url (referenced as "@string/url") is defined as <string name="url" translatable="false">
generates code like this:
class NavGraphDirections private constructor() {
private data class ActionGlobalHomeFragment(val webUrl: String = "@string/url") :
NavDirections {
override fun getActionId(): Int = no.amedia.newsapp.android.R.id.action_global_homeFragment
override fun getArguments(): Bundle {
val result = Bundle()
result.putString("web_url", this.webUrl)
return result
}
}
companion object {
fun actionGlobalHomeFragment(webUrl: String = "@string/url"): NavDirections =
ActionGlobalHomeFragment(webUrl)
}
}
so the problem is webUrl: String = "@string/url" instead of webUrl: String = "
the same is with WebPageFragmentDirections generated class:
class WebPageFragmentDirections private constructor() {
companion object {
fun actionGlobalHomeFragment(webUrl: String = "@string/url"): NavDirections =
NavGraphDirections.actionGlobalHomeFragment(webUrl)
}
when I try to use code like this
navController.navigate(WebPageFragmentDirections.actionGlobalHomeFragment())
or
navController.navigate(NavGraphDirections.actionGlobalHomeFragment())
argument value in the fragment is "@string/url" instead of "
while if I navigate like this
navController.navigate(R.id.homeFragment)
default value from navigation xml is used correctly and I get "
I hope that I manage to describe the problem in a proper way, it is very simple to reproduce, but if you have any questions just ask