JobScheduler là một dịch vụ hệ thống Android, được giới thiệu trong API 21 (Android 5.0 Lollipop), cho phép các ứng dụng lên lịch thực hiện các tác vụ nền dựa trên các điều kiện xác định. Không giống như AlarmManager, JobScheduler không yêu cầu thời gian thực thi chính xác — hệ thống tự xác định thời điểm tối ưu bằng cách kết hợp yêu cầu của ứng dụng với trạng thái hiện tại của thiết bị. Theo Android Developers, 2026, dịch vụ này hỗ trợ các tiêu chí về mạng, sạc, trạng thái lưu trữ và thời gian thiết bị không hoạt động.
Những điểm chính
JobScheduler là một dịch vụ hệ thống Android nhóm nhiều tác vụ nền thành các lô để giảm tiêu thụ điện năng. Thay vì mỗi ứng dụng đánh thức thiết bị để thực hiện tác vụ riêng, JobScheduler nhóm chúng lại và thực thi vào thời điểm tối ưu khi thiết bị đã hoạt động. Điều này kéo dài đáng kể thời lượng pin.
Trước JobScheduler, các nhà phát triển sử dụng AlarmManager và BroadcastReceiver cho các tác vụ nền. Vấn đề của cách tiếp cận này là mỗi ứng dụng đánh thức thiết bị độc lập, dẫn đến hao pin nhanh chóng. JobScheduler đã giải quyết vấn đề này bằng cách giới thiệu một cửa sổ thực thi hàng loạt, trong đó hệ thống khởi chạy đồng thời tất cả các tác vụ đã lên lịch của các ứng dụng khác nhau.
Nguyên tắc hoạt động dựa trên đối tượng JobInfo mà ứng dụng truyền cho JobScheduler. Hệ thống lưu tác vụ và thực thi nó khi tất cả các điều kiện được chỉ định được đáp ứng. Không giống như WorkManager, JobScheduler không đảm bảo khởi động lại khi gặp lỗi — nếu một tác vụ ném ra ngoại lệ, nhà phát triển phải tự lên lịch lại thủ công.
JobScheduler sử dụng kiến trúc dựa trên JobService và JobInfo. JobInfo mô tả tác vụ và các điều kiện của nó, JobService chứa logic thực thi. Ứng dụng đăng ký tác vụ qua getSystemService(JobScheduler.class) và gọi schedule(jobInfo). Hệ thống đảm nhận việc lập lịch.
JobService là một lớp trừu tượng kế thừa Service. Nó có hai phương thức chính: onStartJob (được gọi khi tác vụ bắt đầu) và onStopJob (được gọi khi hệ thống dừng tác vụ cưỡng chế). JobInfo được tạo qua Builder và chứa tất cả các tham số tác vụ: định danh, điều kiện, ràng buộc thời gian.
public class SyncJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
// Chạy trên luồng chính
Thread thread = new Thread(() -> {
performSync();
jobFinished(params, false);
});
thread.start();
return true; // true = công việc tiếp tục
}
@Override
public boolean onStopJob(JobParameters params) {
return true; // true = lên lịch lại tác vụ
}
}
JobScheduler cho phép đặt nhiều tiêu chí cùng lúc: loại mạng (NETWORK_TYPE_ANY, NOT_ROAMING, UNMETERED), trạng thái sạc (requiresCharging), mức pin (requiresBatteryNotLow), trạng thái lưu trữ (requiresStorageNotLow) và chế độ không hoạt động (requiresDeviceIdle). Tác vụ chỉ chạy khi tất cả các tiêu chí được đáp ứng.
JobInfo.Builder cung cấp các cài đặt linh hoạt cho mỗi tác vụ nền. Sự kết hợp đúng đắn của các tham số cho phép cân bằng giữa tính kịp thời của thực thi và mức tiêu thụ điện năng.
| Phương thức | Mô tả | Ví dụ |
|---|---|---|
| setRequiredNetworkType | Loại mạng yêu cầu | NETWORK_TYPE_UNMETERED |
| setRequiresCharging | Thiết bị đang sạc | true |
| setRequiresDeviceIdle | Thiết bị không hoạt động | true |
| setOverrideDeadline | Thời gian chờ tối đa (ms) | 300000 |
| setMinimumLatency | Độ trễ tối thiểu (ms) | 60000 |
| setPeriodic | Thực thi định kỳ (ms) | 3600000 |
| setBackoffCriteria | Chiến lược thử lại khi lỗi | LINEAR / EXPONENTIAL |
Một tham số quan trọng là setOverrideDeadline. Nếu chỉ định thời hạn, hệ thống đảm bảo tác vụ sẽ chạy vào thời điểm đó, ngay cả khi không phải tất cả điều kiện đều được đáp ứng. Điều này hữu ích cho các tác vụ có thời gian quan trọng, như đồng bộ hóa mỗi 6 giờ.
Một kịch bản điển hình là đồng bộ dữ liệu khi kết nối Wi-Fi và sạc thiết bị. Ứng dụng tạo JobInfo với các tiêu chí tương ứng và truyền nó cho JobScheduler. Hệ thống chạy tác vụ khi các điều kiện thuận lợi được đáp ứng.
ComponentName serviceName = new ComponentName(this, SyncJobService.class);
JobInfo jobInfo = new JobInfo.Builder(JOB_ID_SYNC, serviceName)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.setRequiresBatteryNotLow(true)
.setOverrideDeadline(6 * 60 * 60 * 1000) // 6 giờ
.build();
JobScheduler scheduler = (JobScheduler)
getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
JobService phải được đăng ký trong AndroidManifest.xml với quyền BIND_JOB_SERVICE. Trong phương thức onStartJob, điều quan trọng là gọi jobFinished sau khi hoàn thành công việc — nếu không, hệ thống sẽ coi tác vụ đang chạy vô thời hạn và có thể dừng nó cưỡng chế.
<service
android:name=".SyncJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
JobScheduler có một số hạn chế. Thứ nhất, nó chỉ khả dụng trên Android 5+ — các phiên bản cũ hơn cần giải pháp thay thế. Thứ hai, hệ thống có thể trì hoãn các tác vụ của ứng dụng ít được sử dụng, đặc biệt trên Android 9+ với App Standby Buckets. Thứ ba, JobScheduler không cung cấp cơ chế khởi động lại đảm bảo khi gặp lỗi.
Google khuyến nghị sử dụng WorkManager thay vì sử dụng trực tiếp JobScheduler. WorkManager sử dụng JobScheduler bên trong trên Android 5+, nhưng thêm hỗ trợ cho các phiên bản cũ, đảm bảo thực thi, chuỗi tác vụ và quan sát trạng thái qua LiveData. Nếu ứng dụng của bạn chỉ hỗ trợ Android 8+ và không yêu cầu logic tác vụ nền phức tạp, JobScheduler vẫn có thể hợp lý.
Để gỡ lỗi JobScheduler, sử dụng dumpsys jobscheduler qua ADB: lệnh hiển thị tất cả các tác vụ đã lên lịch, trạng thái, thời gian còn lại và lịch sử thực thi. Cho một ứng dụng cụ thể: adb shell dumpsys jobscheduler | grep package_name. Điều này cho phép kiểm tra xem tác vụ đã được đăng ký chưa, điều kiện nào được đặt và tại sao nó không chạy. Bạn cũng có thể sử dụng JobScheduler.getPendingJob() để kiểm tra trạng thái tác vụ theo chương trình. Ngoài ra, Android Studio Profiler có thể được sử dụng để phân tích mức tiêu thụ điện năng trong quá trình thực thi tác vụ. Đối với các ứng dụng trên Android 5+, JobScheduler vẫn là công cụ đáng tin cậy cho các tác vụ nền không chính xác với điều kiện mạng và sạc.
Theo mặc định, JobService chạy trên luồng chính, do đó tất cả các hoạt động chặn đều yêu cầu tạo một luồng riêng hoặc sử dụng AsyncTask. Không giống WorkManager, JobScheduler không cung cấp nhóm luồng tích hợp. Nhà phát triển tự quản lý các luồng và đồng bộ hóa. Nên sử dụng ThreadPoolExecutor cho các tác vụ song song và Handler để giao tiếp với luồng chính. Trong onStopJob, điều quan trọng là ngắt các luồng đang chạy đúng cách để tránh rò rỉ.
JobScheduler hỗ trợ các tác vụ định kỳ qua phương thức setPeriodic(long intervalMillis). Khoảng thời gian tối thiểu là 15 phút. Tuy nhiên, không giống WorkManager, JobScheduler không đảm bảo tuân thủ khoảng thời gian chính xác — hệ thống có thể dịch chuyển thời gian thực thi để gộp với các tác vụ khác. Phương thức setPeriodic cũng không hỗ trợ khoảng thời gian linh hoạt (cửa sổ linh hoạt), xuất hiện trong các phiên bản API sau này. Để thực thi định kỳ chính xác, hãy sử dụng AlarmManager kết hợp với BroadcastReceiver.
Bắt đầu từ Android 9, Google đã giới thiệu App Standby Buckets, phân loại ứng dụng theo tần suất sử dụng: Active, Working Set, Frequent, Rare. Các ứng dụng trong danh mục Rare bị trì hoãn thực thi tác vụ JobScheduler lên đến 24 giờ. Nhà phát triển chỉ có thể ảnh hưởng đến danh mục thông qua chất lượng ứng dụng — các cơ chế hệ thống tự động tăng mức ưu tiên của các ứng dụng mà người dùng tương tác thường xuyên. JobScheduler xem xét phân loại này và một tác vụ từ ứng dụng Rare sẽ chỉ được thực thi trong cửa sổ bảo trì. Đối với các ứng dụng trong danh mục Active (được sử dụng thường xuyên nhất), độ trễ là tối thiểu và các tác vụ chạy gần như ngay lập tức khi các điều kiện được đáp ứng.
Đối với các tác vụ định kỳ có thời gian chính xác, JobScheduler không phù hợp — hãy sử dụng AlarmManager. Đối với các tác vụ ngắn một lần — Foreground Service với thông báo. JobScheduler là tối ưu cho các tác vụ mà hiệu quả năng lượng quan trọng hơn độ chính xác về thời gian: đồng bộ hóa, tải bản cập nhật, xử lý dữ liệu hàng loạt. Lựa chọn đúng công cụ làm việc nền ảnh hưởng trực tiếp đến trải nghiệm người dùng và thời lượng pin của thiết bị. Kết luận cuối cùng: sử dụng JobScheduler cho xử lý hàng loạt với điều kiện, AlarmManager cho các tác vụ theo lịch và WorkManager như một bộ lập lịch vạn năng.
Các câu hỏi thường gặp
Đúng, JobScheduler nhóm các tác vụ từ các ứng dụng khác nhau thành các lô và thực thi chúng cùng nhau. Đây là lợi thế chính so với AlarmManager: thay vì mỗi ứng dụng đánh thức thiết bị riêng lẻ, hệ thống đánh thức bộ xử lý một lần và xử lý tất cả các tác vụ đã lên lịch.
Nếu jobFinished không được gọi trong một khoảng thời gian hợp lý, hệ thống có thể cưỡng chế gọi onStopJob và kết thúc tác vụ. Nên hoàn thành một tác vụ trong vòng vài phút và luôn gọi jobFinished khi kết thúc.
Trong Doze Mode, JobScheduler hoãn tất cả các tác vụ cho đến cửa sổ bảo trì tiếp theo, diễn ra định kỳ. Sử dụng setOverrideDeadline đảm bảo tác vụ sẽ được thực thi có tính đến các cửa sổ này, nhưng không nhất thiết vào thời gian chính xác.
WorkManager là một thư viện sử dụng JobScheduler bên trong trên Android 5+. WorkManager thêm đảm bảo thực thi, hỗ trợ các phiên bản cũ (API 14+), chuỗi Worker, quan sát trạng thái qua LiveData/Flow và tự động thử lại khi gặp lỗi.
Để hủy, sử dụng scheduler.cancel(JOB_ID) cho một tác vụ cụ thể hoặc scheduler.cancelAll() cho tất cả các tác vụ của ứng dụng. Đảm bảo ID công việc khớp với ID đã chỉ định khi tạo JobInfo, nếu không tác vụ sẽ không bị hủy.
Các nhà phát triển cần hiểu rằng JobScheduler là một API hệ thống cấp thấp được thiết kế cho các nhóm có kinh nghiệm muốn kiểm soát hoàn toàn các tác vụ nền trên thiết bị. Đối với hầu hết các ứng dụng, WorkManager cung cấp cùng chức năng với API đơn giản hơn, an toàn hơn và hiện đại hơn cho Android.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm