Paramclasses Academy - Blog

Tutorials Details

←
Post 32 of 40
→

How to setup Background Work in Android: Services, WorkManager and Scheduled Tasks

How to setup Background Work in Android: Services, WorkManager and Scheduled Tasks

November 4, 2026

Introduction

Android applications often need to perform tasks without blocking the main user interface.

For example:

  • Downloading files from the internet.

  • Uploading images to a server.

  • Synchronizing application data.

  • Sending scheduled reminders.

  • Processing large files.

  • Performing periodic database operations.

These operations are known as background tasks.

Android provides different APIs for performing background work, including Services, WorkManager, and scheduling APIs.

In this tutorial, we will understand these concepts and create a practical Background Task Demo App using Java and Android Studio.

By the end of this tutorial, you will learn how to:

  • Understand Android Services.

  • Understand foreground and background services.

  • Create a Worker class.

  • Schedule one-time background tasks.

  • Schedule periodic background tasks.

  • Apply background task constraints.

  • Monitor WorkManager task status.

  • Cancel scheduled tasks.

1. What Is Background Work in Android?

Background work refers to operations performed outside the application's main user interface workflow.

For example, imagine a shopping application that needs to upload an order confirmation to a server.

The application should allow the user to continue using the interface while the upload operation runs separately.

If a long-running operation is performed directly on the main thread, the application may freeze or produce an Application Not Responding (ANR) error.

Background execution helps keep the user interface responsive.

2. What Is an Android Service?

A Service is an Android application component that can perform operations without providing its own user interface.

A Service can continue performing work when the user moves away from the Activity that started it, subject to Android's background execution restrictions.

For example:

  • Playing music.

  • Maintaining an ongoing navigation session.

  • Performing a user-visible data transfer.

  • Managing an ongoing connection.

A Service does not automatically create a separate thread. By default, its callbacks run on the application's main thread.

Therefore, long-running or blocking operations should not be performed directly inside Service callbacks.

3. Types of Android Services

Android Services are commonly discussed in the following categories.

Started Service

A Started Service begins when another application component calls startService() or, where appropriate, startForegroundService().

It can continue running independently of the Activity that started it, subject to system restrictions.

Bound Service

A Bound Service allows another component to connect to it and communicate with it through an IBinder interface.

For example, an Activity can bind to a music service to control playback.

Foreground Service

A Foreground Service performs work that is noticeable to the user.

Examples include:

  • Music playback.

  • Active navigation.

  • Ongoing fitness tracking.

  • User-visible data transfer.

A Foreground Service must display a notification.

Modern Android versions also require appropriate foreground service types and permissions. Android 14 and later require foreground service types to be declared for applicable services.

Important: A Service is not automatically a reliable task scheduler. For most deferrable background tasks, Android recommends considering WorkManager.

4. What Is WorkManager?

WorkManager is an Android Jetpack library used to schedule reliable background work.

It is especially useful when a task should continue to be eligible for execution even if the user leaves the application or the application process is recreated.

Examples include:

  • Uploading application data.

  • Synchronizing database records.

  • Downloading files.

  • Cleaning temporary files.

  • Periodically refreshing application content.

WorkManager works with Android's scheduling mechanisms and manages execution according to system conditions and constraints.

It is generally the recommended solution for persistent, deferrable background tasks.

5. Important WorkManager Components

Before creating our application, understand these important classes.

Worker

A Worker contains the actual code that should execute in the background.

You override its doWork() method to perform the required operation.

WorkRequest

A WorkRequest defines when and how a Worker should be scheduled.

There are two commonly used types:

OneTimeWorkRequest: Schedules a task to run once.

PeriodicWorkRequest: Schedules a task to repeat periodically.

WorkManager

WorkManager manages and schedules the WorkRequest.

You use it to enqueue, observe, and cancel background work.

Constraints

Constraints define the conditions that must be satisfied before a task can execute.

Examples include:

  • Internet connection is available.

  • Device is charging.

  • Battery is not low.

  • Storage is not low.

  • Device is idle, where supported.

6. Difference Between Services and WorkManager

Services and WorkManager solve different background execution problems.

Services are useful for ongoing operations that need to run as a service, especially work that is directly noticeable to the user.

WorkManager is useful for reliable, deferrable work that should be scheduled and executed when system conditions allow.

For example:

  • Music playback: Foreground Service.

  • Periodic server synchronization: WorkManager.

  • Image upload that can wait for network availability: WorkManager.

  • Active navigation session: Foreground Service.

Choose the API based on the actual requirements of the task rather than using a Service for every background operation.

7. Create a New Android Studio Project

First, open Android Studio.

Follow these steps:

  1. Click New Project.

  2. Select Empty Views Activity.

  3. Enter the project name: BackgroundTaskDemoApp.

  4. Select Java as the programming language.

  5. Select an appropriate minimum SDK.

  6. Click Finish.

For this tutorial, we will use WorkManager 2.12.0, which requires a minimum SDK of API 24 and compile SDK of API 33 or higher.

We will create these files:

  • MainActivity.java

  • activity_main.xml

  • BackgroundWorker.java

8. Add the WorkManager Dependency

Open the module-level build.gradle file.

Add the following dependency inside the dependencies block:

implementation 'androidx.work:work-runtime:2.12.0'

For Kotlin DSL, use:

implementation("androidx.work:work-runtime:2.12.0")

Click Sync Now.

If your existing project must support Android versions below API 24, use a compatible WorkManager 2.11.x release instead of version 2.12.0.

9. Design the Application Layout

Now create the user interface.

Open activity_main.xml and replace its content with:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="20dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Background Task Demo"
        android:textSize="24sp"
        android:textStyle="bold"
        android:gravity="center"
        android:padding="12dp" />

    <Button
        android:id="@+id/btnStartTask"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start One-Time Task" />

    <Button
        android:id="@+id/btnScheduleTask"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Schedule Periodic Task" />

    <Button
        android:id="@+id/btnCancelTask"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Cancel Periodic Task" />

    <TextView
        android:id="@+id/txtStatus"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Task Status: Waiting"
        android:textSize="16sp"
        android:gravity="center"
        android:padding="16dp" />

</LinearLayout>

Understanding the Layout

TextView: Displays the application title and task status.

Start One-Time Task: Starts a background task once.

Schedule Periodic Task: Schedules a task to repeat periodically.

Cancel Periodic Task: Cancels the scheduled periodic task.

10. Create the BackgroundWorker.java Class

Now we will create a Worker class.

Follow these steps:

  1. Open your Java package.

  2. Right-click the package name.

  3. Select New → Java Class.

  4. Enter the class name BackgroundWorker.

  5. Click OK.

Add the following code:

package com.example.backgroundtaskdemoapp;

import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class BackgroundWorker extends Worker {

    private static final String TAG = "BackgroundWorker";

    public BackgroundWorker(
            @NonNull Context context,
            @NonNull WorkerParameters workerParams
    ) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        Log.d(TAG, "Background task started");

        try {

            // Simulate background processing
            Thread.sleep(3000);

            Log.d(TAG, "Background task completed");

            return Result.success();

        } catch (InterruptedException e) {

            Thread.currentThread().interrupt();

            Log.e(TAG, "Background task interrupted", e);

            return Result.failure();
        }
    }
}

Understanding the Worker Code

extends Worker

public class BackgroundWorker extends Worker

This declares a class that uses WorkManager's Worker API.

doWork()

public Result doWork()

This method contains the actual background task.

WorkManager executes this method on a background thread.

Thread.sleep(3000)

Thread.sleep(3000);

This temporarily pauses the worker for three seconds to simulate processing.

This is only for demonstration. In a real application, you would replace it with an actual task such as uploading data or processing a file.

Result.success()

return Result.success();

Indicates that the task completed successfully.

Result.failure()

return Result.failure();

Indicates that the task failed and should not be retried automatically.

You can return Result.retry() when a temporary error occurs and the task should be retried according to its configured retry policy.

11. Implement One-Time Background Work

Now we will schedule a task that runs once.

Open MainActivity.java.

First, add these imports:

import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.work.Constraints;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.Data;

Now add the following code inside the MainActivity class:

private void startOneTimeTask() {

    Constraints constraints = new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();

    OneTimeWorkRequest workRequest =
            new OneTimeWorkRequest.Builder(BackgroundWorker.class)
                    .setConstraints(constraints)
                    .build();

    WorkManager.getInstance(this)
            .enqueue(workRequest);

    WorkManager.getInstance(this)
            .getWorkInfoByIdLiveData(workRequest.getId())
            .observe(this, workInfo -> {

                if (workInfo != null) {

                    txtStatus.setText(
                            "One-Time Task Status: " +
                            workInfo.getState().name()
                    );
                }
            });
}

Understanding the Code

Constraints

Constraints constraints = new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build();

This defines a condition that requires a network connection before the task can execute.

OneTimeWorkRequest

OneTimeWorkRequest workRequest =
        new OneTimeWorkRequest.Builder(BackgroundWorker.class)
                .setConstraints(constraints)
                .build();

Creates a one-time request using our BackgroundWorker class.

enqueue()

WorkManager.getInstance(this).enqueue(workRequest);

Adds the work request to WorkManager's scheduling queue.

getWorkInfoByIdLiveData()

.getWorkInfoByIdLiveData(workRequest.getId())

Returns observable information about the task.

We use this information to update the TextView when the task state changes.

The task may show states such as:

  • ENQUEUED

  • RUNNING

  • SUCCEEDED

  • FAILED

  • BLOCKED

  • CANCELLED

Because the task requires network connectivity, it may remain ENQUEUED until a suitable network connection is available.

12. Schedule Periodic Background Work

Sometimes an application needs to perform the same operation repeatedly.

For example:

  • Refreshing data periodically.

  • Synchronizing local records.

  • Checking for updates.

  • Cleaning temporary application files.

For these situations, we can use PeriodicWorkRequest.

Add this method inside MainActivity.java:

private static final String PERIODIC_WORK_NAME =
        "periodic_background_task";

private void schedulePeriodicTask() {

    PeriodicWorkRequest periodicWorkRequest =
            new PeriodicWorkRequest.Builder(
                    BackgroundWorker.class,
                    15,
                    java.util.concurrent.TimeUnit.MINUTES
            ).build();

    WorkManager.getInstance(this)
            .enqueueUniquePeriodicWork(
                    PERIODIC_WORK_NAME,
                    androidx.work.ExistingPeriodicWorkPolicy.KEEP,
                    periodicWorkRequest
            );

    txtStatus.setText(
            "Periodic task scheduled successfully"
    );
}

Understanding PeriodicWorkRequest

PeriodicWorkRequest

new PeriodicWorkRequest.Builder(
        BackgroundWorker.class,
        15,
        TimeUnit.MINUTES
)

Creates a periodic background task.

The minimum repeat interval for a periodic WorkManager request is 15 minutes.

enqueueUniquePeriodicWork()

.enqueueUniquePeriodicWork(
        PERIODIC_WORK_NAME,
        ExistingPeriodicWorkPolicy.KEEP,
        periodicWorkRequest
);

Schedules periodic work with a unique name.

The KEEP policy prevents a new periodic request from replacing an existing unfinished request with the same unique name.

Important: Periodic WorkManager execution is not an exact alarm. Android may delay execution because of battery optimization, device conditions, and system scheduling.

13. Cancel a Scheduled Background Task

Sometimes users need to stop a scheduled task.

For example, a user may disable automatic synchronization.

Add this method:

private void cancelPeriodicTask() {

    WorkManager.getInstance(this)
            .cancelUniqueWork(PERIODIC_WORK_NAME);

    txtStatus.setText(
            "Periodic task cancellation requested"
    );
}

Understanding the Code

cancelUniqueWork()

This method cancels the work associated with the specified unique name.

WorkManager cancellation is asynchronous, so the work may not disappear from its state immediately.

14. Complete MainActivity.java Code

Now combine the methods into one complete Java file.

Open MainActivity.java and use the following code:

package com.example.backgroundtaskdemoapp;

import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import androidx.work.Constraints;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.ExistingPeriodicWorkPolicy;

import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    private Button btnStartTask;
    private Button btnScheduleTask;
    private Button btnCancelTask;

    private TextView txtStatus;

    private static final String PERIODIC_WORK_NAME =
            "periodic_background_task";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        btnStartTask = findViewById(R.id.btnStartTask);
        btnScheduleTask = findViewById(R.id.btnScheduleTask);
        btnCancelTask = findViewById(R.id.btnCancelTask);

        txtStatus = findViewById(R.id.txtStatus);

        btnStartTask.setOnClickListener(v ->
                startOneTimeTask()
        );

        btnScheduleTask.setOnClickListener(v ->
                schedulePeriodicTask()
        );

        btnCancelTask.setOnClickListener(v ->
                cancelPeriodicTask()
        );
    }

    private void startOneTimeTask() {

        Constraints constraints =
                new Constraints.Builder()
                        .setRequiredNetworkType(
                                NetworkType.CONNECTED
                        )
                        .build();

        OneTimeWorkRequest workRequest =
                new OneTimeWorkRequest.Builder(
                        BackgroundWorker.class
                )
                        .setConstraints(constraints)
                        .build();

        WorkManager.getInstance(this)
                .enqueue(workRequest);

        WorkManager.getInstance(this)
                .getWorkInfoByIdLiveData(workRequest.getId())
                .observe(this, workInfo -> {

                    if (workInfo != null) {

                        txtStatus.setText(
                                "One-Time Task Status: " +
                                workInfo.getState().name()
                        );
                    }
                });
    }

    private void schedulePeriodicTask() {

        PeriodicWorkRequest periodicWorkRequest =
                new PeriodicWorkRequest.Builder(
                        BackgroundWorker.class,
                        15,
                        TimeUnit.MINUTES
                ).build();

        WorkManager.getInstance(this)
                .enqueueUniquePeriodicWork(
                        PERIODIC_WORK_NAME,
                        ExistingPeriodicWorkPolicy.KEEP,
                        periodicWorkRequest
                );

        txtStatus.setText(
                "Periodic task scheduled successfully"
        );
    }

    private void cancelPeriodicTask() {

        WorkManager.getInstance(this)
                .cancelUniqueWork(PERIODIC_WORK_NAME);

        txtStatus.setText(
                "Periodic task cancellation requested"
        );
    }
}

Important: Replace the package declaration with your actual project's package name.

15. How to Test the Application

Now run the application on an Android emulator or a real device.

Test One-Time Background Work

  1. Open the application.

  2. Make sure the device has an active network connection.

  3. Click Start One-Time Task.

  4. The task enters the ENQUEUED state.

  5. When its constraints are satisfied, WorkManager starts the Worker.

  6. The status changes to RUNNING.

  7. After the demonstration task completes, the status becomes SUCCEEDED.

Test Periodic Background Work

  1. Open the application.

  2. Click Schedule Periodic Task.

  3. WorkManager schedules the periodic request.

  4. The request becomes eligible to run according to its interval and system conditions.

  5. Click Cancel Periodic Task to cancel it.

Remember that a periodic task is not guaranteed to run exactly every 15 minutes. The 15-minute value is the minimum repeat interval, not an exact execution time.

16. How to Create a Simple Android Service

WorkManager is suitable for many scheduled tasks, but it is important to understand how a Service works.

Create a new Java class named DemoService.java.

Use the following example for a short operation:

package com.example.backgroundtaskdemoapp;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DemoService extends Service {

    private ExecutorService executorService;

    @Override
    public void onCreate() {
        super.onCreate();

        executorService = Executors.newSingleThreadExecutor();
    }

    @Override
    public int onStartCommand(
            Intent intent,
            int flags,
            int startId
    ) {

        executorService.execute(() -> {

            Log.d("DemoService", "Service task started");

            try {

                Thread.sleep(3000);

                Log.d("DemoService", "Service task completed");

            } catch (InterruptedException e) {

                Thread.currentThread().interrupt();

                Log.e("DemoService", "Service interrupted", e);

            } finally {

                stopSelf(startId);
            }
        });

        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {

        if (executorService != null) {
            executorService.shutdown();
        }

        super.onDestroy();
    }
}

Understand the Important Service Methods

onCreate(): Called when the Service is first created.

onStartCommand(): Called when the Service receives a start request.

ExecutorService: Runs the demonstration operation on a background thread instead of blocking the main thread.

stopSelf(): Requests that the Service stop after its work is complete.

onBind(): Returns an IBinder when another component binds to the Service. This example does not support binding.

Register the Service in AndroidManifest.xml

Inside the application element, add:

<service
    android:name=".DemoService"
    android:exported="false" />

Start the Service from MainActivity

For this demonstration, add a button or call the following code from an Activity while the application is visible:

Intent serviceIntent = new Intent(
        MainActivity.this,
        DemoService.class
);

startService(serviceIntent);

This is a short-lived started Service example. It is not a replacement for WorkManager or a long-running Foreground Service.

For user-visible work that must continue as a foreground operation, use the Foreground Service APIs and follow the required notification, permission, service-type, and Android version rules.

17. What Are Scheduled Tasks in Android?

Scheduled tasks are operations configured to execute later or repeatedly.

Android offers several scheduling options depending on the requirements.

One-Time Work

Use OneTimeWorkRequest when a task needs to execute once.

Example: Uploading a document after an internet connection becomes available.

Periodic Work

Use PeriodicWorkRequest when a task needs to repeat over time.

Example: Synchronizing application data periodically.

JobScheduler

JobScheduler is an Android platform API for scheduling jobs based on system conditions.

WorkManager uses platform scheduling mechanisms where appropriate and provides a higher-level API for persistent work.

AlarmManager

AlarmManager is useful for time-based alarms, including use cases that need more precise timing.

Exact alarms are subject to Android permissions and restrictions. They should not be used as a general replacement for WorkManager.

18. Common Background Work Errors and Solutions

Error 1: Background Task Is Not Running

Possible reasons:

  • Required network connection is unavailable.

  • Device conditions do not satisfy the constraints.

  • The task is still waiting in the WorkManager queue.

Solution: Check the WorkInfo state and verify the configured constraints.

Error 2: Service Is Not Starting

Possible reasons:

  • Incorrect service declaration.

  • Background execution restrictions.

  • The application is trying to start a restricted Service from the background.

Solution: Check the manifest and follow the applicable Android background execution rules.

Error 3: Periodic Task Is Not Running at an Exact Time

Possible reason: WorkManager does not guarantee exact periodic execution.

Solution: Use WorkManager for deferrable work. If the use case genuinely requires an exact alarm, evaluate AlarmManager and its permissions and restrictions.

Error 4: Application Shows an ANR Error

Possible reason: Heavy work is running on the main thread.

Solution: Move blocking operations to a Worker or a suitable background executor.

19. Best Practices for Android Background Tasks

Follow these practices when building production Android applications:

  • Prefer WorkManager for persistent, deferrable tasks.

  • Use Services only when their behavior is actually required.

  • Use Foreground Services for ongoing, user-noticeable operations.

  • Never perform long-running blocking operations on the main thread.

  • Add constraints when tasks depend on network or device conditions.

  • Handle failures and retries carefully.

  • Cancel work when it is no longer required.

  • Avoid unnecessary periodic execution to reduce battery consumption.

  • Do not assume scheduled tasks run at an exact time.

  • Follow Android's foreground service permission and type requirements.

Conclusion

In this tutorial, we learned how background work is handled in Android applications using Java.

We covered Android Services, Foreground Services, WorkManager, Worker, WorkRequest, Constraints, OneTimeWorkRequest, PeriodicWorkRequest, and task cancellation.

We also created a practical Background Task Demo App that schedules one-time and periodic background tasks.

Finally, we implemented a simple Service to understand how Service components work.

These concepts are useful for developing file upload applications, data synchronization systems, reminder applications, media applications, and other Android projects.

Frequently Asked Questions

1. What is background work in Android?

Background work refers to operations performed outside the application's main user interface workflow.

2. What is WorkManager in Android?

WorkManager is an Android Jetpack library used to schedule reliable and deferrable background tasks.

3. What is the difference between Service and WorkManager?

A Service is an Android application component used for service-based operations, while WorkManager schedules persistent background tasks that can run when system conditions allow.

4. What is a Worker class?

A Worker class contains the background task logic and implements the doWork() method.

5. What is OneTimeWorkRequest?

OneTimeWorkRequest schedules a background task to execute once.

6. What is PeriodicWorkRequest?

PeriodicWorkRequest schedules a background task to repeat over a specified interval. Its minimum repeat interval is 15 minutes.

7. Can WorkManager run tasks when an application is closed?

Yes. WorkManager can schedule persistent work that remains eligible for execution when the application is no longer open. Actual execution still depends on system conditions and restrictions.

8. Does a Service automatically run on a background thread?

No. A Service runs on the application's main thread by default. Developers must use a background thread or another suitable asynchronous API for blocking work.

←
Post 32 of 40
→