Hạn chế của hệ thống đối với công việc ở chế độ nền

Các quy trình trong nền có thể tốn nhiều bộ nhớ và pin. Ví dụ: một thông báo truyền phát ngầm có thể bắt đầu nhiều quy trình trong nền đã đăng ký lắng nghe nó, ngay cả khi các quy trình đó có thể không hiệu quả. Thông tin này có thể có ảnh hưởng đáng kể đến cả hiệu suất thiết bị và trải nghiệm người dùng.

Để tránh các hạn chế của hệ thống, hãy nhớ sử dụng API phù hợp cho tác vụ trong nền. Chiến lược phát hành đĩa đơn Tài liệu Tổng quan về tác vụ trong nền giúp bạn chọn API phù hợp với nhu cầu của bạn.

Các hạn chế do người dùng khởi tạo

Nếu một ứng dụng cho thấy một số hành vi xấu như mô tả trong Android vitals, hệ thống sẽ nhắc người dùng hạn chế quyền truy cập của ứng dụng đó vào các tài nguyên hệ thống.

Nếu nhận thấy một ứng dụng đang sử dụng quá nhiều tài nguyên, hệ thống sẽ thông báo người dùng và cung cấp cho người dùng tùy chọn hạn chế hành động của ứng dụng. Những hành vi có thể kích hoạt thông báo bao gồm:

  1. Quá nhiều khoá chế độ thức: 1 phần khoá chế độ thức bị giữ trong một giờ khi màn hình đang bật đang tắt
  2. Quá nhiều dịch vụ nền: Nếu ứng dụng nhắm đến các cấp độ API thấp hơn 26 và có quá nhiều dịch vụ nền

Các hạn chế chính xác do nhà sản xuất thiết bị quyết định. Cho ví dụ: trên các bản dựng AOSP, các ứng dụng bị hạn chế không thể chạy công việc, kích hoạt chuông báo hoặc sử dụng mạng, trừ phi ứng dụng chạy trên nền trước.

Quy định hạn chế đối với việc nhận thông báo về hoạt động mạng

Ứng dụng không nhận được thông báo CONNECTIVITY_ACTION nếu đăng ký nhận thông báo trong tệp kê khai và các quy trình phụ thuộc vào thông báo truyền tin này sẽ không bắt đầu. Điều này có thể gây ra vấn đề cho những ứng dụng muốn theo dõi mạng các thay đổi hoặc thực hiện các hoạt động mạng hàng loạt khi thiết bị kết nối với một mạng không đo lượng dữ liệu. Đã có sẵn một số giải pháp để khắc phục hạn chế này tồn tại trong khung Android, nhưng việc chọn mã phù hợp sẽ phụ thuộc vào những gì bạn muốn ứng dụng của mình hoàn thành.

Lên lịch cho công việc trên các kết nối không đo lượng dữ liệu

Khi tạo WorkRequest, hãy thêm NetworkType.UNMETERED Constraint.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

Khi các điều kiện cho công việc được đáp ứng, ứng dụng sẽ nhận được một lệnh gọi lại để chạy phương thức doWork() trong lớp Worker được chỉ định.

Giám sát khả năng kết nối mạng trong khi ứng dụng đang chạy

Các ứng dụng đang chạy vẫn có thể theo dõi CONNECTIVITY_CHANGE bằng đã đăng ký BroadcastReceiver. Tuy nhiên, API ConnectivityManager cung cấp một phương thức mạnh mẽ hơn để chỉ yêu cầu gọi lại khi mạng được chỉ định được đáp ứng.

Đối tượng NetworkRequest xác định các thông số của lệnh gọi lại mạng trong các điều khoản của NetworkCapabilities. Bạn tạo các đối tượng NetworkRequest bằng lớp NetworkRequest.Builder. registerNetworkCallback sau đó truyền đối tượng NetworkRequest đến hệ thống. Khi mạng đáp ứng điều kiện, ứng dụng sẽ nhận được lệnh gọi lại để thực thi lệnh gọi lại Phương thức onAvailable() được xác định trong ConnectivityManager.NetworkCallback.

Ứng dụng sẽ tiếp tục nhận được các lệnh gọi lại cho đến khi ứng dụng thoát hoặc gọi unregisterNetworkCallback().

Quy định hạn chế đối với việc nhận thông báo về hình ảnh và video

Ứng dụng không thể gửi hoặc nhận ACTION_NEW_PICTURE hoặc Truyền phát ACTION_NEW_VIDEO. Quy định hạn chế này giúp giảm bớt những tác động đến hiệu suất và trải nghiệm người dùng khi một số ứng dụng phải đánh thức để xử lý một hình ảnh hoặc video mới.

Xác định những tổ chức phát hành nội dung đã kích hoạt công việc

WorkerParameters cho phép ứng dụng của bạn nhận thông tin hữu ích về những gì các tổ chức phát hành nội dung và URI đã kích hoạt công việc:

List<Uri> getTriggeredContentUris()

Trả về danh sách URI đã kích hoạt công việc. Trường này trống nếu không có URI nào kích hoạt tác vụ (ví dụ: tác vụ đã được kích hoạt do thời hạn hoặc một số lý do khác) hoặc số URI thay đổi lớn hơn 50.

List<String> getTriggeredContentAuthorities()

Trả về một danh sách chuỗi của các tổ chức phát hành nội dung đã kích hoạt tác vụ. Nếu danh sách được trả về không phải là danh sách trống, hãy sử dụng getTriggeredContentUris() để truy xuất thông tin chi tiết về các URI thay đổi.

Mã mẫu sau đây ghi đè phương thức CoroutineWorker.doWork() đồng thời ghi lại những tổ chức phát hành nội dung và URI đã kích hoạt công việc đó:

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

Kiểm thử ứng dụng theo các quy định hạn chế của hệ thống

Tối ưu hoá ứng dụng của bạn để chạy trên thiết bị có bộ nhớ thấp hoặc trong điều kiện bộ nhớ thấp, có thể cải thiện hiệu suất và trải nghiệm người dùng. Xoá các phần phụ thuộc ở chế độ nền các dịch vụ và broadcast receiver ngầm đã đăng ký tệp kê khai có thể giúp ứng dụng của bạn chạy tốt hơn trên các thiết bị như vậy. Bạn nên tối ưu hoá ứng dụng để chạy nếu không sử dụng hoàn toàn các quy trình nền này.

Một số lệnh Cầu gỡ lỗi Android (ADB) khác có thể giúp bạn kiểm thử ứng dụng khi các tiến trình nền đó bị tắt:

  • Để mô phỏng các điều kiện trong đó thông báo truyền phát ngầm và dịch vụ nền không có sẵn, hãy nhập lệnh sau:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • Để bật lại các thông báo truyền phát ngầm và dịch vụ nền, hãy nhập các thông tin sau :

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

Tối ưu hoá hơn nữa ứng dụng của bạn

Để biết những cách hay khác giúp tối ưu hoá các tác vụ trong nền, hành vi, xem Tối ưu hoá mức sử dụng pin cho API lên lịch tác vụ tài liệu.