Android library to handle jobs in the background.

Overview

DEPRECATED

This library is not maintained anymore and there will be no further releases except for very critical bug fixes. Use WorkManager instead of this library.

Android-Job

A utility library for Android to run jobs delayed in the background. Depending on the Android version either the JobScheduler, GcmNetworkManager or AlarmManager is getting used. You can find out in this blog post or in these slides why you should prefer this library than each separate API. All features from Android Oreo are backward compatible back to Ice Cream Sandwich.

Download

Download the latest version or grab via Gradle:

dependencies {
    implementation 'com.evernote:android-job:1.4.2'
}

Starting with version 1.3.0 the library will use the WorkManager internally, please read the documentation and opt-in.

If you didn't turn off the manifest merger from the Gradle build tools, then no further step is required to setup the library. Otherwise you manually need to add the permissions and services like in this AndroidManifest.

You can read the JavaDoc here.

Usage

The class JobManager serves as entry point. Your jobs need to extend the class Job. Create a JobRequest with the corresponding builder class and schedule this request with the JobManager.

Before you can use the JobManager you must initialize the singleton. You need to provide a Context and add a JobCreator implementation after that. The JobCreator maps a job tag to a specific job class. It's recommended to initialize the JobManager in the onCreate() method of your Application object, but there is an alternative, if you don't have access to the Application class.

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        JobManager.create(this).addJobCreator(new DemoJobCreator());
    }
}
public class DemoJobCreator implements JobCreator {

    @Override
    @Nullable
    public Job create(@NonNull String tag) {
        switch (tag) {
            case DemoSyncJob.TAG:
                return new DemoSyncJob();
            default:
                return null;
        }
    }
}

After that you can start scheduling jobs.

public class DemoSyncJob extends Job {

    public static final String TAG = "job_demo_tag";

    @Override
    @NonNull
    protected Result onRunJob(Params params) {
        // run your job here
        return Result.SUCCESS;
    }

    public static void scheduleJob() {
        new JobRequest.Builder(DemoSyncJob.TAG)
                .setExecutionWindow(30_000L, 40_000L)
                .build()
                .schedule();
    }
}

Advanced

The JobRequest.Builder class has many extra options, e.g. you can specify a required network connection, make the job periodic, pass some extras with a bundle, restore the job after a reboot or run the job at an exact time.

Each job has a unique ID. This ID helps to identify the job later to update requirements or to cancel the job.

private void scheduleAdvancedJob() {
    PersistableBundleCompat extras = new PersistableBundleCompat();
    extras.putString("key", "Hello world");

    int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .setExecutionWindow(30_000L, 40_000L)
            .setBackoffCriteria(5_000L, JobRequest.BackoffPolicy.EXPONENTIAL)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(false)
            .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
            .setExtras(extras)
            .setRequirementsEnforced(true)
            .setUpdateCurrent(true)
            .build()
            .schedule();
}

private void schedulePeriodicJob() {
    int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
            .build()
            .schedule();
}

private void scheduleExactJob() {
    int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .setExact(20_000L)
            .build()
            .schedule();
}

private void runJobImmediately() {
    int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .startNow()
            .build()
            .schedule();
}

private void cancelJob(int jobId) {
    JobManager.instance().cancel(jobId);
}

If a non periodic Job fails, then you can reschedule it with the defined back-off criteria.

public class RescheduleDemoJob extends Job {

    @Override
    @NonNull
    protected Result onRunJob(Params params) {
        // something strange happened, try again later
        return Result.RESCHEDULE;
    }

    @Override
    protected void onReschedule(int newJobId) {
        // the rescheduled job has a new ID
    }
}

Proguard

The library doesn't use reflection, but it relies on three Services and two BroadcastReceivers. In order to avoid any issues, you shouldn't obfuscate those four classes. The library bundles its own Proguard config and you don't need to do anything, but just in case you can add these rules in your configuration.

More questions?

See the FAQ in the Wiki.

WorkManager

WorkManager is a new architecture component from Google and tries to solve a very similar problem this library tries to solve: implementing background jobs only once for all Android versions. The API is very similar to this library, but provides more features like chaining work items and it runs its own executor.

If you start a new project, you should be using WorkManager instead of this library. You should also start migrating your code from this library to WorkManager. At some point in the future this library will be deprecated.

Starting with version 1.3.0 this library will use the WorkManager internally for scheduling jobs. That should ease the transition to the new architecture component. You only need to add the WorkManager to your classpath, e.g.

dependencies {
    implementation "android.arch.work:work-runtime:$work_version"
}

Please take a look at the Wiki for a complete transition guide.

The API and feature set of android-job and WorkManager are really similar. However, some features are unique and only supported by one or the other

Feature android-job WorkManager
Exact jobs Yes No
Transient jobs Yes No
Daily jobs Yes No
Custom Logger Yes No
Observe job status No Yes
Chained jobs No Yes
Work sequences No Yes

Google Play Services

This library does not automatically bundle the Google Play Services, because the dependency is really heavy and not all apps want to include them. That's why you need to add the dependency manually, if you want that the library uses the GcmNetworkManager on Android 4, then include the following dependency.

dependencies {
    compile "com.google.android.gms:play-services-gcm:latest_version"
}

Because of recent changes in the support library, you must turn on the service manually in your AndroidManifest.xml

<service
    android:name="com.evernote.android.job.gcm.PlatformGcmService"
    android:enabled="true"
    tools:replace="android:enabled"/>

If you don't turn on the service, the library will always use the AlarmManager on Android 4.x.

Crashes after removing the GCM dependency is a known limitation of the Google Play Services. Please take a look at this workaround to avoid those crashes.

License

Copyright (c) 2007-2017 by Evernote Corporation, All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Android O - java.lang.RuntimeException: An error occurred while executing doInBackground()

    Android O - java.lang.RuntimeException: An error occurred while executing doInBackground()

    Crash happened with 1.2.0-alpha3 on Pixel running 8.0.0. Here's the stacktrace:

    Fatal Exception: java.lang.RuntimeException: An error occurred while executing doInBackground()
           at android.os.AsyncTask$3.done(AsyncTask.java:353)
           at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
           at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
           at java.util.concurrent.FutureTask.run(FutureTask.java:271)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
           at java.lang.Thread.run(Thread.java:764)
    Caused by java.lang.SecurityException: Caller no longer running, last stopped +25s437ms because: timed out while starting
           at android.os.Parcel.readException(Parcel.java:1942)
           at android.os.Parcel.readException(Parcel.java:1888)
           at android.app.job.IJobCallback$Stub$Proxy.dequeueWork(IJobCallback.java:191)
           at android.app.job.JobParameters.dequeueWork(JobParameters.java:196)
           at android.support.v4.app.JobIntentService$JobServiceEngineImpl.dequeueWork(JobIntentService.java:309)
           at android.support.v4.app.JobIntentService.dequeueWork(JobIntentService.java:627)
           at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:384)
           at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:377)
           at android.os.AsyncTask$2.call(AsyncTask.java:333)
           at java.util.concurrent.FutureTask.run(FutureTask.java:266)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
           at java.lang.Thread.run(Thread.java:764)
    
    bug 
    opened by rockerhieu 61
  • Jobs rescheduled after reboot even if they shouldn't be

    Jobs rescheduled after reboot even if they shouldn't be

    So I use android-job and use setPersisted. Persistence should be cleared once job finishes executing and it happens on most phones, but on some it doesn't - that causes jobs to repeat themselves after the boot.

    The problem happens on Alcatel phones that have Android 6.0.

    Any idea what's happening?

    question 
    opened by mario 48
  • Library crash after play-services-gcm:12.0.0 update.

    Library crash after play-services-gcm:12.0.0 update.

    My app started crashing after updating com.google.android:play-services-gcm from 11.8.0 to 12.0.0. Crash appears in your library. Error is following:

    java.lang.RuntimeException: Unable to create application: java.lang.IllegalArgumentException: The GcmTaskService class you provided com.evernote.android.job.gcm.PlatformGcmService does not seem to support receiving com.google.android.gms.gcm.ACTION_TASK_READY

    Tested on 4.4.2.

    bug needs info 
    opened by anri-vin 39
  • SQLiteConstraintException: UNIQUE constraint failed: jobs._id

    SQLiteConstraintException: UNIQUE constraint failed: jobs._id

    Not sure if this is just an concurrency issue of the users' db got corruped.

    There following crash was observed by fabric on an Samsung 5.0 and 6.0 when executing:

    new JobRequest.Builder(JOB_WIDGET_UPDATER)
                    .setExecutionWindow(SECONDS.toMillis(3), SECONDS.toMillis(15))
                    .build()
                    .schedule();
    

    android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: jobs._id (code 1555) ################################################################# Error Code : 1555 (SQLITE_CONSTRAINT_PRIMARYKEY) Caused By : Abort due to constraint violation. (UNIQUE constraint failed: jobs._id (code 1555)) ################################################################# at android.app.ActivityThread.handleReceiver(ActivityThread.java:3641) at android.app.ActivityThread.access$2000(ActivityThread.java:221) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1876) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7224) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: jobs._id (code 1555) ################################################################# Error Code : 1555 (SQLITE_CONSTRAINT_PRIMARYKEY) Caused By : Abort due to constraint violation. (UNIQUE constraint failed: jobs._id (code 1555)) ################################################################# at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(SQLiteConnection.java) at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:915) at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788) at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86) at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1609) at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1505) at com.evernote.android.job.JobStorage.store(JobStorage.java:245) at com.evernote.android.job.JobStorage.put(JobStorage.java:127) at com.evernote.android.job.JobManager.schedule(JobManager.java:231) at com.evernote.android.job.JobRequest.schedule(JobRequest.java:354)

    bug 
    opened by tobiasschuerg 39
  • JobStatus.getUid()' on a null object reference

    JobStatus.getUid()' on a null object reference

    Not sure if actually an issue with this lib or maybe gcm.

    Cant't reproduce but seems to happen after JobManager.instance().cancelAllForTag. Up to now only appeared three times (2x Samsung 5.0, 1x Huawai 6.0) within the last week (having a few thousand active users per day).

    Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.android.server.job.controllers.JobStatus.getUid()' on a null object reference
           at android.os.Parcel.readException(Parcel.java:1552)
           at android.os.Parcel.readException(Parcel.java:1499)
           at android.app.job.IJobCallback$Stub$Proxy.jobFinished(IJobCallback.java:167)
           at android.app.job.JobService$JobHandler.handleMessage(JobService.java:147)
           at android.os.Handler.dispatchMessage(Handler.java:102)
           at android.os.Looper.loop(Looper.java:135)
           at android.app.ActivityThread.main(ActivityThread.java:5910)
           at java.lang.reflect.Method.invoke(Method.java)
           at java.lang.reflect.Method.invoke(Method.java:372)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
    
    opened by tobiasschuerg 32
  • Rejecting re-init on previously-failed class java.lang.Class<com.evernote.android.job.gcm.PlatformGcmService>

    Rejecting re-init on previously-failed class java.lang.Class

    I know that this is not the first post of its kind, and while not all issues that may look similar are caused by the same bug in the code, there should be some at least.

    Symptoms in this specific case:

    Rejecting re-init on previously-failed class java.lang.Class<com.evernote.android.job.gcm.PlatformGcmService>: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/gcm/GcmTaskService;
        at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
        at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
        at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
        at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
        at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
        at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
        at void java.lang.Thread.run() (Thread.java:764)
    Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService" on path: DexPathList[[zip file ...
        at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:125)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
        at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
        at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
        at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
        at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
        at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
        at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
        at void java.lang.Thread.run() (Thread.java:764)
    Rejecting re-init on previously-failed class java.lang.Class<com.evernote.android.job.gcm.PlatformGcmService>: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/gcm/GcmTaskService;
        at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
        at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
        at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
        at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
        at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
        at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
        at void java.lang.Thread.run() (Thread.java:764)
    Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.gcm.GcmTaskService" on path: DexPathList[[zip file ...
        at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:125)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
        at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
        at boolean com.evernote.android.job.GcmAvailableHelper.isGcmApiSupported(android.content.Context) (GcmAvailableHelper.java:-1)
        at boolean com.evernote.android.job.JobApi.isSupported(android.content.Context) (JobApi.java:115)
        at void com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(android.content.Context, int) (JobProxy.java:286)
        at void com.evernote.android.job.JobManager.schedule(com.evernote.android.job.JobRequest) (JobManager.java:176)
        at int com.evernote.android.job.JobRequest.schedule() (JobRequest.java:426)
        at void com.evernote.android.job.JobRequest$2.run() (JobRequest.java:455)
        at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
        at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
        at void java.lang.Thread.run() (Thread.java:764)
    
    

    Prerequisites: I don't have GCM included and I don't want it.

    bug 
    opened by softworkz 26
  • [1.2.0-RC1] Didn't find class

    [1.2.0-RC1] Didn't find class "android.app.job.JobServiceEngine"

    Hey,

    looks like version 1.2.0-RC1 doesn't work on pre-Oreo devices. While adding JobCreator in the Application class JobManager.create(this).addJobCreator(new SampleJobCreator()); the following error about missing android.app.job.JobServiceEngine class occurs:

    09-02 20:27:52.601 9871-9871/com.sampleapp I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.app.JobIntentService$JobServiceEngineImpl>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/app/job/JobServiceEngine;
    09-02 20:27:52.601 9871-9871/com.sampleapp I/art:     at void com.evernote.android.job.JobRescheduleService.startService(android.content.Context) (JobRescheduleService.java:29)
    09-02 20:27:52.601 9871-9871/com.sampleapp I/art:     at void com.evernote.android.job.JobManager.<init>(android.content.Context) (JobManager.java:159)
    09-02 20:27:52.601 9871-9871/com.sampleapp I/art:     at com.evernote.android.job.JobManager com.evernote.android.job.JobManager.create(android.content.Context) (JobManager.java:112)
    09-02 20:27:52.601 9871-9871/com.sampleapp I/art:     at void com.sampleapp.SampleApplication.setUpJobCreator() (SampleApplication.java:119)
    09-02 20:27:52.601 9871-9871/com.sampleapp I/art:     at void com.sampleapp.SampleApplication.onCreate() (SampleApplication.java:73)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.Instrumentation.callApplicationOnCreate(android.app.Application) (Instrumentation.java:1024)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.handleBindApplication(android.app.ActivityThread$AppBindData) (ActivityThread.java:5405)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.-wrap2(android.app.ActivityThread, android.app.ActivityThread$AppBindData) (ActivityThread.java:-1)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1546)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.os.Looper.loop() (Looper.java:154)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6121)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.app.job.JobServiceEngine" on path: DexPathList[[zip file "/data/app/com.sampleapp-2/base.apk", zip file "/data/app/com.sampleapp-2/split_lib_dependencies_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_0_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_1_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_2_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_3_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_4_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_5_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_6_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_7_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_8_apk.apk", zip file "/data/app/com.sampleapp-2/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.sampleapp-2/lib/arm64, /system/lib64, /vendor/lib64]]
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.evernote.android.job.JobRescheduleService.startService(android.content.Context) (JobRescheduleService.java:29)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.evernote.android.job.JobManager.<init>(android.content.Context) (JobManager.java:159)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at com.evernote.android.job.JobManager com.evernote.android.job.JobManager.create(android.content.Context) (JobManager.java:112)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.sampleapp.SampleApplication.setUpJobCreator() (SampleApplication.java:119)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.sampleapp.SampleApplication.onCreate() (SampleApplication.java:73)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.Instrumentation.callApplicationOnCreate(android.app.Application) (Instrumentation.java:1024)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.handleBindApplication(android.app.ActivityThread$AppBindData) (ActivityThread.java:5405)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.-wrap2(android.app.ActivityThread, android.app.ActivityThread$AppBindData) (ActivityThread.java:-1)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1546)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.os.Looper.loop() (Looper.java:154)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6121)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
    09-02 20:27:52.602 9871-9871/com.sampleapp I/art:     at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
    

    Launching on Oreo looks fine. Am I missing something in configuration for pre-Oreo devices?

    needs info 
    opened by MateuszMlodawski 21
  • 1.11-SNAPSHOT:  com.evernote.android.job.JobManagerCreateException

    1.11-SNAPSHOT: com.evernote.android.job.JobManagerCreateException

    Seeing these reported for the first time on the Play store with my app using 1.11-SNAPSHOT.

    Android 7.0 com.evernote.android.job.JobManagerCreateException com.evernote.android.job.JobManager. java.lang.RuntimeException: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5884) at android.app.ActivityThread.-wrap3(ActivityThread.java:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1718) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6688) at java.lang.reflect.Method.invoke(Method.java:0) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) Caused by: com.evernote.android.job.JobManagerCreateException: at com.evernote.android.job.JobManager.(JobManager.java:184) at com.evernote.android.job.JobManager.create(JobManager.java:107) at com.dvtonder.chronus.WidgetApplication.onCreate(WidgetApplication.java:166) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1032) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5881)

    And on Android 6.0 and 4.2 com.evernote.android.job.JobManagerCreateException com.evernote.android.job.JobManager. java.lang.RuntimeException: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431) at android.app.ActivityThread.access$1800(ActivityThread.java:229) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:7331) at java.lang.reflect.Method.invoke(Method.java:0) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: com.evernote.android.job.JobManagerCreateException: at com.evernote.android.job.JobManager.(JobManager.java:184) at com.evernote.android.job.JobManager.create(JobManager.java:107) at com.dvtonder.chronus.WidgetApplication.onCreate(WidgetApplication.java:166) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6428)

    opened by DvTonder 21
  • NoClassDefFoundError: Failed resolution of: Lcom/evernote/android/job/JobRescheduleService

    NoClassDefFoundError: Failed resolution of: Lcom/evernote/android/job/JobRescheduleService

    On API 5.1, getting this error.

    compile 'com.evernote:android-job:1.2.0-RC4'

    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/evernote/android/job/JobRescheduleService; at com.evernote.android.job.JobManager.<init>(JobManager.java:159) at com.evernote.android.job.JobManager.create(JobManager.java:112) at com.xxx.xxx.App.onCreate(App.java:20) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1017) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4858) at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method) at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:334) at android.app.ActivityThread.handleBindApplication(<Xposed>) at android.app.ActivityThread.access$1500(ActivityThread.java:178) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531) at android.os.Handler.dispatchMessage(Handler.java:111) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5637) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102) Caused by: java.lang.ClassNotFoundException: Didn't find class "com.evernote.android.job.JobRescheduleService" on path: DexPathList[[zip file "/data/app/com.xxx.xxx-2/base.apk"],nativeLibraryDirectories=[/data/app/com.xxx.xxx-2/lib/arm64, /vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at com.evernote.android.job.JobManager.<init>(JobManager.java:159)  at com.evernote.android.job.JobManager.create(JobManager.java:112)  at com.xxx.xxx.App.onCreate(App.java:20)  at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1017)  at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4858)  at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)  at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:334)  at android.app.ActivityThread.handleBindApplication(<Xposed>)  at android.app.ActivityThread.access$1500(ActivityThread.java:178)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531)  at android.os.Handler.dispatchMessage(Handler.java:111)  at android.os.Looper.loop(Looper.java:194)  at android.app.ActivityThread.main(ActivityThread.java:5637)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)  at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)  Suppressed: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/app/JobIntentService; at dalvik.system.DexFile.defineClassNative(Native Method) at dalvik.system.DexFile.defineClass(DexFile.java:226) at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219) at dalvik.system.DexPathList.findClass(DexPathList.java:321) at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54) ... 20 more Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.JobIntentService" on path: DexPathList[[zip file "/data/app/com.xxx.xxx-2/base.apk"],nativeLibraryDirectories=[/data/app/com.xxx.xxx-2/lib/arm64, /vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) ... 25 more Suppressed: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.JobIntentService" on path: DexPathList[[dex file "/data/dalvik-cache/xposed_XResourcesSuperClass.dex"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 26 more Suppressed: java.lang.ClassNotFoundException: android.support.v4.app.JobIntentService at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 27 more Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.evernote.android.job.JobRescheduleService" on path: DexPathList[[dex file "/data/dalvik-cache/xposed_XResourcesSuperClass.dex"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoa.....

    needs info 
    opened by thisismohitgupta 20
  • Multiple executions of the job

    Multiple executions of the job

    A user has reported a strange issue where a single PERIODIC job is executing at a very high frequency (as you can see from the log sample below. The version of Android-job matching the log below is the latest v1.2.1-SNAPSHOT. I have given the user a version of the app to test that uses v1.2.0 to see if the problem persists. I will provide more details to this issue as the user completes the testing steps over the next few days. In the meantime, is you see anything wrong in my code block below, let me know.

    One recent change that may be the cause is the adding of the 'syncronized' to the onRunJob() method. I amso have a syncronized() in the updateWeather() method - maybe that is redundant now? Thoughts or suggestions?

    The code snippet where the log statement comes from the WeatherUpdateJob class that implements Job.

    protected synchronized Result onRunJob(Params params) {
        if (DebugFlags.WEATHER_DEBUG) {
            Log.d(TAG, "Running weather update task " + params.getTag());
        }
        switch (params.getTag()) {
            case JOB_TAG_MANUAL:
                return updateWeather(true);
            case JOB_TAG_PERIODIC:
                return updateWeather(false);
        }
    
        return Result.FAILURE;
    }
    
    private Result updateWeather(boolean manual) {
        // The job scheduler runs our update jobs in separate threads each, but we don't
        // want to run multiple updates at once, as we only store one result anyway. One
        // specific case where this can happen is periodic update encountering an outdated
        // location, thus triggering the location listener, which in turn schedules a manual
        // update. If the location is acquired fast enough, the manual update starts before
        // the periodic update is finished.
        synchronized (WeatherUpdateJob.class) {
            return updateWeatherLocked(manual);
        }
    }
    
    private Result updateWeatherLocked(boolean manual) {
        // The job does all its work here and when done returns success
        Log.i(TAG, "Weather update successful");
        return Result.SUCCESS;
    }
    

    Snippet from the log:

    10-25 16:19:16.307 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:17.186 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:18.082 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:18.976 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:19.830 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:20.730 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:21.605 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:22.430 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:23.279 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:24.169 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:25.131 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:25.996 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:26.959 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:27.876 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:28.646 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:29.533 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:30.381 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:31.427 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:32.344 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:33.212 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:34.152 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:35.047 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:35.856 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:36.786 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:37.623 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:38.823 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:39.636 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:40.499 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:41.342 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:42.256 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:43.071 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:43.871 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:44.739 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:45.551 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:46.399 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:47.261 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:48.156 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:49.918 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:50.753 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:51.561 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:52.454 I/WeatherUpdateJob(26812): Weather update successful 10-25 16:19:56.267 I/WeatherUpdateJob(26812): Weather update successful

    question needs info 
    opened by DvTonder 19
  • Behaviour when system time changes

    Behaviour when system time changes

    I am a little bit confused about why you are internally using AlarmManager.RTC instead of AlarmManager.ELAPSED_REALTIME. If am setting a job to be run in 1 min and the system time changes inbetween, than the job will run immediatly or even too late (depending on how the time changes), although this is not the expected behaviour if the wall clock time is irrelevant for the job.

    Is this really intended?

    enhancement 
    opened by misrakli 19
  • Add missing pending intent immutable flag in JobProxy14.java

    Add missing pending intent immutable flag in JobProxy14.java

    This fixes #600 #602 #604 . 1.4.3 was released which supports Android S. The published version didn't have the same changes made to JobProxy14.java. I have made the same changes to JobProxy14.java. Please let me know if you need any more info on this

    opened by RationalRank 0
  • Cancel Job is throwing exception in logs as mutability is not defined for PendingIntent on API 32

    Cancel Job is throwing exception in logs as mutability is not defined for PendingIntent on API 32

    E/JobProxy14: cancel() called with a null PendingIntent java.lang.NullPointerException: cancel() called with a null PendingIntent at android.app.AlarmManager.cancel(AlarmManager.java:1193) at com.evernote.android.job.v14.JobProxy14.cancel(JobProxy14.java:164) at com.evernote.android.job.JobProxy$Common.cleanUpOrphanedJob(JobProxy.java:285) at com.evernote.android.job.JobManager.schedule(JobManager.java:188) at com.evernote.android.job.JobRequest.schedule(JobRequest.java:430) at com.evernote.android.job.JobRequest$2.run(JobRequest.java:459) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920)

    When I check

    protected int createPendingIntentFlags(boolean repeating) { int flags = PendingIntent.FLAG_UPDATE_CURRENT; if (!repeating) { flags |= PendingIntent.FLAG_ONE_SHOT; } return flags; }

    In JobProxy14.java its missing mutability flag can you please add this one?

    opened by vipul-d 2
  • Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent

    Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent

    When I want to schedule exact alarm it gives me this error:

    Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

    I have in dependencies:

    implementation "androidx.work:work-runtime-ktx:2.7.1"
    implementation 'com.evernote:android-job:1.4.3'
    implementation 'android.arch.work:work-runtime:1.0.1'
    

    But in log it keeps crashing. How can this behaviour be resolved?

    opened by simondorociak 0
  • Adapt WakeLockUtil for Android Oreo background restriction, fixing crash issue #592.

    Adapt WakeLockUtil for Android Oreo background restriction, fixing crash issue #592.

    Adapt WakeLockUtil for Android Oreo background restriction, fixing crash issue #592

    Background: We observed a crash on Android 8.x, 9, and 10 devices that happens ~300 times a day as follows:

    05-20 21:35:07.364 E/AndroidRuntime(25087): FATAL EXCEPTION: main
    05-20 21:35:07.364 E/AndroidRuntime(25087): Process: com.microsoft.office.outlook, PID: 25087
    05-20 21:35:07.364 E/AndroidRuntime(25087): java.lang.RuntimeException: Unable to start receiver com.evernote.android.job.v14.PlatformAlarmReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.microsoft.office.outlook/com.evernote.android.job.v14.PlatformAlarmServiceExact (has extras) }: app is in background uid UidRecord{af197af u0a213 RCVR idle change:uncached procs:1 proclist:25087, seq(0,0,0)}
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:3612)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ActivityThread.access$1300(ActivityThread.java:237)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1796)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.os.Handler.dispatchMessage(Handler.java:106)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.os.Looper.loop(Looper.java:214)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ActivityThread.main(ActivityThread.java:7050)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at java.lang.reflect.Method.invoke(Native Method)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
    05-20 21:35:07.364 E/AndroidRuntime(25087): Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.microsoft.office.outlook/com.evernote.android.job.v14.PlatformAlarmServiceExact (has extras) }: app is in background uid UidRecord{af197af u0a213 RCVR idle change:uncached procs:1 proclist:25087, seq(0,0,0)}
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1666)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ContextImpl.startService(ContextImpl.java:1611)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.content.ContextWrapper.startService(ContextWrapper.java:677)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.content.ContextWrapper.startService(ContextWrapper.java:677)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.evernote.android.job.WakeLockUtil.a(SourceFile:109)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.evernote.android.job.JobProxy$Common.startWakefulService(SourceFile:297)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.evernote.android.job.v14.PlatformAlarmReceiver.onMAMReceive(SourceFile:51)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at com.microsoft.intune.mam.client.content.MAMBroadcastReceiver.onReceive(SourceFile:31)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:3603)
    05-20 21:35:07.364 E/AndroidRuntime(25087): 	... 8 more
    

    We have several exact job configurations that are set using startNow() or setExact(long) API. Behind these 2 APIs, it sets the JobRequest.Builder#mExact to true. If the JobRequest.Builder.mExact is true, the JobRequest#getJobApi method will return a hard-coded JobApi#V_14 even if we're running on a Android 8+ device.

        /*package*/ JobApi getJobApi() {
            return mBuilder.mExact ? JobApi.V_14 : JobApi.getDefault(context());
        }
    

    The WakeLockUtil#startWakefulService(Context, Intent) method used from com.evernote.android.job.v14.* is problematic in Android 8+ devices in terms of the background restriction introduced in Android Oreo and is deprecated by the original Android support library WakefulBroadcastReceiver.

    Note that we can't use JobIntentService which is recommended by the Android team as a replacement. The JobIntentServiceutilizes JobScheduler for Android 8.0+, which can not be accurate / exact in terms of the execution time.

    The idea of this change is to start the job immediately without using Service if the Service failed to start (with handling the WakeLock stuff gracefully).

    Code changes: 1, WakeLockUtil.startWakefulPlatformAlarmServiceExact() isn't a general purpose method any more; Verification logic is added to make it be able to start PlatformAlarmServiceExact only;

    2, Gracefully handle the IllegalStateException thrown by the Android 8.0+ OS; In this case we just fallback to run job directly without using a Service;

    3, Removed 2 bridge methods in JobProxy.Common since they seemed not that much meaningful;

    4, Fix the demo app crash issue for Android 8.1 & 10 testing device by removing the StrictMode settings;

    Testing: I tried hard but can't find a way to trigger / simulate the background restriction, but we know that when we hit the background restriction, an IllegalStateException will be thrown according to the javadocs.

         * @throws IllegalStateException If the application is in a state where the service
         * can not be started (such as not in the foreground in a state when services are allowed).
         */
        @Nullable
        public abstract ComponentName startService(Intent service);
    

    So here's my manual testing steps: 1, Modify the source code of WakeLockUtil to make the service start always failed;

        private static void startPlatformAlarmServiceExactCompat(Context context, Intent intent) {
            boolean success;
            try {
                // success = context.startService(intent) != null;
                throw new IllegalStateException();
            } catch (IllegalStateException e) {
                success = false;
            }
            if (success) {
                return;
            }
            PlatformAlarmServiceExact.runJobWithoutUsingService(context, intent);
        }
    

    2, Run the demo app, then click the Exact button; 3, Wait for 10 seconds and see if there's a notification shown up; 4, Verify the WakeLock is released by adb shell dumpsys power;

    opened by xingda920813 2
  • WakeLockUtil.startWakefulService crash with IllegalStateException

    WakeLockUtil.startWakefulService crash with IllegalStateException

    Before starting, this is surely related to #572

    we still have this bug in android 8 and 9.

    the problem is with .startService(intent) in WakeLockUtil.java#L111

    looking to this thread in stackoverflow, we might solve it.

    try {
        context.startService(intent)
    }
    catch (ex: IllegalStateException) {
        intent.putExtra(NEED_FOREGROUND_KEY, true)
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        }
        else {
            context.startService(intent)
        }
    }
    

    but we have to take care of ANR like described here :

    Prior to Android 8.0, the usual way to create a foreground service was to create a background service, then promote that service to the foreground. With Android 8.0, there is a complication; the system doesn't allow a background app to create a background service. For this reason, Android 8.0 introduces the new method startForegroundService() to start a new service in the foreground. After the system has created the service, the app has five seconds to call the service's startForeground() method to show the new service's user-visible notification. If the app does not call startForeground() within the time limit, the system stops the service and declares the app to be ANR.

    i have tried applying it, but i failed to apply startForeground().

    is there someone that could help with it?

    @Owners, please don't close this issue till we find a solution to it. it's really a disturbing bug, causing many problems in prod.
    Thanks.

    opened by chlegou 0
Releases(v1.4.2)
  • v1.4.2(Oct 9, 2019)

  • v1.4.1(Sep 30, 2019)

  • v1.4.0(Sep 29, 2019)

  • v1.3.0(Sep 29, 2019)

    • (No changes compared to 1.3.0-rc1)
    • Implement an API that uses the WorkManager for scheduling work items
    • Initialize the job storage on a background thread, see #471
    • Restrict usage of internal classes for internal usage only, see #465
    • Use a JobIntentService implementation that doesn't crash, see #255
    • Offset the end time when rescheduling an inexact job, see #547
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0-rc1(Mar 22, 2019)

  • v1.3.0-alpha09(Nov 18, 2018)

  • v1.3.0-alpha08(Oct 21, 2018)

  • v1.3.0-alpha07(Sep 24, 2018)

  • v1.3.0-alpha06(Jul 25, 2018)

  • v1.3.0-alpha05(Jul 23, 2018)

  • v1.3.0-alpha04(Jul 21, 2018)

    1.3.0-alpha04 (2018-07-20)

    • Fix rare NPE when WorkManager is null for some reason, see #477
    • Fix rare NPE when JobStorage is null, see #492
    • Fix class loading error for the GCM API, see #487
    • Use a JobIntentService implementation that doesn't crash, see #255
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0-alpha03(Jun 11, 2018)

  • v1.3.0-alpha02(Jun 10, 2018)

    • Initialize the job storage on a background thread, see #471
    • Restrict usage of internal classes for internal usage only, see #465
    • Add a workaround for the internal crash in JobIntentService, see #255
    • Fix RuntimeException with WorkManager, see #464
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0-alpha01(May 29, 2018)

  • v1.2.6(May 28, 2018)

    • Make the license in Java files clearer, see #422
    • Use own internal monitor for synchronizing access to variables in order to avoid deadlocks when using the library, see #414
    • Cleanup jobs in the database if no job creator returns an instance during execution, see #413
    • Make sure that the JobManager is created when canceling jobs, see #442
    • Don't crash on Android 4.X with the recent Google Play Services, see #415
    • Explain the relation to WorkManager, see here
    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Mar 19, 2018)

    • Handle platform bug where querying the network state throws an NPE internally, see #380
    • Fix database access on main thread, see #385
    • Fix misleading log message for some internal improvements, see #391
    • Fix race condition when scheduling a job with setUpdateCurrent(true) where multiple jobs could have been scheduled, see #396
    • Fix bug where a daily job runs twice a day, see #406
    • Fix a bug where periodic jobs in the flex support mode weren't properly canceled while the job was running, see #407
    Source code(tar.gz)
    Source code(zip)
  • v1.2.4(Feb 8, 2018)

  • v1.2.3(Feb 7, 2018)

    • Add an onCancel() method to get notified when the job is canceled, see #359
    • Expose the meetsRequirements() method to have the option to check all requirements manually, see #349
    • Don't close the database automatically after each interaction, but give an option in the JobConfig class to revert this behavior, see #344
    • Add scheduleAsync() for scheduling jobs asynchronously to avoid IO operations on the main thread
    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Jan 13, 2018)

    • Use only the support-compat instead of the full support-v4 library, see #326
    • Use a ReadWriteLock for synchronizing the database reads and writes, see #344
    • Update the last run time for daily jobs, see #332
    • Shift the max execution delay if the requirements are enforced, see #325
    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Nov 23, 2017)

    • Add option to override the default background executor, see #292
    • Don't keep a strong reference to finished jobs to allow freeing memory, see #299
    • Allow running a daily job immediately once, this is helpful for testing purposes, see #317
    • Allow enforcing requirements for daily jobs, see #313
    • Remove the Cat dependency for logging, see 295
    • Add @NonNull annotation to param parameter, see #321 (thanks for the contribution @Jawnnypoo)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 6, 2017)

    • Extract JobManager.Config class into JobConfig class to make it possible to change settings before the JobManager is created
    • Add an option to disable any specific API and not just the GCM API (only useful for testing purposes)
    • Remove deprecated methods
    • Add the startNow() method to run a job immediately respecting all constraints in Android O
    • Remove the persisted parameter, which didn't work reliable, all jobs are persisted anyway
    • Remove startWakefulService from the Job class, WakefulBroadcastReceiver is now deprecated with JobIntentService as the better option
    • Add feature to make jobs transient and to add a Bundle, see setTransientExtras(bundle)
    • Add new METERED network type
    • Add new requirements battery not low and storage not low
    • Add helper job class DailyJob to make it easier to run jobs once a day, see #223
    • Add option in JobConfig to add a logger
    • Add option in JobConfig for a job ID offset to avoid clashes with other jobs in the JobScheduler
    • Switch to elapsed real time with the AlarmManager to have a consistent behavior with the JobScheduler, see #237

    (Requires target SDK 26)

    Source code(tar.gz)
    Source code(zip)
  • v1.1.12(Oct 6, 2017)

    • Handle NPE inside of JobScheduler
    • Handle 'Package manager has died' crash
    • Save the highest job ID in a pref file so that it isn't lost when no job is in the database anymore (makes debugging easier)
    • Fix rare NPE when rescheduling jobs after service has been restarted, see #234
    • Fix rescheduled periodic job although it has been canceled pre Android N, see #241
    Source code(tar.gz)
    Source code(zip)
  • v1.1.11(Jun 5, 2017)

    • Fix a race condition when canceling jobs, see #178
    • Disable the JobScheduler API if the service is disabled, see #190
    • Fix SQLiteConstraintException when rescheduling jobs, because job is already present in the database, see #176
    • Improve job result documentation, see #192
    • Prevent app ending in a crash loop, see #194
    • Fallback to an older API if the JobScheduler is null on the device
    • Don't persist jobs with the JobScheduler, if this device is weird and doesn't have the boot permission
    • List support-v4 as dependency, because it's required, see #200
    • Make Job.Params public for better test support, see #201
    • Allow to suppress the JobManagerCreateException, see JobApi.setForceAllowApi14(boolean)
    • Make SimpleDateFormat thread-local to avoid possible crash, see #208
    Source code(tar.gz)
    Source code(zip)
  • v1.1.10(Apr 29, 2017)

    • Fix a race condition when canceling jobs, see #178
    • Make it possible to reuse builder objects, this may fix SQL exceptions, see #176
    • Add JobRequest.getLastRun() returning the time when the job did run the last time, if it was rescheduled or it's a periodic job, see #141
    • Fix crash on Android 4.0.3 where SQLiteDatabase doesn't implement Closable, see #182
    • Updating wording for network type ANY to make it clearer that no specific network state is required, see #185
    • Use a copy of the platform DefaultDatabaseErrorHandler. Some manufacturers replace this causing stack overflows, see #184
    Source code(tar.gz)
    Source code(zip)
  • v1.1.9(Apr 10, 2017)

    • Improve logging by providing an option to add a custom logger
    • Fix crash when rescheduling jobs, see #164
    • Fix wrong returned network type, see #166
    • Expose failure count in the JobRequest class, see #168
    • Don't silently eat JobScheduler's limit exception
    • Make schedule() method idempotent
    • Add a fallback if removing a job from the database fails for some reason, see #145
    Source code(tar.gz)
    Source code(zip)
  • v1.1.8(Mar 23, 2017)

    • Catch wake lock crashes in all cases, fixes #153
    • Use a better execution in parallel with the AlarmManager. This may prevent a process death.
    • Use better thread names
    • List for quick boot completed broad casts, see #157
    Source code(tar.gz)
    Source code(zip)
  • v1.1.7(Feb 27, 2017)

  • v1.1.6(Feb 13, 2017)

  • v1.1.5(Jan 25, 2017)

  • v1.1.4(Jan 5, 2017)

A simple Android app to demonstrate the use of Hover SDK for M-PESA Send Money while offline. This SDK does not require an internet connection, it automates USSD sessions in the background of an android application.

HoverSDKDemo Hover SDK is an Android SDK that lets mobile developers to add money features to the applications. This SDK does not require an internet

Joel Kanyi 9 Dec 21, 2022
The easiest way to create a dashed or striped background on Android 🐝

DashedView The easiest way to create a dashed or striped background on Android The DashedView library allows you to create views with a dashed (or str

null 59 Oct 3, 2022
PDFER - App demo that uses WorkManager API to download and schedule PDFs in the background

PDFER App demo that uses WorkManager API to download and schedule PDFs in the background Download PDF You can either download custom pdf files by plac

Ahmed Samir 4 Nov 22, 2022
An App based on MVVM architecture to track & store a user's runs using Google Maps, with options to view & sort the runs as per the user's choice along the with option to run the app in background.

An App based on MVVM architecture to track & store a user's runs using Google Maps, with options to view & sort the runs as per the user's choice along the with option to run the app in background.

Harshit Maheshwari 1 Jun 9, 2022
Show worldwide headline. API/Glide library/recycler view/volley library/kotlin/xml/ chrome custom tabs

Show worldwide headline. API/Glide library/recycler view/volley library/kotlin/xml/ chrome custom tabs. -> you can click on headline and it will open an article of that news in the app(no need to go to chrome or any browser)

SUMIT KUMAR 5 Nov 28, 2022
A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library.

Expo Music Picker A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library. Supp

Bartłomiej Klocek 60 Dec 29, 2022
:movie_camera: Movie discovery app showcasing Android best practices with Google's recommended architecture: MVVM + Repository + Offline support + Android Architecture Components + Paging library & Retrofit2.

Popular Movies Stage 1 + Stage 2 Discover the most popular and top rated movies playing. Movies data fetched using themoviedb.org API. ✨ Screenshots M

Yassin AJDI 189 Nov 26, 2022
Oratio Library for Android Studio helps you simplify your Android TTS codes

Oratio Oratio is a library for Android Studio. This library is useful to a number of developers who are currently making apps using android TTS(Text-T

Jacob Lim 1 Oct 28, 2021
Unity-Android-SDK-Plugins - Android SDK/Library/Plugins (aar) for Unity Developers

Unity Android SDK Plugins Unity Android SDK Plugins is an Open Source project th

NNK 1 Aug 14, 2022
Spantastic - an Android library that provides a simple and Kotlin fluent API for creating Android Spannable

Spantastic is an Android library that provides a simple and Kotlin fluent API for creating Android Spannable. This library wrappers SpannableStringBuilder and add methods to easily decorate the text with multiple spans.

Wellington Cabral da Silva 12 Nov 27, 2022
AndroidEssentials is an android library that creates helper functions for performing common tasks in Android

AndroidEssentials is an android library that creates helper functions for performing common tasks in Android such as managing preferences, managing files, showing alerts, showing toasts, checking user country & checking network connection of users. All the methods of the class are static and should be accessed directly from the AndroidEssentials class.

Isaac Sichangi 3 Jul 7, 2022
Utility Android app for generating color palettes of images using the Palette library. Written in Kotlin.

Palette Helper is a simple utility app made to generate color palettes of images using Google's fantastic Palette library. It's mostly a for-fun pet p

Zac Sweers 154 Nov 18, 2022
Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information about Marvel's vast library of comics. :zap:

Villains & Heroes Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information

André Mion 53 Jul 13, 2022
Library to change Android launcher App Icon and App Name programmatically !

AppIconNameChanger Change Android App launcher Icon and App Name programmatically ! Download Demo APK from HERE Kindly use the following links to use

Prabhakar Thota 587 Dec 29, 2022
📱 Android Library to implement Rich, Beautiful, Stylish 😍 Material Navigation View for your project with Material Design Guidelines. Easy to use.

Material NavigationView for Android ?? ?? Android Library to implement Rich, Beautiful Material Navigation View for your project with Material Design

Shreyas Patil 198 Dec 17, 2022
Utility Android app for generating color palettes of images using the Palette library. Written in Kotlin.

Palette Helper is a simple utility app made to generate color palettes of images using Google's fantastic Palette library. It's mostly a for-fun pet p

Zac Sweers 154 Nov 18, 2022
📱 AppListManager (Android Library) makes managing application and activity lists easy.

AppListManager (Android Library) AppListManager is easy to use Android library, which minimizes developing time when working on application or activit

Rokas Jankunas 60 Dec 27, 2022
An library to help android developers working easly with activities and fragments (Kotlin version)

AFM An library to help android developer working easly with activities and fragments (Kotlin) Motivation Accelerate the process and abstract the logic

Massive Disaster 12 Oct 3, 2022