Thêm quyền khi bắt đầu chạy vào ứng dụng trong Kotlin

1. Chào mừng

Giới thiệu

Quyền cho ứng dụng được dùng để cấp quyền truy cập vào dữ liệu và chức năng ngoài phạm vi môi trường hộp cát của ứng dụng. Các quyền này có thể cải thiện chức năng của ứng dụng bằng cách cho phép ứng dụng truy cập vào Internet, thông tin vị trí thiết bị, máy ảnh, v.v.

Để ứng dụng có được những khả năng này, bạn cần phải yêu cầu người dùng cấp quyền. Lớp học lập trình này sẽ hướng dẫn bạn các bước cần thiết để thêm quyền khi bắt đầu chạy và kiểm tra xem những quyền này đã được cấp hay chưa.

Bạn cần có

Kiến thức bạn cần có

Kiến thức bạn sẽ học được

  • Cách thêm quyền vào tệp kê khai Android.
  • Cách yêu cầu cấp quyền.
  • Cách xử lý khi quyền được chấp nhận và bị từ chối.
  • Cách kiểm tra xem một quyền nào đó đã được cấp hay chưa.

Sản phẩm bạn sẽ tạo ra

Bạn sẽ tạo một ứng dụng yêu cầu quyền sử dụng máy ảnh. Bạn sẽ triển khai phần cấp quyền cho ứng dụng, nhưng không triển khai phần máy ảnh.

2. Tạo một dự án Android Studio

  1. Bắt đầu một dự án Android Studio mới.
  2. Chọn Empty Activity (Hoạt động trống).

70e5de28256e3dcb.png

  1. Đặt tên cho dự án là Permissions Codelab và dùng ngôn ngữ Kotlin.

f2948b584ca99c47.png

3. Thiết lập đoạn mã

  1. Thêm phiên bản mới nhất của các phần phụ thuộc sau đây vào tệp build.gradle ở cấp ứng dụng. Những phần phụ thuộc này cho phép bạn sử dụng thư viện Activity. Chúng ta sẽ đề cập đến thư viện này ở các phần sau trong lớp học lập trình này.
implementation "androidx.activity:activity-ktx:1.2.2"
implementation "androidx.fragment:fragment-ktx:1.3.2"
  1. Đặt tuỳ chọn bản dựng viewBinding thành true trong khối lệnh android để bật tính năng ViewBinding.
android {
   ...
   buildFeatures {
       viewBinding true
   }
}
  1. Sau đó, nhấn nút lệnh hình cái búa màu xanh lục để tạo ứng dụng. Thao tác này sẽ tạo một lớp liên kết có tên ActivityMainBinding mà sau này bạn sẽ sử dụng cho ViewBinding.

d4064454e5c50111.png

  1. Chuyển đến tệp activity_main.xml rồi thay mã bằng đoạn mã sau.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/main_layout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <Button
       android:id="@+id/button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Request Permissions"
       android:onClick="onClickRequestPermission"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  1. Thêm các chuỗi này vào tệp strings.xml.
<string name="app_name">Permissions Codelab</string>
<string name="permission_required">Camera access is required to display the camera preview.</string>
<string name="ok">OK</string>
<string name="permission_granted">Permission is granted. You can use the camera now.</string>
  1. Trong MainActivity.kt, phía trên phương thức onCreate(), hãy định nghĩa các biến cho bố cục và ViewBinding.
private lateinit var layout: View
private lateinit var binding: ActivityMainBinding
  1. Thay thế mã trong phương thức onCreate() bằng đoạn mã dưới đây. Mã này sẽ khởi tạo mối liên kết, tạo một val thể hiện khung nhìn này và thiết lập khung nhìn này thành gốc liên kết, đồng thời đặt bố cục thành mainLayout của mối liên kết.
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   binding = ActivityMainBinding.inflate(layoutInflater)
   val view = binding.root
   layout = binding.mainLayout
   setContentView(view)
}
  1. Ở cuối tệp, trong lớp MainActivity, hãy thêm một hàm mở rộng để hiển thị thanh thông báo nhanh xuyên suốt lớp học lập trình này.
fun View.showSnackbar(
   view: View,
   msg: String,
   length: Int,
   actionMessage: CharSequence?,
   action: (View) -> Unit
) {
   val snackbar = Snackbar.make(view, msg, length)
   if (actionMessage != null) {
       snackbar.setAction(actionMessage) {
           action(this)
       }.show()
   } else {
       snackbar.show()
   }
}

4. Thêm quyền vào tệp kê khai

Việc cần làm đầu tiên là khai báo rằng bạn sẽ dùng quyền trong Android manifest bằng cách sử dụng thẻ <uses-permission>.

Đôi khi quyền mà bạn đang đề nghị cấp cũng sẽ có các yêu cầu khác. Trong trường hợp này, bạn không thể dùng ứng dụng máy ảnh trừ phi thiết bị có máy ảnh. Do đó, bạn cần thêm thẻ <uses-feature> vào tệp kê khai.

  1. Trong tệp AndroidManifest.xml, hãy thêm quyền cho máy ảnh ở phía trên thẻ <application>.
<uses-permission android:name="android.permission.CAMERA" />

5. Tạo trình chạy quyền

Trong tệp MainActivity.kt, hãy tạo một val có tên là requestPermissionLauncher rồi sao chép đoạn mã này vào đó. Chúng ta sẽ phân tích chi tiết về đoạn mã này ở những dòng bên dưới.

private val requestPermissionLauncher =
   registerForActivityResult(
       ActivityResultContracts.RequestPermission()
   ) { isGranted: Boolean ->
       if (isGranted) {
           Log.i("Permission: ", "Granted")
       } else {
           Log.i("Permission: ", "Denied")
       }
   }
private val requestPermissionLauncher =
   registerForActivityResult(
       ActivityResultContracts.RequestPermission())
  • Thêm lệnh gọi lại (callback) để kiểm tra xem một quyền đã được cấp phép hay chưa. Trong trường hợp này, chúng ta sẽ ghi kết quả vào nhật ký.
{ isGranted: Boolean ->
       if (isGranted) {
           Log.i("Permission: ", "Granted")
       } else {
           Log.i("Permission: ", "Denied")
       }
}

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

  1. Tạo một hàm có tên là onClickRequestPermission(view: View) rồi sao chép đoạn mã này vào hàm đó. Chúng ta sẽ phân tích những gì đang xảy ra bên trong đoạn mã này ở những dòng tiếp theo.
fun onClickRequestPermission(view: View) {
   when {
       ContextCompat.checkSelfPermission(
           this,
           Manifest.permission.CAMERA
       ) == PackageManager.PERMISSION_GRANTED -> {
           layout.showSnackbar(
               view,
               getString(R.string.permission_granted),
               Snackbar.LENGTH_INDEFINITE,
               null
           ) {}
       }

       ActivityCompat.shouldShowRequestPermissionRationale(
           this,
           Manifest.permission.CAMERA
       ) -> {
           layout.showSnackbar(
               view,
               getString(R.string.permission_required),
               Snackbar.LENGTH_INDEFINITE,
               getString(R.string.ok)
           ) {
               requestPermissionLauncher.launch(
                   Manifest.permission.CAMERA
               )
           }
       }

       else -> {
           requestPermissionLauncher.launch(
               Manifest.permission.CAMERA
           )
       }
   }
}
  • Tạo câu lệnh when để xử lý ba trường hợp: quyền đã được cấp, ứng dụng thấy cần hiển thị lý do yêu cầu cấp quyền và chưa yêu cầu cấp quyền.
when {
   ContextCompat.checkSelfPermission(
       this,
       Manifest.permission.CAMERA
   ) == PackageManager.PERMISSION_GRANTED -> {

   }

   ActivityCompat.shouldShowRequestPermissionRationale(
       this,
       Manifest.permission.CAMERA
   ) -> {

   }

   else -> {

   }
}
  • Trong trường hợp quyền đã được cấp, đoạn mã sẽ hiện một thông báo trên thanh thông báo nhanh.
ContextCompat.checkSelfPermission(
   this,
   Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
   layout.showSnackbar(
       view,
       getString(R.string.permission_granted),
       Snackbar.LENGTH_INDEFINITE,
       null
   ) {}
}
  • Nếu shouldShowRequestPermissionRationale() trả về giá trị true, đoạn mã sẽ hiện một giao diện người dùng mô tả chi tiết hơn về lý do cần cấp quyền cho tính năng đó, đồng thời hướng dẫn người dùng chấp nhận/từ chối cấp quyền trên giao diện người dùng.

a25d8c6c1d5051d.png

ActivityCompat.shouldShowRequestPermissionRationale(
   this,
   Manifest.permission.CAMERA
) -> {
   layout.showSnackbar(
       view,
       getString(R.string.permission_required),
       Snackbar.LENGTH_INDEFINITE,
       getString(R.string.ok)
   ) {
       requestPermissionLauncher.launch(
           Manifest.permission.CAMERA
       )
   }
}
  • Trường hợp còn lại, đoạn mã sẽ yêu cầu cấp quyền đó.
else -> {
   requestPermissionLauncher.launch(
       Manifest.permission.CAMERA
   )
}

7. Tóm tắt

Vậy là xong! Lớp học lập trình này cho bạn biết cách thêm quyền khi bắt đầu chạy và có thể dùng cho các quyền liên quan đến vị trí, mạng, nội dung đa phương tiện và nhiều quyền khác!

Bạn có thể xem đoạn mã hoàn chỉnh và đọc thêm trong tài liệu này.