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

Overview

Development in this repository is stopped. Future development continues on https://github.com/yigit/android-priority-jobqueue

==========================

logo

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.
        webservice.postTweet(text);
    }
    @Override
    protected boolean shouldReRunOnThrowable(Throwable throwable) {
        // An error occurred in onRun.
        // Return value determines whether this job should retry running (true) or abort (false).
    }
    @Override
    protected void onCancel() {
        // Job has exceeded retry attempts or shouldReRunOnThrowable() has returned false.
    }
}

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

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 fracions 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. Beware, onAdded() is called on the thread job was added.

  • 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 activites, 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.

Gradle: compile 'com.path:android-priority-jobqueue:1.1.2'

Maven:

<dependency>
    <groupId>com.path</groupId>
    <artifactId>android-priority-jobqueue</artifactId>
    <version>1.1.2</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

  • 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

We are in the process of moving build system from ant to gradle. Right now, you can build with gradle but if you want to run tests, you'll need ant.

  • Clone the repo
  • > cd jobqueue
  • > ant clean build-jar

This will create a jar file under release folder.

Running Tests

  • cd jobqueue

  • ant clean test

License

Android Priority Jobqueue is made available under the MIT license:

The MIT License (MIT)

Copyright (c) 2013 Path, 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
  • Pass ID to the job in onAdded()

    Pass ID to the job in onAdded()

    In some cases it is useful when the job knows its own job ID.

    Example usecase: Consider multiple job instances which have been chained by calling addOnBackground() in their respective onRun() method which is very useful for executing requests with result limits and paging. In this case the last job can check if all previous jobs have been executed successfully (by using the IDs they have passed to it via the constructor or stored in a central place) before sending out a finish-event.

    opened by ubuntudroid 8
  • Add cancelJob() family methods

    Add cancelJob() family methods

    Add below methods to cancel not running jobs:

    boolean cancelJob(long id, boolean isPersistent)
    boolean cancelJobInBackground(long id, boolean isPersistent)
    boolean cancelJobInBackground(long id, boolean isPersistent, AsyncCanelCallback callback)
    

    I know there is ongoing discussion at #2. In other hand, currently we want to remove job only while the activity is alive. In this case, cancel with id might be clearer than tag.

    2052f5c is commit for migration to gradle project which aware of latest Android Studio IDE :). This changes directory structure to gradle style one. ('examples' directory is not touched. sorry for TODO!) If not ready to migration, I'll remove that commit.

    Thanks for great works!

    opened by ypresto 6
  • Update README.md

    Update README.md

    Added a potential exclusion necessary for building a Maven project with this library. We ran into issues that required several exclusions, including com.android.google, so it is likely that others will experience similar issues.

    opened by pendext 0
  • Dispatch Timer-based flushing

    Dispatch Timer-based flushing

    • gradle works, but only for building a library project.
    • Created a new interface TimerDispatcher and a basic/intermediate implementation. Default impl recreates previous functionality. Intermediate impl should create a timer that flushes every n milliseconds.
    • also added functionality to automatically flush queue after a certain capacity threshold has been reached.
    opened by JvmName 0
  • Added inspection and removal of jobs to JobManager

    Added inspection and removal of jobs to JobManager

    Added ability to retrieve all existing job IDs from the JobManager Added ability to retrieve a job by ID from the JobManager Added ability to remove a job by ID from the JobManager

    opened by fmoda3 0
Owner
Path Mobile Inc Pte. Ltd.
Path Mobile Inc Pte. Ltd.
Recruitment Task App - record time which a user spends on tasks defined by himself

Recruitment-Task The purpose of this application is to record time which a user spends on tasks defined by himself. The user can add new tasks. New ta

Sylwester Zieliński 0 Feb 9, 2022
Using Resilience4J, this is a Demo project which uses a Library as background and manages all its requests.

Using Resilience4J, this is a Demo project which uses a Library as background and manages all its requests. This library can rent books online and the usage rate is extremely high. There is a reactive way to access, which is the one normally used, but sometimes, the system needs a bit of help from an old machine running a non-reactive MVC Spring application using JPA. Let's make this in Kotlin and find the best solution!

João Filipe Sabino Esperancinha 2 Jan 10, 2022
Android service daemon ,keep background service alive

安卓后台保活2021新姿势 适配华为大部分系列手机,vivo,OPPO 部分机型,小米的不支持,可见小米在对抗后台自保上做得最好 本项目原本是给某个公司合作开发的,最后给了对方SDK之后由于付款问题闹得很郁闷,想着这个代码拿在自己手上也没用,就发出来给大家参考参考。目前分析的结果来看,这个是全网目前

null 64 Nov 22, 2022
A .NET Watch Run Configuration (dotnet-watch) that can be used in RiderA .

A .NET Watch Run Configuration (dotnet-watch) that can be used in RiderA .NET Watch Run Configuration (dotnet-watch) that can be used in Rider

Maarten Balliauw 18 Sep 26, 2022
Makes Google play in app purchase library (BillingClient) into a flowable that can easily be used in compose world

Billy the android Our goal is to make a modern api of BillingClient so that it is easier to use in compose world. This library is still early beta and

Stefan Wärting 14 Nov 17, 2022
A simple screen starter written in kotlin

screen-starter A simple screen starter written in kotlin. Compilation Use clean shadowJar! Usage Use java -jar screen-starter-1.0-SNAPSHOT.jar --confi

GrowlyX 3 Sep 1, 2021
A collection of the same program written in different languages.

Batch Encoders A collection of the same program written in different languages. About This program is a simple batch encoder, it allows you to add mul

Alex Cusaac 0 Nov 4, 2021
A plugin written for my 1.12.2 anarchy server

A plugin written for my 1.12.2 anarchy server. I don't recommend using any of the fixes, most of them are garbage. Pull requests are welcome.

comendantmc 4 Jun 6, 2022
An application for runners and cyclists. Allows you to monitor your physical activity, weight and receive reminders about workouts.

An application for runners and cyclists. Allows you to monitor your physical activity, weight and receive reminders about workouts.

Just_Amalll 3 Feb 7, 2022
A template project that builds a SDL application programmed in Zig to Android from scratch

A template project that builds a SDL application programmed in Zig to Android from scratch

Matheus Lessa 11 Jul 19, 2022
The SSI Kit is a technology stack for enabling Self-Sovereign Identity (SSI) in any application.

Walt.ID SSI Kit The Walt.ID SSI Kit is a holistic SSI solution, with primarily focus on the European EBSI/ESSIF ecosystem. The core services are in th

walt.id 50 Nov 18, 2022
Zakadabar Application Template

Zakadabar Application Template This repository contains an application template which you may use to start a new application project based on Zakadaba

null 0 Nov 1, 2021
Create a simple one screen application with scrollable table view

Create a simple one screen application with scrollable table view

Nikola Crnogorac 0 Nov 19, 2021
UpSchool Capstone Project - Course selling application with MVVM, LiveData, DataBinding, Retrofit, Room Database, Navigation Component, Adapter, Firebase Auth, Picasso, Lottie

UpSchool Capstone Project - Course selling application with MVVM (Model, View, ViewModel), LiveData, DataBinding, Retrofit, Room Database, Navigation Component(NavGraph, BottomNav), Adapter, Firebase Auth, Picasso, Lottie

Sena Çelik 4 Jul 24, 2022
****. Use the native and support library variants instead - https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html. An android library that makes it easy to add custom fonts to edittexts and textviews

Add to your project Add this line to your dependencies in build.gradle compile 'in.workarounds.typography:typography:0.0.8' Using the views There are

Workarounds 43 Nov 6, 2021
SL4A brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device.

#Scripting Layer for Android (SL4A) SL4A brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreter

Damon Kohler 2.3k Nov 20, 2022
A curated list of standards, tests and benchmarks that can be used for testing and evaluating dev-tools

A curated list of standards, tests and benchmarks that can be used for testing and evaluating dev tools Contribution Add the description of the benchm

null 11 May 27, 2022
A gradle plugin for getting java lambda support in java 6, 7 and android

Gradle Retrolambda Plugin This plugin will automatically build your java or android project with retrolambda, giving you lambda goodness on java 6 or

Evan Tatarka 5.3k Nov 22, 2022
An android library for displaying fps from the choreographer and percentage of time with two or more frames dropped

DEPRECATED TinyDancer is deprecated. No more development will be taking place. Check out the Google Android developer documentation for UI performance

Friendly Robot 1.9k Nov 21, 2022