A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.

Overview

This Project is Deprecated!

Thanks to everybody who've used Android Priority JobQueue. It was designed in a world where there was no JobScheduler, RxJava was not popular and Kotlin wasn't even born publicly.

Today, most of the learnings in this project are part of WorkManager, the official deferred task library for Android. I've been involved in its development and I think it is the right way to do deferred tasks on Android.

For your persistent jobs, I recommend using WorkManager. For your non-persistent jobs, drink the kool aid and use Coroutines.

Thanks.

V2 is here!

There is a major internal rewrite of this project for more stability and new features. If you were using v1, see the migration guide here: migration from v1 to v2

dependencies {
    compile 'com.birbit:android-priority-jobqueue:2.0.1'
}

Master Build Status

CircleCI codecov

Android Priority Job Queue (Job Manager)

Priority Job Queue is an implementation of a Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.

It is written primarily with flexibility & functionality in mind. This is an ongoing project, which we will continue to add stability and performance improvements.

Why ?

The Problem

Almost every application does work in a background thread. These "background tasks" are expected to keep the application responsive and robust, especially during unfavorable situations (e.g. limited network connectivity). In Android applications, there are several ways to implement background work:

  • Async Task: Using an async task is the simplest approach, but it is tightly coupled with the activity lifecycle. If the activity dies (or is re-created), any ongoing async task will become wasted cycles or otherwise create unexpected behavior upon returning to the main thread. In addition, it is a terrible idea to drop a response from a network request just because a user rotated his/her phone.
  • Loaders: Loaders are a better option, as they recover themselves after a configuration change. On the other hand, they are designed to load data from disk and are not well suited for long-running network requests.
  • Service with a Thread Pool: Using a service is a much better solution, as it de-couples business logic from your UI. However, you will need a thread pool (e.g. ThreadPoolExecutor) to process requests in parallel, broadcast events to update the UI, and write additional code to persist queued requests to disk. As your application grows, the number of background operations grows, which force you to consider task prioritization and often-complicated concurrency problems.

Our Solution

Job Queue provides you a nice framework to do all of the above and more. You define your background tasks as Jobs and enqueue them to your JobManager instance. Job Manager will take care of prioritization, persistence, load balancing, delaying, network control, grouping etc. It also provides a nice lifecycle for your jobs to provide a better, consistent user experience.

Although not required, it is most useful when used with an event bus. It also supports dependency injection.

Show me the code

Since a code example is worth thousands of documentation pages, here it is.

File: PostTweetJob.java

// A job to send a tweet
public class PostTweetJob extends Job {
    public static final int PRIORITY = 1;
    private String text;
    public PostTweetJob(String text) {
        // This job requires network connectivity,
        // and should be persisted in case the application exits before job is completed.
        super(new Params(PRIORITY).requireNetwork().persist());
    }
    @Override
    public void onAdded() {
        // Job has been saved to disk.
        // This is a good place to dispatch a UI event to indicate the job will eventually run.
        // In this example, it would be good to update the UI with the newly posted tweet.
    }
    @Override
    public void onRun() throws Throwable {
        // Job logic goes here. In this example, the network call to post to Twitter is done here.
        // All work done here should be synchronous, a job is removed from the queue once 
        // onRun() finishes.
        webservice.postTweet(text);
    }
    @Override
    protected RetryConstraint shouldReRunOnThrowable(Throwable throwable, int runCount,
            int maxRunCount) {
        // An error occurred in onRun.
        // Return value determines whether this job should retry or cancel. You can further
        // specify a backoff strategy or change the job's priority. You can also apply the
        // delay to the whole group to preserve jobs' running order.
        return RetryConstraint.createExponentialBackoff(runCount, 1000);
    }
    @Override
    protected void onCancel(@CancelReason int cancelReason, @Nullable Throwable throwable) {
        // Job has exceeded retry attempts or shouldReRunOnThrowable() has decided to cancel.
    }
}

File: TweetActivity.java

//...
public void onSendClick() {
    final String status = editText.getText().toString();
    if(status.trim().length() > 0) {
      jobManager.addJobInBackground(new PostTweetJob(status));
      editText.setText("");
    }
}
...

That's it. :) Job Manager allows you to enjoy:

  • No network calls in activity-bound async tasks
  • No serialization mess for important requests
  • No "manual" implementation of network connectivity checks or retry logic

Priority Job Queue vs Job Scheduler vs GCMNetworkManager vs ?

On Lollipop, Android introduced JobScheduler which is a system friendly way to run non-time-critical tasks. It makes your code cleaner, makes your app a good citizen of the ecosystem and it is backported via GCMNetworkManager.

The first version of Job Queue was created approximately 2 years before Job Scheduler. The major difference is that Job Queue is designed to run all of your background tasks while Job Scheduler is designed only for those you can defer.

We've created Job Queue because we wanted to have more control over the non-ui-thread activity of our application. We needed a convenient way to prioritize them, persist them accross application restarts and group based on the resources they access.

A good practice of using Job Queue is to write all of your network tasks as Jobs and use AsyncTasks for disk access (e.g. loading data from sqlite). If you have long running background operations (e.g. processing an image), it is also a good practice to use Job Queue.

Starting with v2, Job Queue can be integrated with JobScheduler or GCMNetworkManager. This integration allows Job Queue to wake up the aplication based on the criterias of the Jobs it has. You can see the details on the related wiki page. The Scheduler API is flexible such that you can implement a custom version of it if your target market does not have Google Play Services.

Under the hood

  • When user clicked the send button, onSendClick() was called, which creates a PostTweetJob and adds it to Job Queue for execution. It runs on a background thread because Job Queue will make a disk access to persist the job.

  • Right after PostTweetJob is synchronized to disk, Job Queue calls DependencyInjector (if provided) which will inject fields into our job instance. At PostTweetJob.onAdded() callback, we saved PostTweetJob to disk. Since there has been no network access up to this point, the time between clicking the send button and reaching onAdded() is within fractions of a second. This allows the implementation of onAdded() to inform UI to display the newly sent tweet almost instantly, creating a "fast" user experience. In V1, onAdded() is called on the thread job was added. In V2, onAdded() is called in JobManager's own thread.

  • When it's time for PostTweetJob to run, Job Queue will call onRun() (and it will only be called if there is an active network connection, as dictated at the job's constructor). By default, Job Queue uses a simple connection utility that checks ConnectivityManager (ensure you have ACCESS_NETWORK_STATE permission in your manifest). You can provide a custom implementation which can add additional checks (e.g. your server stability). You should also provide a NetworkUtil which can notify Job Queue when network is recovered so that Job Queue will avoid a busy loop and decrease # of consumers(default configuration does it for you).

  • Job Queue will keep calling onRun() until it succeeds (or reaches a retry limit). If onRun() throws an exception, Job Queue will call shouldReRunOnThrowable() to allow you to handle the exception and decide whether to retry job execution or abort.

  • If all retry attempts fail (or when shouldReRunOnThrowable() returns false), Job Queue will call onCancel() to allow you to clean your database, inform the user, etc.

Advantages

  • It is very easy to de-couple application logic from your activities, making your code more robust, easy to refactor, and easy to test.
  • You don't have to deal with AsyncTask lifecycles. This is true assuming you use an event bus to update your UI (you should). At Path, we use greenrobot's EventBus; however, you can also go with your favorite. (e.g. [Square's Otto] (https://github.com/square/otto))
  • Job Queue takes care of prioritizing jobs, checking network connection, running them in parallel, etc. Job prioritization is especially indispensable when you have a resource-heavy app like ours.
  • You can delay jobs. This is helpful in cases like sending a GCM token to your server. It is very common to acquire a GCM token and send it to your server when a user logs in to your app, but you don't want it to interfere with critical network operations (e.g. fetching user-facing content).
  • You can group jobs to ensure their serial execution, if necessary. For example, assume you have a messaging client and your user sent a bunch of messages when their phone had no network coverage. When creating these SendMessageToNetwork jobs, you can group them by conversation ID. Through this approach, messages in the same conversation will send in the order they were enqueued, while messages between different conversations are still sent in parallel. This lets you effortlessly maximize network utilization and ensure data integrity.
  • By default, Job Queue monitors network connectivity (so you don't need to worry about it). When a device is operating offline, jobs that require the network won't run until connectivity is restored. You can even provide a custom NetworkUtil if you need custom logic (e.g. you can create another instance of Job Queue which runs only if there is a wireless connection).
  • It is unit tested and mostly documented. You can check our code coverage report and Javadoc.

Getting Started

We distribute artifacts through maven central repository.

AndroidX Version

Gradle: compile 'com.birbit:android-priority-jobqueue:3.0.0' Maven:

<dependency>
    <groupId>com.birbit</groupId>
    <artifactId>android-priority-jobqueue</artifactId>
    <version>3.0.0</version>
</dependency>

Android Support Version

Gradle: compile 'com.birbit:android-priority-jobqueue:2.0.1' Maven:

<dependency>
    <groupId>com.birbit</groupId>
    <artifactId>android-priority-jobqueue</artifactId>
    <version>2.0.1</version>
</dependency>

You can also download library jar, sources and Javadoc from Maven Central.

We highly recommend checking how you can configure job manager and individual jobs.

Version History

  • 3.0.0 (Jan 20, 2020)
  • Updated to AndroidX dependencies
  • 2.0.1 (Oct 11, 2016)
  • Fixed high CPU usage if queues are full (#262)
  • Handle bad input from job schedulers (#254)
  • 2.0.0 (Aug 14, 2016)
  • Validate JobManager ids
  • 2.0.0-beta3 (Aug 7, 2016)
  • Minor improvements in GCMNetworkManager
  • 2.0.0-beta2 (July 25, 2016)
  • Fixed a bug about cancelling persistent jobs (#212)
  • Fixed a cursor leak in the persistent queue (#206)
  • Added custom duration to the BatchingScheduler (#202)
  • 2.0.0-beta1 (June 27, 2016)
  • Commitment to the final 2.0 API and backward compatibility
  • Fixed a bug where cancel reason was not passed to onCancel if Job decides not to try again
  • 2.0.0-alpha5 (June 21, 2016)
  • Important fix with Framework Scheduler where it was not setting delay properly
  • 2.0.0-alpha4 (June 16, 2016) - Last planned alpha release (with api changes)
  • Introduced deadline parameter. Job will be run (or cancelled) when it hits the deadline regardless of its constraints.
  • Made it easier to write custom serializer by making base job fully transient.
  • Moved persistent job data to individual files which will lift the limit on the job size.
  • If Job serialization fails, JobManager will throw an exception.
  • 2.0.0-alpha3 (May 28, 2016)
  • New onCancel API receives the exception
  • Changed how schedulers are constructed to avoid NPE issues
  • New ThreadPool configuration to allow custom thread creation for consumers
  • 2.0.0-alpha1 (March 26, 2016)
  • A major rewrite with 70+ commits
  • Migration guide
  • 1.3.5 (Nov 7, 2015)
  • Default NetworkUtil is now Doze aware. (thanks @coltin)
  • RetryConstraint Delay can be applied to the group to preserve jobs' execution order. (#41)
  • 1.3.4 (Sept 12, 2015)
  • Fixed a potential ANR that was caused by sync on main thread. Issue #40
  • 1.3.3 (July 12, 2015)
  • Fixed default exponential backoff. Issue #33
  • 1.3.2 (July 5, 2015)
  • Added ability to change a Job's priority or add delay before it is retried. This mechanism can be used to add exponential backoff to jobs.
  • Added Job#getApplicationContext as a convenience method to get the Context inside a Job.
  • 1.3.1 (April 19, 2015)
  • Fixed issue #19 which was blocking a group forever if a job from that group is cancelled while running and then onRun fails.
  • Updated Robolectric version and moved all testing to Gradle.
  • Goodbye Cobertura, Welcome Jacoco!
  • 1.3 (March 23, 2015)
  • Ability to add tags to jobs. These tags can be used to later retrieve jobs.
  • Added long awaited job cancellation. You can use tags to cancel jobs.
  • Removed deprecated BaseJob class. This may break backward compatibility.
  • 1.1.2 (Feb 18, 2014)
  • Report exceptions to logger if addInBackground fails. (#31)
  • 1.1.1 (Feb 8, 2014)
  • Fixed an important bug (#35) where jobs in the same group may run in parallel if many of them become available at the same time while multiple consumer threads are waiting for a new job.
  • 1.1 (Jan 30, 2014)
  • Job Status query API (#18)
  • Fixed a stackoverflow bug when network status changes after a long time. (#21)
  • 1.0 (Jan 14, 2014):
  • Added parameterized constructor for Job for more readable code.
  • Deprecated BaseJob in favor of a more complete Job class.
  • 0.9.9 (Dec 16, 2013):
  • First public release.

Wiki

Dependencies

Building

  • Clone the repo
  • > cd jobqueue
  • > ./gradlew clean assembleDebug assembleDebugUnitTest test

This will create a jar file under release folder.

Running Tests

  • cd jobqueue

  • ./gradlew clean check

License

Android Priority Jobqueue is made available under the MIT license:

The MIT License (MIT)

Copyright (c) 2013 Path, Inc.
Copyright (c) 2014 Google, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Comments
  • JobQueue went crazy on some device.

    JobQueue went crazy on some device.

    Hi,

    Thanks for the awesome library.

    I have one problem on the JobQueue on a specific device. JobQueue went crazy and resulting in the phone to crash and restart. I've tested with 5 phones, and the one that's having this problem is OnePlus One on CM13.1s.

    Attached trimmed log

    When I count the log, there's 3,000 lines printed in a space of 1s.

    I've created a test repo here. test repo

    Any advice?

    bug 
    opened by malvinstn 18
  • IllegalStateException : Couldn't read row 0, col 0 from CursorWindow

    IllegalStateException : Couldn't read row 0, col 0 from CursorWindow

    From @AndroidDeveloperLB on February 17, 2015 15:21

    I got this weird exception, which I can't even find its cause because the library got obfuscated:

    java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. at android.database.CursorWindow.nativeGetLong(CursorWindow.java) at android.database.CursorWindow.getLong(CursorWindow.java:511) at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220) at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245) at com.path.android.jobqueue.h.a.d.b(SqliteJobQueue.java:201) at com.path.android.jobqueue.a.a.b(CachedJobQueue.java:68) at com.path.android.jobqueue.f.d(JobManager.java:273) at com.path.android.jobqueue.f.c(JobManager.java:25) at com.path.android.jobqueue.h.a(JobManager.java:412) at com.path.android.jobqueue.d.a$b.run(JobConsumerExecutor.java:198) at java.lang.Thread.run(Thread.java:841)

    Any way to find why it occurs, and how to fix it?

    Copied from original issue: path/android-priority-jobqueue#95

    opened by yigit 18
  • Persistent job runs (successfully) forever

    Persistent job runs (successfully) forever

    Hi!

    First, I observed the bug on v2 alpha2 and alpha3 (after refactoring according to changes).

    I have one important job that needs to be sent, so I made it serializable, but I'm not using the half-default (half as I saw serialization methods in the Job class) method as if I need to update the Job implementation, a job serialized on an older app version needs to be properly deserialized on a newer version.

    I implemented the SerializerProxy pattern (as seen in Effective Java, last item of the 2nd edition) to keep only the crucial information (a timestamp, and id and a boolean), and use the public constructor to ensure backward and forward compatibility.

    It seems to work as there's no error during serialization and deserialization.

    However, after adding the job once, the JobManager doesn't run it, but, after doing weird things (from my point of view, when I look at the logs), it deserializes the job, runs it, then redeserializes, and run it, and repeat, and repeat, forever, spamming the servers...

    I saw that the job is being deserialized and run in loop by JobManager after I added Thread.dumpStack() in the constructor of my Job and analyzed the Stacktrace.

    You can see the logs attached, from the user event which triggered the job creation and adding, to the point I had to kill my app to keep a trace of logs. You can clearly see that JobManager is way too chatty (afraid of performance...), and that the same job is being deserialized and run again and again.

    Logs AndroidPriorityJobQueue issue.txt

    I'll try to use my own JobSerializer, but if it doesn't work, I won't be able to use this library (that seemed awesome) as my app needs to be dogfoodly tested next week, then shipped ASAP...

    Here's the relevant code:

    The problematic job

    package net.suivideflotte.drivercompanion.jobs;
    
    import android.support.annotation.NonNull;
    
    import net.suivideflotte.drivercompanion.DriverApp;
    import net.suivideflotte.drivercompanion.event.PrivateModeEvent;
    import net.suivideflotte.drivercompanion.model.DeviceStatus;
    import net.suivideflotte.drivercompanion.model.DriverInfo;
    import net.suivideflotte.drivercompanion.model.ImportantJob;
    import net.suivideflotte.drivercompanion.model.PrivateModeSwitchRequest;
    import net.suivideflotte.drivercompanion.rest.SDF;
    
    import java.io.InvalidObjectException;
    import java.io.ObjectInputStream;
    import java.io.Serializable;
    
    import retrofit2.Call;
    import timber.log.Timber;
    
    import static net.suivideflotte.drivercompanion.model.DeviceStatus.State.PRIVATE;
    
    /**
     * @see SDF.API#switchPrivateMode(int, PrivateModeSwitchRequest)
     */
    public final class SwitchPrivateModeJob extends ApiJobWithEvent<Void, PrivateModeEvent> implements ImportantJob, Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private final int mDeviceId;
        private final PrivateModeSwitchRequest mRequest;
    
        public SwitchPrivateModeJob(boolean switchOn, int deviceId) {
            this(switchOn, deviceId, System.currentTimeMillis());
        }
    
        private SwitchPrivateModeJob(boolean switchOn, int deviceId, long time) {
            super(true, true);
            mDeviceId = deviceId;
            mRequest = new PrivateModeSwitchRequest(time, switchOn);
            Timber.i("Constructor called");
            Thread.dumpStack();
        }
    
        @NonNull
        @Override
        protected Call<Void> getCall(SDF.API api) {
            return api.switchPrivateMode(mDeviceId, mRequest);
        }
    
        @Override
        protected PrivateModeEvent getDoneEvent(Void aVoid) {
            //todo: Save the new private mode state
            if (mRequest.state) {
                DeviceStatus deviceStatus = DriverApp.getStickyEvent(DeviceStatus.class);
                if (deviceStatus != null) deviceStatus.state = PRIVATE;
            } else {
                DriverApp app = (DriverApp) getApplicationContext();
                DriverInfo driverInfo = DriverApp.getStickyEvent(DriverInfo.class);
                if (driverInfo != null) {
                    app.getJobManager().addJobInBackground(new FetchDeviceStatusJob(driverInfo.deviceId));
                }
            }
            return PrivateModeEvent.STATE_CHANGED;
        }
    
        private static final class SerializationProxy implements Serializable {
    
            private static final long serialVersionUID = 1L;
            private final int deviceId;
            private final boolean switchOn;
            private final long time;
    
            public SerializationProxy(SwitchPrivateModeJob job) {
                deviceId = job.mDeviceId;
                switchOn = job.mRequest.state;
                time = job.mRequest.at.getTime();
            }
    
            private Object readResolve() {
                return new SwitchPrivateModeJob(switchOn, deviceId, time);
            }
        }
    
        private Object writeReplace() {
            return new SerializationProxy(this);
        }
    
        private void readObject(ObjectInputStream stream) throws InvalidObjectException {
            throw new InvalidObjectException("Use Serialization Proxy instead.");
        }
    }
    

    It's superclass

    package net.suivideflotte.drivercompanion.jobs;
    
    import android.support.annotation.CallSuper;
    
    import net.suivideflotte.drivercompanion.model.CachedModel;
    
    import java.io.IOException;
    
    import retrofit2.Response;
    import timber.log.Timber;
    
    import static net.suivideflotte.drivercompanion.DriverApp.post;
    import static net.suivideflotte.drivercompanion.DriverApp.postSticky;
    
    /**
     * @see net.suivideflotte.drivercompanion.rest.SDF.API
     */
    public abstract class ApiJobWithEvent<ResponseBody, Event> extends AbstractApiJob<ResponseBody> {
    
        public ApiJobWithEvent() {
            this(Priority.HIGH, false);
        }
    
        public ApiJobWithEvent(boolean postSticky) {
            super(postSticky);
        }
    
        public ApiJobWithEvent(boolean postSticky, boolean persistent) {
            super(postSticky, persistent);
        }
    
        public ApiJobWithEvent(@Priority int priority, boolean postSticky) {
            super(priority, postSticky);
        }
    
        public ApiJobWithEvent(@Priority int priority, boolean postSticky, boolean persistent) {
            super(priority, postSticky, persistent);
        }
    
        @Override
        public void onAdded() {
    
        }
    
        @CallSuper
        @Override
        protected void onCallExecuted(Response<ResponseBody> response) throws Throwable {
            if (!response.isSuccessful()) {
                throw new IOException("response unsuccessful. code" + response.code());
            }
            Event event = getDoneEvent(response.body());
            if (event == null) {
                Timber.tag(getClass().getSimpleName()).wtf("done event is null!");
            } else {
                if (event instanceof CachedModel) {
                    ((CachedModel) event).toSharedPrefs(getApplicationContext());
                }
                if (mPostSticky) postSticky(event);
                else post(event);
            }
        }
    
        protected abstract Event getDoneEvent(ResponseBody body);
    }
    

    The superclass of it's superclass

    package net.suivideflotte.drivercompanion.jobs;
    
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    
    import com.birbit.android.jobqueue.CancelReason;
    import com.birbit.android.jobqueue.Job;
    import com.birbit.android.jobqueue.Params;
    import com.birbit.android.jobqueue.RetryConstraint;
    
    import net.suivideflotte.drivercompanion.DriverApp;
    import net.suivideflotte.drivercompanion.model.ImportantJob;
    import net.suivideflotte.drivercompanion.rest.SDF;
    
    import retrofit2.Call;
    import retrofit2.Response;
    
    /**
     * @see ApiJobWithEvent
     */
    public abstract class AbstractApiJob<ResponseBody> extends Job {
    
        @Nullable
        private Call<ResponseBody> mCall;
    
        protected final boolean mPostSticky;
    
        public AbstractApiJob() {
            this(Priority.HIGH, false);
        }
    
        public AbstractApiJob(boolean postSticky) {
            this(Priority.HIGH, postSticky);
        }
    
        public AbstractApiJob(boolean postSticky, boolean persistent) {
            this(Priority.HIGH, postSticky, persistent);
        }
    
        public AbstractApiJob(@Priority int priority, boolean postSticky) {
            this(priority, postSticky, false);
        }
    
        public AbstractApiJob(@Priority int priority, boolean postSticky, boolean persistent) {
            super(new Params(priority).requireNetwork().setPersistent(persistent));
            mPostSticky = postSticky;
        }
    
        @Override
        public void onAdded() {
    
        }
    
        @Override
        public void onRun() throws Throwable {
            if (mCall == null || mCall.isExecuted()) mCall = getCall(DriverApp.getApi());
            Response<ResponseBody> response = mCall.execute();
            onCallExecuted(response);
            mCall = null;
        }
    
        protected abstract void onCallExecuted(Response<ResponseBody> response) throws Throwable;
    
        @NonNull
        protected abstract Call<ResponseBody> getCall(SDF.API api);
    
        @Override
        protected void onCancel(@CancelReason int cancelReason, @Nullable Throwable throwable) {
            if (mCall != null) mCall.cancel();
        }
    
        @Override
        protected RetryConstraint shouldReRunOnThrowable(@NonNull Throwable throwable, int runCount, int maxRunCount) {
            if (this instanceof ImportantJob) return RetryConstraint.createExponentialBackoff(runCount, 3000L);
            if (runCount > maxRunCount) return RetryConstraint.CANCEL;
            return RetryConstraint.createExponentialBackoff(runCount, 3000L);
        }
    }
    

    The code used in my Application class to initialize the JobManager

    private void configureJobManager() {
            JobManagerLogger jobManagerLogger = new JobManagerLogger();
            Configuration config = new Configuration.Builder(this)
                    .customLogger(jobManagerLogger)
                    .minConsumerCount(1)
                    .maxConsumerCount(3)
                    .consumerKeepAlive(120)
                    .build();
            mJobManager = new JobManager(config);
            mJobManager.addCallback(jobManagerLogger);
        }
    

    The logger seen in the JobManager Configurationg.Builder

    package net.suivideflotte.drivercompanion.util;
    
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    
    import com.birbit.android.jobqueue.Job;
    import com.birbit.android.jobqueue.callback.JobManagerCallback;
    import com.birbit.android.jobqueue.log.CustomLogger;
    
    import net.suivideflotte.drivercompanion.BuildConfig;
    
    import timber.log.Timber;
    
    public class JobManagerLogger implements CustomLogger, JobManagerCallback {
    
        @Override
        public boolean isDebugEnabled() {
            // It seems that logs are still produced with false... Better for the issue report though.
            return BuildConfig.DEBUG && false;
        }
    
        @Override
        public void d(String text, Object... args) {
            Timber.d(text, args);
        }
    
        @Override
        public void e(Throwable t, String text, Object... args) {
            Timber.e(t, text, args);
        }
    
        @Override
        public void e(String text, Object... args) {
            Timber.e(text, args);
        }
    
        @Override
        public void v(String text, Object... args) {
            Timber.v(text, args);
        }
    
        @Override
        public void onJobAdded(@NonNull Job job) {
            Timber.i("onJobAdded(%s)", job);
        }
    
        @Override
        public void onJobRun(@NonNull Job job, int resultCode) {
            Timber.i("onJobRun(%s, %s)", job, getResultCodeString(resultCode));
        }
    
        @Override
        public void onJobCancelled(@NonNull Job job, boolean byCancelRequest, @Nullable Throwable throwable) {
            Timber.i(throwable, "onJobCancelled(%s, %b, ...)", job, byCancelRequest);
        }
    
        @Override
        public void onDone(@NonNull Job job) {
            Timber.i("onDone(%s)", job);
        }
    
        @Override
        public void onAfterJobRun(@NonNull Job job, int resultCode) {
            Timber.i("onAfterJobRun(%s, %s)", job, getResultCodeString(resultCode));
        }
    
        @NonNull
        private String getResultCodeString(int resultCode) {
            String resultStr;
            switch (resultCode) {
                case RESULT_SUCCEED:
                    resultStr = "RESULT_SUCCEED";
                    break;
                case RESULT_CANCEL_REACHED_RETRY_LIMIT:
                    resultStr = "RESULT_CANCEL_REACHED_RETRY_LIMIT";
                    break;
                case RESULT_CANCEL_CANCELLED_WHILE_RUNNING:
                    resultStr = "RESULT_CANCEL_CANCELLED_WHILE_RUNNING";
                    break;
                case RESULT_CANCEL_SINGLE_INSTANCE_WHILE_RUNNING:
                    resultStr = "RESULT_CANCEL_SINGLE_INSTANCE_WHILE_RUNNING";
                    break;
                case RESULT_CANCEL_CANCELLED_VIA_SHOULD_RE_RUN:
                    resultStr = "RESULT_CANCEL_CANCELLED_VIA_SHOULD_RE_RUN";
                    break;
                case RESULT_FAIL_WILL_RETRY:
                    resultStr = "RESULT_FAIL_WILL_RETRY";
                    break;
                default:
                    throw new IllegalArgumentException("unknown resultCode: " + resultCode);
            }
            return resultStr;
        }
    }
    

    The code that created the Job

    mApp.getJobManager().addJobInBackground(new SwitchPrivateModeJob(true, driverInfo.deviceId));
    
    opened by LouisCAD 17
  • Database locking

    Database locking

    I'm getting the following crash for some time now in our bug tracker:

    Fatal Exception: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
           at android.database.sqlite.SQLiteConnection.nativeExecute(SQLiteConnection.java)
           at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:555)
           at android.database.sqlite.SQLiteSession.execute(SQLiteSession.java:619)
           at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:44)
           at com.path.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.onJobFetchedForRunning(SqliteJobQueue.java:287)
           at com.path.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.nextJobAndIncRunCount(SqliteJobQueue.java:205)
           at com.path.android.jobqueue.cachedQueue.CachedJobQueue.nextJobAndIncRunCount(CachedJobQueue.java:68)
           at com.path.android.jobqueue.JobManager.getNextJob(JobManager.java:273)
           at com.path.android.jobqueue.JobManager.access$400(JobManager.java:25)
           at com.path.android.jobqueue.JobManager$2.getNextJob(JobManager.java:423)
           at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run(JobConsumerExecutor.java:198)
           at java.lang.Thread.run(Thread.java:818)
    

    I've been logging different scenarios to try and reproduce it, but I haven't been able to. In our bug tracker, It's always random, there's no pattern, except for the crash itself.

    Any idea on what could be causing that exception? I've read on the actual SQLite issue: https://www.sqlite.org/cvstrac/wiki?p=DatabaseIsLocked, everything seems to be in order in my code but that may not be the case.

    opened by eddnav 17
  • Unwanted duplication of jobs in a queue

    Unwanted duplication of jobs in a queue

    From @ckozak on February 7, 2015 0:36

    I have a following scenario in which I consistently get duplication of jobs.

    Configuration configuration = new Configuration.Builder(getContext())
                    .minConsumerCount(1) //always keep at least one consumer alive
                    .maxConsumerCount(1) //up to 3 consumers at a time
                    .loadFactor(1) //3 jobs per consumer
                    .consumerKeepAlive(120) //wait 2 minute
                    .build();
    

    I'm trying to get sequential jobs execution. Parallelization is not that important to me.

    • Execute a job with a network call (with .requireNetwork().persist()).
    • It fails with an AuthException. At this point I call jobManaber.stop() because any subsequent job execution will fail with the same AuthException and I need to re-login.
    @Override
        protected void onCancel() {
    
        }
    
        @Override
        protected boolean shouldReRunOnThrowable(Throwable throwable) {
            return throwable instanceof AuthException;
        }
    
    • When I relogin I call jobManager.start() to continue jobs execution.
    • I consistently get 2-3 duplicated jobs at this point.

    Copied from original issue: path/android-priority-jobqueue#92

    opened by yigit 17
  • Crash related to DB version

    Crash related to DB version

    Hi, We are facing crashes in our android application related to this library. The play-store version of the app used the older path/job-queue library (1.1.2) . We upgraded the version to use yirgit/job-queue (2.0.0-alpha5) . But sometimes when we try to upgrade the app from playstore-version to latest one , we see this crash. This is device independent.Could it be something wrong with our usage of this library ?

    07-28 10:49:25.186 29626-29626/? E/AndroidRuntime: FATAL EXCEPTION: main java.lang.RuntimeException: Unable to create application android.database.sqlite.SQLiteException: Can't downgrade database from version 11 to 3 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6320) at android.app.ActivityThread.access$1800(ActivityThread.java:221) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1860) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7225) at java.lang.reflect.Method.invoke(Native Method) 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.SQLiteException: Can't downgrade database from version 11 to 3 at android.database.sqlite.SQLiteOpenHelper.onDowngrade(SQLiteOpenHelper.java:360) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:254) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163) at com.path.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.<init>(SqliteJobQueue.java:42) at com.path.android.jobqueue.JobManager$DefaultQueueFactory.createPersistentQueue(JobManager.java:594) at com.path.android.jobqueue.JobManager.<init>(JobManager.java:77) at com.path.android.jobqueue.JobManager.<init>(JobManager.java:61)

    bug infeasible 
    opened by mayankkrjain 16
  • Battery draining issue

    Battery draining issue

    Dear yigit, You have done great framework. However, I am using this library one of my apps related with transportation. I created many jobs, and it is working fine. After quite some times I noticed that there is a serious issue taht the job always keep alive one consumer, so that my app power consumption is high. Moreover, in order to double confirm this issue, I remove the this lib, and change to asyncTask. It is give me surprise it is not taking so much battery.

    So, How to improve the battery life with this library. or do you have roadmap to fix this problem in the future. Thanks

    opened by ravenet 16
  • Feature Single-id to handle jobs that should only run once

    Feature Single-id to handle jobs that should only run once

    This resolves path#51 and addresses part of what was requested in #36 .

    When building a job, you can pass a singleId Param, so that if another Job with the same singleId is already queued, they will only run once. This avoids having to manually use static atomic variables or other kinds of locks. It also improves from what was suggested in path#51 in that onAdded() will always be called, so you can do database operations in the JobManager's Executor (if using addJobInBackground). The feature covers the KEEP_OTHER scenario.

    Some details:

    • onAdded() will still be called on every Job so that you can update the local database if necessary.
    • The ID returned from addJob() will be the same for both (or more) jobs.
    • Finally, if the previous Job with the same singleId is already running, this behavior will not apply and both jobs will be run normally.
    opened by guavabot 14
  • JobsQueue doesn't work after calling 'cancelJobsInBackground' method (CRITICAL)

    JobsQueue doesn't work after calling 'cancelJobsInBackground' method (CRITICAL)

    Hello @yigit. First of all, thank you for your great work :)

    I faced with one quite serious problem after attempts to use the newly added jobs cancelation mechanism (added in v1.3).

    Seems that after calling jobManager.cancelJobsInBackground JobsQueue brakes itself and doesn't execute new jobs anymore.

    public class MainActivity extends ActionBarActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final JobManager jobManager = MyApplication.getInstance().getJobManager();
    
            Button doJobButton = (Button) findViewById(R.id.button1);
            doJobButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    jobManager.addJobInBackground(new SimpleJob());
                }
            });
    
            Button cancelJobsButton = (Button) findViewById(R.id.button2);
            cancelJobsButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    jobManager.cancelJobsInBackground(new CancelResult.AsyncCancelCallback() {
                        @Override
                        public void onCancelled(CancelResult cancelResult) {
                            Collection<Job> cancelledJobs = cancelResult.getCancelledJobs();
                            Collection<Job> failedToCancelJobs = cancelResult.getFailedToCancel();
                            jobManager.clear();
                            jobManager.stop();
                            Log.d(MainActivity.class.getSimpleName(), "JobsQueue: cancelled jobs - " + cancelledJobs.size()
                                    + ", failed to cancel jobs - " + failedToCancelJobs.size());
                        }
                    }, TagConstraint.ALL, SimpleJob.TAG);
                }
            });
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            EventBus.getDefault().register(this);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            EventBus.getDefault().unregister(this);
        }
    
        public void onEventMainThread(JobDoneEvent event) {
            Toast.makeText(this, "Job done", Toast.LENGTH_SHORT).show();
        }
    
        private static class SimpleJob extends Job {
    
            public static String TAG = SimpleJob.class.getSimpleName();
    
            protected SimpleJob() {
                super(new Params(1).addTags(TAG));
            }
    
            @Override
            public void onAdded() {
                Log.d(TAG, "onAdded");
            }
    
            @Override
            public void onRun() throws Throwable {
                Log.d(TAG, "onRun");
                Thread.sleep(TimeUnit.SECONDS.toMillis(3));
                EventBus.getDefault().post(new JobDoneEvent());
            }
    
            @Override
            protected void onCancel() {
                Log.d(TAG, "onCancel");
            }
    
            @Override
            protected int getRetryLimit() {
                return 5;
            }
    
            @Override
            protected boolean shouldReRunOnThrowable(Throwable throwable) {
                return true;
            }
        }
    
        private static class JobDoneEvent {
    
        }
    }
    

    A super-easy way to reproduce the problem using the code from above:

    1. Add several jobs the the queue, just click 3-4 times on addJobButton
    2. When there are some active/waiting jobs in the queue still, click cancelJobsButton.
    3. Try to add a new job (again, by clicking the Add Job button)... Nothing happens. There will be a call to onAdded method of our SimpleJob, but onRun won't be ever called.
    4. What's even more important, JobsQueue will be in this "broken" state even after application restart (close the app by pressing system Back button and launch the app again). The only way to fix this is to kill the whole process completely. So this is an indication of another problem which probably isn't connected to cancelation itself: JobsQueue keeps itself alive even if application was closed. I assume if we set minConsumerCount to something greater than 0 then JobsQueue will do attempts to keep at least one consumer thread alive draining battery life even if your application was closed.

    I'm using Android 5.0 on my test device. By the way, here is my config if it helps:

     Configuration configuration = new Configuration.Builder(this)
                    .minConsumerCount(0)
                    .maxConsumerCount(3)
                    .loadFactor(3)
                    .consumerKeepAlive(60)
                    .customLogger(new JobQueueLogger())
                    .build();
    
    opened by fraggjkee 13
  • Logging JobManagerThread.getNextJob() logs only if debug is enabled

    Logging JobManagerThread.getNextJob() logs only if debug is enabled

    Hello,

    This change just uses the JqLog.isDebugEnabled() method to don't log those messages if we're not in debug. I've made the change because I was getting too many messages in the logcat.

    Please, don't hesitate to reply if you want me to change anything else.

    Thanks for your time, best regards

    opened by gmerinojimenez 12
  • Idle mode awareness

    Idle mode awareness

    Android M adds Doze mode and App Standby. This change aims to make the Job Manager work with Doze mode.

    Doze mode disables access to network while active, but isConnectedOrConnecting() says there is network. This results in the Job Manager thinking there is network, scheduling jobs to run that require the network, those jobs failing and then being rescheduled (just to fail again).

    Additionally when Doze exits a network broadcast (CONNECTIVITY_ACTION) is NOT sent. So until another job is entered into the queue or the device loses internet and gains it back, networking jobs will be idle even after Doze is finished. By listening to ACTION_DEVICE_IDLE_MODE_CHANGED the Job Manager can update the network queue accordingly.

    This is important especially for IDLE_MAINTENANCE which is entered periodically during doze (granting network access if available). If we don't listen to this broadcast it's unlikely we'll wake up to do work during this maintenance window.

    opened by coltin 12
  • Fatal Exception: java.lang.SecurityException Package android does not belong to 10275

    Fatal Exception: java.lang.SecurityException Package android does not belong to 10275

    com.birbit.android.jobqueue.network.NetworkUtilImpl.listenNetworkViaConnectivityManager (NetworkUtilImpl.java:47) com.birbit.android.jobqueue.network.NetworkUtilImpl. (NetworkUtilImpl.java:28) com.birbit.android.jobqueue.config.Configuration$Builder.build (Configuration.java:462)

    Version used: 'com.birbit:android-priority-jobqueue:2.0.1'

    Crashes on Android 11 devices. The target app version is 30.

    Request for quick resolution.

    opened by PranavK1104 2
  • android.database.sqlite.SQLiteBlobTooBigException

    android.database.sqlite.SQLiteBlobTooBigException

    Suddenly I am seeing such kind of SQLiteBlobTooBigException exception on Android 9+ devices.

    LOCATION: SqliteJobQueue.java line 297 in com.path.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.nextJobAndIncRunCount() EXCEPTION: android.database.sqlite.SQLiteBlobTooBigException MESSAGE: Row too big to fit into CursorWindow requiredPos=0, totalRows=1

    android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1 at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow()(SQLiteConnection.java:-2) at android.database.sqlite.SQLiteConnection.executeForCursorWindow()(SQLiteConnection.java:942) at android.database.sqlite.SQLiteSession.executeForCursorWindow()(SQLiteSession.java:838) at android.database.sqlite.SQLiteQuery.fillWindow()(SQLiteQuery.java:62) at android.database.sqlite.SQLiteCursor.fillWindow()(SQLiteCursor.java:155) at android.database.sqlite.SQLiteCursor.getCount()(SQLiteCursor.java:142) at android.database.AbstractCursor.moveToPosition()(AbstractCursor.java:232) at android.database.AbstractCursor.moveToNext()(AbstractCursor.java:287) at com.path.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.nextJobAndIncRunCount()(SqliteJobQueue.java:297) at com.path.android.jobqueue.cachedQueue.CachedJobQueue.nextJobAndIncRunCount()(CachedJobQueue.java:72) at com.path.android.jobqueue.JobManager.getNextJob()(JobManager.java:527) at com.path.android.jobqueue.JobManager.access$900()(JobManager.java:32) at com.path.android.jobqueue.JobManager$5.getNextJob()(JobManager.java:701) at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run()(JobConsumerExecutor.java:303) at java.lang.Thread.run()(Thread.java:919)

    thread 79682 - HwBinder:6224_1:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill()(SynchronousQueue.java:461) java.util.concurrent.SynchronousQueue$TransferStack.transfer()(SynchronousQueue.java:362) java.util.concurrent.SynchronousQueue.poll()(SynchronousQueue.java:937) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill()(SynchronousQueue.java:461) java.util.concurrent.SynchronousQueue$TransferStack.transfer()(SynchronousQueue.java:362) java.util.concurrent.SynchronousQueue.poll()(SynchronousQueue.java:937) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.LinkedBlockingQueue.poll()(LinkedBlockingQueue.java:467) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : android.os.MessageQueue.nativePollOnce()(MessageQueue.java:-2) android.os.MessageQueue.next()(MessageQueue.java:336) android.os.Looper.loop()(Looper.java:181) android.app.ActivityThread.main()(ActivityThread.java:7560) java.lang.reflect.Method.invoke()(Method.java:-2) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run()(RuntimeInit.java:539) com.android.internal.os.ZygoteInit.main()(ZygoteInit.java:950)

    thread 79676 - SoundPoolThread:

    thread 79624 - Jit thread pool worker thread 0:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1127) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1120) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) java.lang.Object.wait()(Object.java:442) java.lang.Object.wait()(Object.java:568) com.android.okhttp.okio.AsyncTimeout.awaitTimeout()(AsyncTimeout.java:313) com.android.okhttp.okio.AsyncTimeout.access$000()(AsyncTimeout.java:42) com.android.okhttp.okio.AsyncTimeout$Watchdog.run()(AsyncTimeout.java:288)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1127) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) java.lang.Object.wait()(Object.java:442) java.lang.ref.ReferenceQueue.remove()(ReferenceQueue.java:190) java.lang.ref.ReferenceQueue.remove()(ReferenceQueue.java:211) com.bumptech.glide.load.engine.ActiveResources.cleanReferenceQueue()(ActiveResources.java:128) com.bumptech.glide.load.engine.ActiveResources$2.run()(ActiveResources.java:61) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1167) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.bumptech.glide.load.engine.ActiveResources$1$1.run()(ActiveResources.java:43) java.lang.Thread.run()(Thread.java:919)

    thread 79630 - Binder:6224_1:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1132) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) java.lang.Object.wait()(Object.java:442) java.lang.Object.wait()(Object.java:568) java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded()(Daemons.java:342) java.lang.Daemons$FinalizerWatchdogDaemon.runInternal()(Daemons.java:322) java.lang.Daemons$Daemon.run()(Daemons.java:140) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1132) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread 79633 - Binder:6224_3:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1120) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1132) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.LinkedBlockingQueue.poll()(LinkedBlockingQueue.java:467) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) java.lang.Object.wait()(Object.java:442) java.lang.Object.wait()(Object.java:568) java.lang.Daemons$ReferenceQueueDaemon.runInternal()(Daemons.java:218) java.lang.Daemons$Daemon.run()(Daemons.java:140) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.LinkedBlockingQueue.poll()(LinkedBlockingQueue.java:467) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919) com.google.android.gms.analytics.zzk$zzc.run()(zzk.java:4)

    thread 79625 - Signal Catcher:

    thread 79632 - Profile Saver:

    thread 79677 - SoundPool:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1132) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill()(SynchronousQueue.java:461) java.util.concurrent.SynchronousQueue$TransferStack.transfer()(SynchronousQueue.java:362) java.util.concurrent.SynchronousQueue.poll()(SynchronousQueue.java:937) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1120) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill()(SynchronousQueue.java:461) java.util.concurrent.SynchronousQueue$TransferStack.transfer()(SynchronousQueue.java:362) java.util.concurrent.SynchronousQueue.poll()(SynchronousQueue.java:937) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) com.android.okhttp.ConnectionPool$1.run()(ConnectionPool.java:107) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1167) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread 79626 - HeapTaskDaemon:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:1132) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread 79631 - Binder:6224_2:

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.poll()(ScheduledThreadPoolExecutor.java:1168) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.poll()(ScheduledThreadPoolExecutor.java:849) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.parkNanos()(LockSupport.java:230) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos()(AbstractQueuedSynchronizer.java:2109) java.util.concurrent.LinkedBlockingQueue.poll()(LinkedBlockingQueue.java:467) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1091) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) com.google.android.gms.common.util.concurrent.zza.run()(zza.java:6) java.lang.Thread.run()(Thread.java:919)

    thread null - : com.android.org.conscrypt.NativeCrypto.SSL_read()(NativeCrypto.java:-2) com.android.org.conscrypt.NativeSsl.read()(NativeSsl.java:411) com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read()(ConscryptFileDescriptorSocket.java:549) com.android.okhttp.okio.Okio$2.read()(Okio.java:138) com.android.okhttp.okio.AsyncTimeout$2.read()(AsyncTimeout.java:213) com.android.okhttp.okio.RealBufferedSource.indexOf()(RealBufferedSource.java:307) com.android.okhttp.okio.RealBufferedSource.indexOf()(RealBufferedSource.java:301) com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict()(RealBufferedSource.java:197) com.android.okhttp.internal.http.Http1xStream.readResponse()(Http1xStream.java:188) com.android.okhttp.internal.http.Http1xStream.readResponseHeaders()(Http1xStream.java:129) com.android.okhttp.internal.http.HttpEngine.readNetworkResponse()(HttpEngine.java:750) com.android.okhttp.internal.http.HttpEngine.readResponse()(HttpEngine.java:622) com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute()(HttpURLConnectionImpl.java:475) com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse()(HttpURLConnectionImpl.java:411) com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode()(HttpURLConnectionImpl.java:542) com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode()(DelegatingHttpsURLConnection.java:106) com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode()(HttpsURLConnectionImpl.java:30) com.newrelic.agent.android.instrumentation.HttpsURLConnectionExtension.getResponseCode()(HttpsURLConnectionExtension.java:255) com.facebook.GraphResponse.fromHttpConnection()(GraphResponse.java:264) com.facebook.GraphRequest.executeConnectionAndWait()(GraphRequest.java:1285) com.facebook.GraphRequest.executeBatchAndWait()(GraphRequest.java:1183) com.facebook.GraphRequest.executeBatchAndWait()(GraphRequest.java:1149) com.facebook.GraphRequest.executeBatchAndWait()(GraphRequest.java:1133) com.facebook.GraphRequest.executeAndWait()(GraphRequest.java:1108) com.facebook.GraphRequest.executeAndWait()(GraphRequest.java:1002) com.facebook.appevents.ml.ModelManager.fetchFromServer()(ModelManager.java:149) com.facebook.appevents.ml.ModelManager.access$000()(ModelManager.java:50) com.facebook.appevents.ml.ModelManager$1.run()(ModelManager.java:82) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1167) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : java.lang.Object.wait()(Object.java:-2) java.lang.Object.wait()(Object.java:442) java.lang.ref.ReferenceQueue.remove()(ReferenceQueue.java:190) java.lang.ref.ReferenceQueue.remove()(ReferenceQueue.java:211) java.lang.Daemons$FinalizerDaemon.runInternal()(Daemons.java:274) java.lang.Daemons$Daemon.run()(Daemons.java:140) java.lang.Thread.run()(Thread.java:919)

    thread null - : sun.misc.Unsafe.park()(Unsafe.java:-2) java.util.concurrent.locks.LockSupport.park()(LockSupport.java:190) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await()(AbstractQueuedSynchronizer.java:2067) java.util.concurrent.LinkedBlockingQueue.take()(LinkedBlockingQueue.java:442) java.util.concurrent.ThreadPoolExecutor.getTask()(ThreadPoolExecutor.java:1092) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1152) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    thread null - : android.os.MessageQueue.nativePollOnce()(MessageQueue.java:-2) android.os.MessageQueue.next()(MessageQueue.java:336) android.os.Looper.loop()(Looper.java:181) android.os.HandlerThread.run()(HandlerThread.java:67)

    thread null - : android.os.Parcel.nativeWriteString()(Parcel.java:-2) android.os.Parcel$ReadWriteHelper.writeString()(Parcel.java:378) android.os.Parcel.writeString()(Parcel.java:750) android.content.pm.IPackageManager$Stub$Proxy.getPackageUid()(IPackageManager.java:5054) android.os.storage.StorageManager.getVolumeList()(StorageManager.java:1262) android.os.Environment$UserEnvironment.getExternalDirs()(Environment.java:109) android.os.Environment.getExternalStorageDirectory()(Environment.java:571) com.facebook.internal.Utility.refreshAvailableExternalStorage()(Utility.java:1223) com.facebook.internal.Utility.refreshPeriodicExtendedDeviceInfo()(Utility.java:1178) com.facebook.internal.Utility.setAppEventExtendedDeviceInfoParameters()(Utility.java:824) com.facebook.appevents.internal.AppEventsLoggerUtility.getJSONObjectForGraphAPICall()(AppEventsLoggerUtility.java:76) com.facebook.FacebookSdk.publishInstallAndWaitForResponse()(FacebookSdk.java:667) com.facebook.FacebookSdk$5.run()(FacebookSdk.java:648) java.util.concurrent.ThreadPoolExecutor.runWorker()(ThreadPoolExecutor.java:1167) java.util.concurrent.ThreadPoolExecutor$Worker.run()(ThreadPoolExecutor.java:641) java.lang.Thread.run()(Thread.java:919)

    opened by morerohit86 0
  • cannot save job to disk

    cannot save job to disk

    Can you tell me how to fix it?

    AndroidRuntime: FATAL EXCEPTION: job-manager Process: com.szjsaq.hzs_tvbox, PID: 5246 java.lang.RuntimeException: cannot save job to disk at com.birbit.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.persistJobToDisk(SqliteJobQueue.java:107) at com.birbit.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.insert(SqliteJobQueue.java:90) at com.birbit.android.jobqueue.cachedQueue.CachedJobQueue.insert(CachedJobQueue.java:29) at com.birbit.android.jobqueue.JobManagerThread.handleAddJob(JobManagerThread.java:143) at com.birbit.android.jobqueue.JobManagerThread.access$100(JobManagerThread.java:35) at com.birbit.android.jobqueue.JobManagerThread$1.handleMessage(JobManagerThread.java:228) at com.birbit.android.jobqueue.messaging.PriorityMessageQueue.consume(PriorityMessageQueue.java:39) at com.birbit.android.jobqueue.JobManagerThread.run(JobManagerThread.java:222) at java.lang.Thread.run(Thread.java:761) Caused by: java.io.NotSerializableException: com.j256.ormlite.dao.BaseDaoImpl$6 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) at com.birbit.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue$JavaSerializer.serialize(SqliteJobQueue.java:493) at com.birbit.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.persistJobToDisk(SqliteJobQueue.java:105) at com.birbit.android.jobqueue.persistentQueue.sqlite.SqliteJobQueue.insert(SqliteJobQueue.java:90)  at com.birbit.android.jobqueue.cachedQueue.CachedJobQueue.insert(CachedJobQueue.java:29)  at com.birbit.android.jobqueue.JobManagerThread.handleAddJob(JobManagerThread.java:143)  at com.birbit.android.jobqueue.JobManagerThread.access$100(JobManagerThread.java:35)  at com.birbit.android.jobqueue.JobManagerThread$1.handleMessage(JobManagerThread.java:228)  at com.birbit.android.jobqueue.messaging.PriorityMessageQueue.consume(PriorityMessageQueue.java:39)  at com.birbit.android.jobqueue.JobManagerThread.run(JobManagerThread.java:222)  at java.lang.Thread.run(Thread.java:761) 

    com.j256.ormlite.dao.BaseDaoImpl Not serializable How to solve?

    opened by BlueGeneR 0
  • Hi Yigit, hope you can help us out

    Hi Yigit, hope you can help us out

    Hello Yigit

    my name is Laizz and we are working on a new webtorrent platform for Android. We have a problem and are looking for an experienced developer who knows about android job scheduler. I hope you can help us out.

    Our problem

    We have a Cordova Ionic app that integrates webtorrent and peerjs modules among others. Up to Android version 8.0, the app and the modules work correctly. As of Android version 8.1, we have found that there are problems with forwarding events from the WebSocket base module. Since the app also runs on the Android Studio emulator, it can be assumed that the source code is correct.

    The task is to adapt the app and if necessary its modules to support Android greater than Android 8

    I would be happy if you could help us please contact me if you are interested in cooperation.

    my eMAil : [email protected]

    i would be glad to receive a positive answer greetings from the sun coast Spain Laizz

    opened by laizzz 0
  • Fatal Exception: android.database.sqlite.SQLiteException

    Fatal Exception: android.database.sqlite.SQLiteException

    near "SEDECT": syntax error (code 1 SQLITE_ERROR[1]): , while compiling: SEDECT SUM(case WHEN group_id is null then group_cnt else 1 end) from (SELECT count(*) group_cnt, group_id FROM job_holder WHERE ( (deadline != 9223372036854775807 AND deadline <= ?) OR network_type <= ?) AND (cancelled IS NULL OR cancelled != 1) AND delay_until_ns <= ? AND running_session_id != ? GROUP BY group_id)

    opened by slott 0
Owner
Yigit Boyar
Yigit Boyar
Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.

Codename One - Cross Platform Native Apps with Java or Kotlin Codename One is a mobile first cross platform environment for Java and Kotlin developers

Codename One 1.4k Dec 23, 2022
dexposed enable 'god' mode for single android application.

What is it? Dexposed is a powerful yet non-invasive runtime AOP (Aspect-oriented Programming) framework for Android app development, based on the work

Alibaba 4.5k Dec 28, 2022
Kick-starts Android application development.

Synopsis If you've made it here, chances are you are not quite as satisfied with the Android application framework as you could be. Same for us, that'

Matthias Käppler 1.3k Dec 4, 2022
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
VasSonic is a lightweight and high-performance Hybrid framework developed by tencent VAS team, which is intended to speed up the first screen of websites working on Android and iOS platform.

VasSonic: A Lightweight And High-performance Hybrid Framework VasSonic is a lightweight and high-performance Hybrid framework developed by tencent VAS

Tencent 11.6k Dec 30, 2022
Android common lib, include ImageCache, HttpCache, DropDownListView, DownloadManager, Utils and so on

android-common-lib 关于我,欢迎关注 微博:Trinea 主页:trinea.cn 邮箱:trinea.cn#gmail.com 微信:codek2 主要包括:缓存(图片缓存、预取缓存、网络缓存)、公共View(下拉及底部加载更多ListView、底部加载更多ScrollView、

Trinea 5k Dec 30, 2022
🚀Plugin for Android Studio And IntelliJ Idea to generate Kotlin data class code from JSON text ( Json to Kotlin )

JsonToKotlinClass Hi, Welcome! This is a plugin to generate Kotlin data class from JSON string, in another word, a plugin that converts JSON string to

Seal 2.8k Jan 3, 2023
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
kotlin-core - A full framework for making Android apps. Based on Anko and Kotson.

kotlin-core This package is not Android-specific, and can be used across platforms. However, for a good example of use in Android, take a look at kotl

Lightning Kite 36 Oct 3, 2022
Add new features for reverse engineering, such as: renaming of classes, fields, methods, variables, reference graphs and more.

Super JADX features Add new features for reverse engineering, such as: renaming of classes, fields, methods, variables, reference graphs and more. bas

null 284 Dec 28, 2022
Source++ is an open-source live coding platform. Add breakpoints, logs, metrics, and tracing to live production applications

Source++ is an open-source live coding platform. Add breakpoints, logs, metrics, and distributed tracing to live production software in real-time on-d

Source++ 40 Dec 14, 2022
Android part of the Android Studio(IntellijIDEA) OkHttp Profiler plugin

OkHttpProfiler Android Library Created by LocaleBro.com - Android Localization Platform The OkHttp Profiler plugin can show requests from the OkHttp l

Ievgenii 261 Dec 8, 2022
A Model-View-Presenter / Model-View-Intent library for modern Android apps

Mosby A Model-View-Presenter and Model-View-Intent library for Android apps. Dependency dependencies { compile 'com.hannesdorfmann.mosby3:mvi:3.1.1

Hannes Dorfmann 5.5k Dec 25, 2022
A small, yet full-featured framework that allows building View-based Android applications

Conductor A small, yet full-featured framework that allows building View-based Android applications. Conductor provides a light-weight wrapper around

BlueLine Labs 3.9k Jan 6, 2023
A plugin system that runs like a browser, but instead of load web pages, it load apk plugins which runs natively on Android system.

Android Dynamic Loader Android Dynamic Loader is a plugin system. The host application is like a browser, but instead of load web pages, it load plugi

Tu Yimin 1.4k Dec 28, 2022
LiteOrm is a fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line of code efficiently.

#LiteOrm:Android高性能数据库框架 A fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line

马天宇 1.5k Nov 19, 2022
Rosie is an Android framework to create applications following the principles of Clean Architecture.

Rosie The only way to make the deadline—the only way to go fast—is to keep the code as clean as possible at all times. — Robert C. Martin in Clean Cod

Karumi 1.8k Dec 28, 2022
Create kotlin android project with one line of command.

README This is an android application template project built with kotlin language and some useful libraries. It provides a creator script to quickly c

nekocode 1.6k Dec 20, 2022
Moxy is MVP library for Android

Moxy This Moxy repository is deprecated and no longer supported. Please migrate to the actual version of the Moxy framework at Moxy communuty repo. De

Arello Mobile 1.6k Dec 28, 2022