Please allow camera Permissions to continue là gì

Mọi ứng dụng Android đều chạy trong một hộp cát bị giới hạn về khả năng truy cập. Nếu ứng dụng của bạn cần sử dụng tài nguyên hoặc thông tin bên ngoài hộp cát, thì bạn có thể khai báo một quyền và thiết lập yêu cầu cấp quyền truy cập này. Các bước này là một phần trong quy trình sử dụng quyền.

Nếu bạn khai báo bất kỳ quyền nguy hiểm nào và nếu ứng dụng được cài đặt trên thiết bị chạy Android 6.0 (API cấp 23) trở lên, bạn phải yêu cầu các quyền nguy hiểm đó trong thời gian chạy bằng cách làm theo các bước trong hướng dẫn này.

Nếu bạn không khai báo bất kỳ quyền nguy hiểm nào hoặc nếu ứng dụng được cài đặt trên thiết bị chạy Android 5.1 (API cấp 22) trở xuống, thì các quyền đó sẽ tự động được cấp và bạn không cần hoàn thành bất kỳ bước nào còn lại trên trang này.

Nguyên tắc cơ bản

Nguyên tắc cơ bản để yêu cầu cấp quyền trong thời gian chạy bao gồm:

  • Yêu cầu cấp quyền trong bối cảnh khi người dùng bắt đầu tương tác với tính năng yêu cầu quyền đó.
  • Không chặn người dùng. Luôn cung cấp tuỳ chọn huỷ quy trình giao diện hướng dẫn người dùng liên quan đến quyền.
  • Nếu người dùng từ chối hoặc thu hồi quyền mà một tính năng cần đến, nên xuống cấp nhẹ nhàng ứng dụng để người dùng tiếp tục sử dụng ứng dụng, có thể là bằng cách tắt tính năng yêu cầu cấp quyền đó.
  • Không giả định bất kỳ hành vi hệ thống nào. Ví dụ: không giả định rằng quyền xuất hiện trong cùng một nhóm quyền. Nhóm quyền chỉ giúp hệ thống tối thiểu hoá số lượng hộp thoại hệ thống hiển thị với người dùng khi ứng dụng yêu cầu cấp quyền có liên quan chặt chẽ.

Quy trình yêu cầu cấp quyền

Trước khi bạn khai báo và yêu cầu cấp quyền khi bắt đầu chạy trong ứng dụng, hãy đánh giá xem liệu ứng dụng có cần làm như vậy hay không. Bạn có thể thực hiện nhiều trường hợp sử dụng trong ứng dụng của mình, chẳng hạn như chụp ảnh, tạm dừng phát lại nội dung nghe nhìn và hiển thị quảng cáo phù hợp mà không cần khai báo bất kỳ quyền nào.

Nếu bạn kết luận rằng ứng dụng cần khai báo và yêu cầu cấp quyền khi bắt đầu chạy, thì hoàn tất các bước sau:

  1. Trong tệp kê khai của ứng dụng, khai báo các quyền mà ứng dụng của bạn có thể yêu cầu.
  2. Thiết kế trải nghiệm người dùng trên ứng dụng của bạn để hành động cụ thể trong ứng dụng liên kết với các quyền khi bắt đầu chạy cụ thể. Người dùng phải biết hành động nào sẽ yêu cầu họ cấp quyền cho ứng dụng truy cập vào dữ liệu riêng tư của người dùng.
  3. Chờ người dùng gọi ra nhiệm vụ hoặc thao tác trong ứng dụng mà yêu cầu quyền truy cập vào dữ liệu riêng tư của người dùng. Tại thời điểm đó, ứng dụng của bạn có thể yêu cầu cấp quyền khi bắt đầu chạy cần đến để truy cập dữ liệu đó.
  4. Kiểm tra xem liệu người dùng đã cấp quyền khi bắt đầu chạy mà ứng dụng của bạn yêu cầu chưa. Nếu có, ứng dụng của bạn có thể truy cập dữ liệu riêng tư của người dùng. Nếu không, chuyển sang bước tiếp theo.

    Bạn phải kiểm tra xem liệu mình có quyền đó hay không mỗi lần thực hiện một thao tác yêu cầu quyền đó.

  5. Kiểm tra liệu ứng dụng của bạn có cho biết lý do hay không, giải thích với người dùng tại sao ứng dụng của bạn cần người dùng cấp quyền cụ thể khi bắt đầu chạy. Nếu hệ thống xác định rằng ứng dụng không nên cho biết lý do, thì tiếp tục thực hiện ngay bước tiếp theo mà không cần hiển thị thành phần giao diện người dùng.

    Tuy nhiên, nếu hệ thống xác định rằng ứng dụng của bạn cần cho biết lý do, thì nên trình bày lý do với người dùng trong một phần tử giao diện người dùng. Lý do này phải giải thích rõ ràng ứng dụng của bạn đang cố truy cập dữ liệu nào và ứng dụng cung cấp quyền lợi gì cho người dùng nếu họ cấp quyền khi bắt đầu chạy. Sau khi người dùng xác nhận lý do, tiếp tục chuyển sang bước tiếp theo.

  6. Yêu cầu cấp quyền khi bắt đầu chạy mà ứng dụng của bạn cần đến để truy cập dữ liệu riêng tư của người dùng. Hệ thống sẽ hiển thị lời nhắc cấp quyền khi bắt đầu chạy, chẳng hạn như lời nhắc được hiển thị trên trang tổng quan về cấp quyền.

  7. Kiểm tra phản hồi của người dùng, xem họ đã chọn cấp hay từ chối cấp quyền khi bắt đầu chạy.

  8. Nếu người dùng đã cấp quyền cho ứng dụng, bạn có thể truy cập vào dữ liệu riêng tư của người dùng. Thay vào đó, nếu người dùng từ chối cấp quyền, nhẹ nhàng xuống cấp trải nghiệm ứng dụng của bạn để cung cấp chức năng cho người dùng, ngay cả khi không có thông tin được bảo vệ bằng quyền đó.

Hình 1 minh hoạ quy trình làm việc và tập hợp các quyết định liên quan đến quy trình này:

HÌnh 1. Sơ đồ cho thấy quy trình khai báo và yêu cầu cấp quyền khi bắt đầu chạy trên Android.

Xác định xem liệu ứng dụng của bạn đã được cấp quyền hay chưa

Để kiểm tra xem người dùng đã cấp cho ứng dụng một quyền cụ thể hay chưa, chuyển quyền đó vào phương thức ContextCompat.checkSelfPermission(). Phương thức này trả về PERMISSION_GRANTED hoặc PERMISSION_DENIED, tuỳ thuộc vào việc ứng dụng của bạn có quyền hay không.

Giải thích vì sao ứng dụng của bạn cần quyền truy cập

Hộp thoại cấp quyền được hệ thống hiển thị khi bạn gọi requestPermissions() cho biết ứng dụng muốn có quyền gì, nhưng không cho biết lý do vì sao. Trong một số trường hợp, người dùng có thể thấy khó hiểu. Nên giải thích cho người dùng tại sao ứng dụng muốn có quyền trước khi bạn gọi requestPermissions().

Nghiên cứu cho thấy rằng người dùng cảm thấy thoải mái hơn với các yêu cầu cấp quyền nếu họ biết tại sao ứng dụng cần các yêu cầu đó. Một nghiên cứu về người dùng cho thấy:

...việc người dùng sẵn sàng cấp quyền nhất định cho một ứng dụng di động nhất định chịu ảnh hưởng rất lớn bởi mục đích liên quan đến quyền đó. Ví dụ: việc người dùng sẵn sàng cấp quyền truy cập vào thông tin vị trí của họ là khác nhau tuỳ thuộc vào việc liệu yêu cầu có cần để hỗ trợ chức năng cốt lõi của ứng dụng hay không hoặc liệu yêu cầu đó là để chia sẻ thông tin này với một mạng quảng cáo hay một công ty phân tích.1

Sau khi cộng tác với nhiều người khác để nghiên cứu về chủ đề này, Giáo sư Jason Hong đến từ CMU đã kết luận rằng: nói chung,

...khi mọi người biết lý do ứng dụng sử dụng những thông tin nhạy cảm như vị trí của họ — ví dụ: để quảng cáo nhắm mục tiêu — thì họ sẽ cảm thấy thoải mái hơn so với khi chỉ được thông báo một ứng dụng đang sử dụng thông tin vị trí của họ.1

Do đó, nếu bạn chỉ sử dụng một phần các lệnh gọi API thuộc một nhóm quyền, thì việc này sẽ giúp bạn liệt kê rõ ràng những quyền bạn đang sử dụng và lý do tại sao. Ví dụ:

  • Nếu bạn chỉ sử dụng vị trí gần đúng, cho người dùng biết điều này trong phần mô tả ứng dụng hoặc trong các bài viết trợ giúp về ứng dụng của bạn.
  • Nếu bạn cần truy cập vào tin nhắn SMS để nhận mã xác thực bảo vệ người dùng khỏi hành vi gian lận, cho người dùng biết điều này trong phần mô tả ứng dụng và khi ứng dụng của bạn cần truy cập dữ liệu lần đầu tiên.

    Lưu ý: Nếu ứng dụng của bạn nhắm đến Android 8.0 (API cấp 26) trở lên, không nên yêu cầu cấp quyền READ_SMS xác minh thông tin xác thực của người dùng. Thay vào đó, tạo mã thông báo dành riêng cho ứng dụng bằng createAppSpecificSmsToken(), sau đó chuyển mã thông báo này sang một ứng dụng hoặc dịch vụ khác có khả năng gửi tin nhắn SMS xác minh.

Trong một số tình huống nhất định, việc cho người dùng biết về quyền truy cập dữ liệu nhạy cảm theo thời gian thực cũng là một lợi thế. Ví dụ: nếu đang truy cập vào camera hoặc micrô, bạn nên cho người dùng biết bằng biểu tượng thông báo ở một nơi nào đó trong ứng dụng hoặc trong khay thông báo (nếu ứng dụng đang chạy ở chế độ nền), để bạn không có vẻ như đang lén lút thu thập dữ liệu.

Cuối cùng, nếu cần một quyền để khiến điều gì đó trong ứng dụng hoạt động, nhưng người dùng lại không rõ lý do, hãy tìm cách cho người dùng biết tại sao bạn cần các quyền truy cập thông tin nhạy cảm nhất.

Nếu phương thức ContextCompat.checkSelfPermission() trả về PERMISSION_DENIED, gọi shouldShowRequestPermissionRationale(). Nếu phương thức này trả về true, hiển thị giao diện hướng dẫn người dùng cho người dùng. Trong giao diện người dùng này, mô tả lý do tính năng, mà người dùng muốn bật, cần có một quyền cụ thể.

Ngoài ra, nếu ứng dụng của bạn yêu cầu một quyền liên quan đến vị trí, micrô hoặc camera, hãy cân nhắc giải thích lý do ứng dụng của bạn cần quyền truy cập vào thông tin này.

Yêu cầu cấp quyền

Hãy yêu cầu cấp quyền sau khi người dùng xem giao diện người dùng hướng dẫn hoặc giá trị trả về của shouldShowRequestPermissionRationale() cho biết bạn không cần hiển thị giao diện người dùng hướng dẫn lần này. Người dùng sẽ thấy hộp thoại cấp quyền của hệ thống, trong đó họ có thể chọn có cấp một quyền cụ thể cho ứng dụng của bạn hay không.

Thường thì bạn tự quản lý mã yêu cầu trong yêu cầu cấp quyền và đưa mã yêu cầu này vào logic gọi lại quyền của mình. Một tuỳ chọn khác là sử dụng hợp đồng RequestPermission, nằm trong thư viện AndroidX, trong đó bạn cho phép hệ thống quản lý mã yêu cầu cấp quyền cho bạn. Vì việc sử dụng hợp đồng RequestPermission đơn giản hoá logic, do vậy bạn nên sử dụng hợp đồng này mỗi khi có thể.

Cho phép hệ thống quản lý mã yêu cầu cấp quyền

Để cho phép hệ thống quản lý mã yêu cầu dược liên kết với yêu cầu cấp quyền, thêm các phần phụ thuộc có trong những thư viện sau vào tệp build.gradle của mô-đun:

Sau đó, bạn có thể sử dụng một trong các lớp sau:

Các bước sau đây cho biết cách sử dụng hợp đồng RequestPermission. Quy trình gần giống với quy trình cho hợp đồng RequestMultiplePermissions.

  1. Trong hoạt động hoặc logic khởi chạy mảnh của bạn, chuyển việc triển khai ActivityResultCallback vào lệnh gọi đến registerForActivityResult(). ActivityResultCallback xác định cách ứng dụng của bạn xử lý phản hồi của người dùng với yêu cầu cấp quyền.

    Duy trì tham chiếu đến giá trị trả về của registerForActivityResult(), thuộc loại ActivityResultLauncher.

  2. Để hiển thị hộp thoại cấp quyền của hệ thống khi cần, gọi phương thức launch() trên thực thể của ActivityResultLauncher mà bạn đã lưu ở bước trước.

    Sau khi launch() được gọi, hộp thoại cấp quyền của hệ thống sẽ xuất hiện. Khi người dùng chọn, hệ thống sẽ không đồng bộ gọi cách triển khai ActivityResultCallback đã được bạn xác định ở bước trước.

    Lưu ý: Ứng dụng của bạn không thể tuỳ chỉnh hộp thoại xuất hiện khi bạn gọi launch(). Để cung cấp thêm thông tin hoặc ngữ cảnh đến người dùng, thay đổi giao diện người dùng của ứng dụng để người dùng dễ dàng hiểu lý do vì sao một tính năng trong ứng dụng của bạn cần đến một quyền cụ thể. Ví dụ: có lẽ bạn nên thay đổi văn bản trong nút để bật tính năng này.

    Ngoài ra, văn bản trong hộp thoại cấp quyền của hệ thống tham chiếu đến nhóm quyền được liên kết với quyền mà bạn đã yêu cầu. Nhóm quyền này được thiết kế để giúp hệ thống dễ sử dụng và ứng dụng của bạn không nên dựa vào các quyền nằm bên trong hoặc bên ngoài một nhóm quyền cụ thể.

Đoạn mã sau đây cho thấy cách xử lý phản hồi cấp quyền:

// Register the permissions callback, which handles the user's response to the // system permissions dialog. Save the return value, an instance of // ActivityResultLauncher. You can use either a val, as shown in this snippet, // or a lateinit var in your onAttach() or onCreate() method. val requestPermissionLauncher = registerForActivityResult(RequestPermission() ) { isGranted: Boolean -> if (isGranted) { // Permission is granted. Continue the action or workflow in your // app. } else { // Explain to the user that the feature is unavailable because the // features requires a permission that the user has denied. At the // same time, respect the user's decision. Don't link to system // settings in an effort to convince the user to change their // decision. } }
// Register the permissions callback, which handles the user's response to the // system permissions dialog. Save the return value, an instance of // ActivityResultLauncher, as an instance variable. private ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(new RequestPermission(), isGranted -> { if (isGranted) { // Permission is granted. Continue the action or workflow in your // app. } else { // Explain to the user that the feature is unavailable because the // features requires a permission that the user has denied. At the // same time, respect the user's decision. Don't link to system // settings in an effort to convince the user to change their // decision. } });

Đoạn mã này minh hoạ quy trình đề xuất để kiểm tra một quyền và yêu cầu người dùng cấp quyền khi cần:

when { ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION ) == PackageManager.PERMISSION_GRANTED -> { // You can use the API that requires the permission. } shouldShowRequestPermissionRationale(...) -> { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected. In this UI, // include a "cancel" or "no thanks" button that allows the user to // continue using your app without granting the permission. showInContextUI(...) } else -> { // You can directly ask for the permission. // The registered ActivityResultCallback gets the result of this request. requestPermissionLauncher.launch( Manifest.permission.REQUESTED_PERMISSION) } }
if (ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION) == PackageManager.PERMISSION_GRANTED) { // You can use the API that requires the permission. performAction(...); } else if (shouldShowRequestPermissionRationale(...)) { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected. In this UI, // include a "cancel" or "no thanks" button that allows the user to // continue using your app without granting the permission. showInContextUI(...); } else { // You can directly ask for the permission. // The registered ActivityResultCallback gets the result of this request. requestPermissionLauncher.launch( Manifest.permission.REQUESTED_PERMISSION); }

Tự quản lý mã yêu cầu cấp quyền

Thay vì cho phép hệ thống quản lý mã yêu cầu cấp quyền, bạn có thể tự quản lý mã yêu cầu cấp quyền này. Để thực hiện việc này, đưa mã yêu cầu vào lệnh gọi requestPermissions().

Lưu ý: Ứng dụng của bạn không thể tuỳ chỉnh hộp thoại được xuất hiện khi bạn gọi requestPermissions(). Văn bản trong hộp thoại cấp quyền của hệ thống tham chiếu đến một nhóm quyền nhưng nhóm quyền này được thiết kế để giúp bạn dễ sử dụng hệ thống. Ứng dụng của bạn không nên dựa vào các quyền nằm trong hoặc ngoài một nhóm quyền cụ thể.

Đoạn mã sau đây minh hoạ cách yêu cầu cấp quyền bằng mã yêu cầu:

when { ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION ) == PackageManager.PERMISSION_GRANTED -> { // You can use the API that requires the permission. performAction(...) } shouldShowRequestPermissionRationale(...) -> { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected. In this UI, // include a "cancel" or "no thanks" button that allows the user to // continue using your app without granting the permission. showInContextUI(...) } else -> { // You can directly ask for the permission. requestPermissions(CONTEXT, arrayOf(Manifest.permission.REQUESTED_PERMISSION), REQUEST_CODE) } }
if (ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION) == PackageManager.PERMISSION_GRANTED) { // You can use the API that requires the permission. performAction(...); } else if (shouldShowRequestPermissionRationale(...)) { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected. In this UI, // include a "cancel" or "no thanks" button that allows the user to // continue using your app without granting the permission. showInContextUI(...); } else { // You can directly ask for the permission. requestPermissions(CONTEXT, new String[] { Manifest.permission.REQUESTED_PERMISSION }, REQUEST_CODE); }

Sau khi người dùng phản hồi với hộp thoại cấp quyền hệ thống, thì hệ thống sẽ gọi chế độ triển khai onRequestPermissionsResult() của ứng dụng. Hệ thống sẽ chuyển phản hồi người dùng tới hộp thoại cấp quyền, cũng như mã yêu cầu mà bạn đã xác định, như được cho thấy trong đoạn mã sau:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { when (requestCode) { PERMISSION_REQUEST_CODE -> { // If request is cancelled, the result arrays are empty. if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { // Permission is granted. Continue the action or workflow // in your app. } else { // Explain to the user that the feature is unavailable because // the features requires a permission that the user has denied. // At the same time, respect the user's decision. Don't link to // system settings in an effort to convince the user to change // their decision. } return } // Add other 'when' lines to check for other // permissions this app might request. else -> { // Ignore all other requests. } } }
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_CODE: // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission is granted. Continue the action or workflow // in your app. } else { // Explain to the user that the feature is unavailable because // the features requires a permission that the user has denied. // At the same time, respect the user's decision. Don't link to // system settings in an effort to convince the user to change // their decision. } return; } // Other 'case' lines to check for other // permissions this app might request. } }

Yêu cầu cấp nhiều quyền

Khi bạn yêu cầu cấp quyền về vị trí, làm theo các phương pháp hay nhất cũng như đối với mọi quyền bắt đầu khi chạy khác. Một khác biệt quan trọng khi nói đến cấp quyền về vị trí là hệ thống bao gồm nhiều quyền liên quan đến vị trí. Quyền bạn yêu cầu và cách bạn yêu cầu quyền đó tuỳ thuộc vào các yêu cầu về vị trí đối với trường hợp sử dụng của ứng dụng.

Vị trí nền trước

Nếu ứng dụng của bạn chứa một tính năng chỉ chia sẻ hoặc nhận thông tin vị trí một lần hoặc trong một khoảng thời gian xác định, thì tính năng đó sẽ yêu cầu quyền truy cập thông tin vị trí ở chế độ nền trước. Sau đây là một số ví dụ:

  • Trong ứng dụng tìm đường, một tính năng cho phép người dùng xem đường đi từng chặng.
  • Trong ứng dụng nhắn tin, một tính năng cho phép người dùng chia sẻ vị trí hiện tại của mình với người dùng khác.

Hệ thống sẽ coi ứng dụng của bạn đang sử dụng thông tin vị trí ở chế độ nền trước nếu một tính năng của ứng dụng truy cập vào vị trí hiện tại của thiết bị ở một trong các tình huống sau:

  • Một hoạt động thuộc ứng dụng của bạn đang hiển thị.
  • Ứng dụng của bạn đang chạy một dịch vụ trên nền trước. Khi một dịch vụ trên nền trước đang chạy, hệ thống sẽ báo cho người dùng biết bằng cách hiển thị một thông báo liên tục. Ứng dụng của bạn vẫn giữ quyền truy cập khi được đặt vào chế độ nền, chẳng hạn như khi người dùng nhấn nút Home (Màn hình chính) trên thiết bị hoặc tắt màn hình thiết bị.

    Ngoài ra, bạn nên khai báo loại dịch vụ trên nền trước là location, như được minh hoạ trong đoạn mã sau. Trên Android 10 (API cấp 29) trở lên, bạn phải khai báo loại dịch vụ trên nền trước này.

    <!-- Recommended for Android 9 (API level 28) and lower. --> <!-- Required for Android 10 (API level 29) and higher. --> <service android:name="MyNavigationService" android:foregroundServiceType="location" ... > <!-- Any inner elements would go here. --> </service>

Bạn khai báo nhu cầu về thông tin vị trí ở chế độ nền trước khi ứng dụng yêu cầu cấp quyền ACCESS_COARSE_LOCATION hoặc quyền ACCESS_FINE_LOCATION, như được hiển thị trong đoạn mã sau:

<manifest ... > <!-- Always include this permission --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Include only if your app benefits from precise location access. --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> </manifest>

Quyền truy cập thông tin vị trí ở chế độ nền

Ứng dụng sẽ yêu cầu quyền truy cập thông tin vị trí ở chế độ nền nếu một tính năng trong ứng dụng đó liên tục chia sẻ vị trí với người dùng khác hoặc sử dụng API Khoanh vùng địa lý. Sau đây là một số ví dụ:

  • Trong ứng dụng chia sẻ vị trí của nhóm gia đình, một tính năng cho phép người dùng liên tục chia sẻ vị trí với thành viên gia đình.
  • Trong ứng dụng IoT, một tính năng cho phép người dùng định cấu hình các thiết bị trong nhà để tắt thiết bị khi người dùng rời khỏi nhà và bật lại khi người dùng trở về nhà.

Hệ thống sẽ coi ứng dụng của bạn đang sử dụng thông tin vị trí ở chế độ nền nếu ứng dụng truy cập vào thông tin vị trí hiện tại của thiết bị trong bất kỳ tình huống nào trừ những tình huống được mô tả trong phần thông tin vị trí ở chế độ nền trước. Độ chính xác của vị trí ở chế độ nền giống như độ chính xác của vị trí ở chế độ nền trước, tuỳ thuộc vào quyền truy cập thông tin vị trí mà ứng dụng của bạn khai báo.

Trên Android 10 (API cấp 29) trở lên, bạn phải khai báo ACCESS_BACKGROUND_LOCATIONquyền trong tệp kê khai của ứng dụng để yêu cầu quyền truy cập thông tin vị trí ở chế độ nền trong thời gian chạy. Trên các phiên bản Android cũ, khi ứng dụng nhận được quyền truy cập thông tin vị trí ở chế độ nền trước, ứng dụng đó cũng tự động nhận được quyền truy cập thông tin vị trí ở chế độ nền.

<manifest ... > <!-- Required only when requesting background location access on Android 10 (API level 29) and higher. --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> </manifest> Lưu ý: Cửa hàng Google Play có chính sách về vị trí liên quan đến vị trí của thiết bị, chỉ cấp quyền truy cập thông tin vị trí ở chế độ nền cho các ứng dụng cần quyền này để thực hiện chức năng cốt lõi và đáp ứng các yêu cầu liên quan của chính sách.

Xử lý việc từ chối cấp quyền

Nếu người dùng từ chối yêu cầu cấp quyền, ứng dụng của bạn sẽ giúp người dùng hiểu hệ quả của việc từ chối cấp quyền. Cụ thể, ứng dụng của bạn phải thông báo cho người dùng về những tính năng sẽ không hoạt động do không có quyền. Khi bạn làm như vậy, lưu ý các phương pháp hay nhất sau:

  • Thu hút sự chú ý của người dùng. Làm nổi bật một phần cụ thể trên giao diện người dùng của ứng dụng trên đó có chức năng bị hạn chế do ứng dụng không có được quyền truy cập cần thiết. Dưới đây là một số ví dụ về những việc bạn có thể làm:

    • Hiển thị thông báo trong đó kết quả hoặc dữ liệu của tính năng có thể xuất hiện.
    • Hiển thị một nút khác chứa biểu tượng lỗi và màu sắc.
  • Nên cụ thể. Không hiển thị thông báo chung chung; thay vào đó, đề cập đến các tính năng không thể hoạt động vì ứng dụng của bạn không có được quyền cần thiết.

  • Không chặn giao diện người dùng. Nói cách khác, không nên hiển thị thông báo cảnh báo toàn màn hình không cho người dùng tiếp tục dùng ứng dụng của bạn.

Mẹo: Ứng dụng của bạn phải khuyến khích trải nghiệm tốt nhất có thể với người dùng, ngay cả sau khi bị từ chối cấp quyền. Chẳng hạn như nếu quyền truy cập vào micrô bị từ chối, bạn vẫn nên quảng bá đầy đủ chức năng của văn bản.

Đồng thời, ứng dụng của bạn nên tôn trọng quyết định từ chối cấp quyền của người dùng. Kể từ Android 11 (API cấp 30), nếu người dùng nhiều lần nhấn vào Từ chối với một quyền cụ thể trong suốt thời gian ứng dụng của bạn được cài đặt trên thiết bị, thì người dùng sẽ không xem hộp thoại cấp quyền của hệ thống nếu ứng dụng của bạn yêu cầu cấp lại quyền đó. Hành động của người dùng ngụ ý "không hỏi lại". Trên các phiên bản trước, người dùng sẽ thấy hộp thoại cấp quyền của hệ thống mỗi khi ứng dụng của bạn yêu cầu cấp quyền, trừ khi trước đó người dùng đã chọn hộp đánh dấu hoặc tuỳ chọn "không hỏi lại".

Nếu người dùng từ chối yêu cầu cấp quyền nhiều lần, thì hành động này được coi là từ chối vĩnh viễn. Đặc biệt quan trọng là chỉ nên nhắc người dùng cấp quyền khi họ cần truy cập vào một tính năng cụ thể, nếu không, bạn có thể vô tình mất khả năng yêu cầu cấp quyền lần nữa.

Trong một số trường hợp nhất định, quyền có thể tự động bị từ chối mà không cần người dùng thực hiện bất kỳ hành động nào. (Tương tự, một quyền cũng có thể được cấp tự động.) Bạn không nên giả định bất kỳ điều gì về hành vi tự động. Mỗi khi ứng dụng cần truy cập chức năng yêu cầu cấp quyền, bạn nên kiểm tra để biết ứng dụng vẫn được cấp quyền đó.

Để cung cấp trải nghiệm người dùng tốt nhất khi yêu cầu cấp quyền cho ứng dụng, bạn cũng nên xem Các phương pháp hay nhất về cấp quyền cho ứng dụng.

Cấp quyền một lần

Figure 2. Hộp thoại hệ thống xuất hiện khi ứng dụng yêu cầu cấp quyền một lần.

Kể từ Android 11 (API cấp 30), bất cứ khi nào ứng dụng yêu cầu cấp quyền liên quan đến vị trí, micrô hoặc máy ảnh, hộp thoại cấp quyền, mà người dùng nhìn thấy, chứa tuỳ chọn có tên là Chỉ lần này, như được minh hoạ trong Hình 2. Nếu người dùng chọn tuỳ chọn này trong hộp thoại, thì ứng dụng của bạn sẽ tạm thời được cấp quyền một lần.

Sau đó, ứng dụng có thể truy cập vào dữ liệu liên quan trong một khoảng thời gian nhất định, tuỳ thuộc vào hành vi của ứng dụng và hành động của người dùng:

  • Trong khi hoạt động của ứng dụng được hiển thị, thì ứng dụng có thể truy cập dữ liệu.
  • Nếu người dùng chuyển ứng dụng của bạn vào nền, ứng dụng vẫn có thể tiếp tục truy cập dữ liệu trong một khoảng thời gian ngắn.
  • Nếu bạn khởi chạy một dịch vụ trên nền trước trong khi hoạt động được hiển thị, sau đó người dùng chuyển ứng dụng sang chế độ nền, thì ứng dụng của bạn có thể tiếp tục truy cập vào dữ liệu cho đến khi dịch vụ trên nền trước này ngừng hoạt động.

Quá trình xử lý của ứng dụng chấm dứt khi quyền bị thu hồi

Nếu người dùng thu hồi quyền một lần, chẳng hạn như trong phần cài đặt hệ thống, thì ứng dụng của bạn không thể truy cập vào dữ liệu, bất kể bạn đã khởi chạy dịch vụ trên nền trước hay chưa. Cũng như đối với bất kỳ quyền nào, nếu người dùng thu hồi quyền một lần của ứng dụng, thì quy trình của ứng dụng sẽ chấm dứt.

Lần tiếp theo khi người dùng mở ứng dụng của bạn và một tính năng trong ứng dụng yêu cầu quyền truy cập vào thông tin vị trí, micrô hoặc máy ảnh, thì người dùng sẽ nhận được lời nhắc cấp quyền một lần nữa.

Lưu ý: Nếu ứng dụng đã làm theo các phương pháp hay nhất khi yêu cầu cấp quyền khi bắt đầu chạy, thì bạn không cần thêm hay thay đổi bất kỳ logic nào trong ứng dụng để hỗ trợ quyền một lần.

Đặt lại quyền không dùng đến

Android cung cấp một số cách để đặt lại quyền không dùng đến khi bắt đầu chạy về trạng thái mặc định, bị từ chối:

Trên Android 13 (API cấp 33) trở lên, bạn có thể xoá quyền truy cập của ứng dụng vào các quyền khi bắt đầu chạy mà ứng dụng không còn yêu cầu. Khi bạn cập nhật ứng dụng, hãy thực hiện bước này để người dùng có thể dễ hiểu lý do ứng dụng tiếp tục yêu cầu các quyền cụ thể. Kiến thức này giúp người dùng tin tưởng ứng dụng của bạn.

Để xoá quyền truy cập vào một quyền khi bắt đầu chạy, hãy chuyển tên của quyền đó vào revokeSelfPermissionOnKill(). Để xoá quyền truy cập vào một nhóm các quyền khi bắt đầu chạy, hãy chuyển một tập hợp tên quyền vào revokeSelfPermissionsOnKill(). Quy trình xoá quyền diễn ra không đồng bộ và loại bỏ tất cả các quy trình liên kết với UID của ứng dụng.

Lưu ý: Để các chế độ cài đặt hệ thống cho thấy rằng ứng dụng của bạn không truy cập vào dữ liệu trong một nhóm quyền cụ thể, bạn phải xoá quyền truy cập vào tất cả các quyền trong nhóm quyền đó. Trong trường hợp này, bạn nên gọi revokeSelfPermissionsOnKill() và chuyển vào nhiều quyền trong nhóm quyền này.

Để hệ thống xoá quyền truy cập của ứng dụng vào các quyền, mọi quy trình liên kết với ứng dụng đều phải bị loại bỏ. Khi bạn gọi API, hệ thống sẽ xác định thời điểm an toàn để loại bỏ các quy trình này. Thông thường, hệ thống sẽ chờ cho đến khi ứng dụng dành một khoảng thời gian dài để chạy trong nền thay vì trong nền trước.

Để thông báo cho người dùng rằng ứng dụng của bạn không còn yêu cầu truy cập vào các quyền cụ thể khi bắt đầu chạy, hãy hiển thị một hộp thoại vào lần tới người dùng chạy ứng dụng. Hộp thoại này có thể bao gồm danh sách các quyền.

Tự động đặt lại quyền cho các ứng dụng không dùng đến

Nếu ứng dụng của bạn nhắm mục tiêu vào Android 11 (API cấp 30) trở lên và không được dùng trong vài tháng, thì hệ thống sẽ bảo vệ dữ liệu người dùng bằng cách tự động đặt lại các quyền nhạy cảm khi bắt đầu chạy mà người dùng đã cấp cho ứng dụng. Hãy tìm hiểu thêm trong hướng dẫn về trạng thái ngủ đông của ứng dụng.

Yêu cầu để trở thành trình xử lý mặc định nếu cần

Một số ứng dụng phụ thuộc vào quyền truy cập đến thông tin người dùng nhạy cảm liên quan đến nhật ký cuộc gọi và tin nhắn SMS. Nếu muốn yêu cầu cấp quyền cụ thể với nhật ký cuộc gọi và tin nhắn SMS cũng như xuất bản ứng dụng lên Cửa hàng Play, thì bạn phải nhắc người dùng đặt ứng dụng làm trình xử lý mặc định cho một hàm hệ thống cốt lõi trước khi yêu cầu quyền khi bắt đầu chạy này.

Để biết thêm thông tin về trình xử lý mặc định, bao gồm cả hướng dẫn về hiển thị lời nhắc trình xử lý mặc định cho người dùng, xem hướng dẫn về các quyền chỉ được sử dụng trong trình xử lý mặc định.

Cấp tất cả quyền khi bắt đầu chạy cho mục đích kiểm thử

Để tự động cấp tất cả các quyền khi bắt đầu chạy khi bạn cài đặt một ứng dụng trên trình mô phỏng hoặc thiết bị kiểm thử, sử dụng tuỳ chọn -g cho lệnh adb shell install như minh hoạ trong đoạn mã sau đây:

adb shell install -g PATH_TO_APK_FILE

Tài nguyên khác

Để biết thêm thông tin về cấp quyền, đọc những bài viết sau:

  • Tổng quan về quyền
  • Các phương pháp hay nhất về quyền cho ứng dụng

Để tìm hiểu thêm về yêu cầu cấp quyền, hãy tải các ứng dụng mẫu sau xuống:

  • Mẫu RuntimePermissionsBasic của Android Java | Kotlin