Hạn chế tương tác với ứng dụng khác

Quyền không chỉ có tác dụng yêu cầu chức năng của hệ thống. Bạn cũng có thể hạn chế cách ứng dụng khác có thể tương tác với các thành phần trong ứng dụng của bạn.

Hướng dẫn này giải thích cách xem tập hợp các quyền mà một ứng dụng khác đã khai báo. Hướng dẫn này cũng giải thích cách bạn có thể định cấu hình các hoạt động, dịch vụ, nhà cung cấp nội dung và broadcast receiver để hạn chế cách các ứng dụng khác có thể tương tác với ứng dụng của bạn. Cuối cùng, trang này hướng dẫn một số cách khác để thực thi các mẫu tương tác giữa các ứng dụng.

Xem các quyền của ứng dụng khác

Để xem tập hợp các quyền mà một ứng dụng khác khai báo, hãy sử dụng một thiết bị hoặc trình mô phỏng để hoàn thành các bước sau:

  1. Mở màn hình App info (Thông tin ứng dụng) của một ứng dụng.
  2. Chọn Permissions (Quyền). Màn hình App permissions (Quyền cho ứng dụng) sẽ tải.

    Màn hình này hiển thị một tập hợp các nhóm quyền. Hệ thống sắp xếp tập hợp các quyền mà một ứng dụng đã khai báo vào các nhóm này.

Hạn chế tương tác với các hoạt động trong ứng dụng của bạn

Các quyền áp dụng sử dụng thuộc tính android:permission cho thẻ <activity> trong tệp kê khai sẽ hạn chế những đối tượng có thể bắt đầu Activity đó. Quyền được kiểm tra trong Context.startActivity()Activity.startActivityForResult(). Nếu phương thức gọi không có quyền cần thiết, thì SecurityException sẽ xuất hiện.

Hạn chế tương tác với các dịch vụ trong ứng dụng của bạn

Các quyền áp dụng sử dụng thuộc tính android:permission cho thẻ <service> trong tệp kê khai hạn chế những đối tượng có thể bắt đầu hoặc liên kết với Service được liên kết. Quyền sẽ được kiểm tra trong Context.startService(), Context.stopService()Context.bindService(). Nếu phương thức gọi không có quyền cần thiết, thì SecurityException sẽ xuất hiện.

Hạn chế tương tác với nhà cung cấp nội dung trong ứng dụng của bạn

Các quyền áp dụng sử dụng thuộc tính android:permission cho thẻ <provider> sẽ hạn chế những đối tượng có thể truy cập vào dữ liệu trong ContentProvider. (Các nhà cung cấp nội dung có một cơ sở bảo mật quan trọng khác mà họ có thể sử dụng, gọi là quyền URI được mô tả trong phần tiếp theo). Không giống như các thành phần khác, bạn có thể đặt hai thuộc tính quyền riêng biệt: android:readPermission hạn chế đối tượng có thể đọc từ nhà cung cấp và android:writePermission hạn chế đối tượng có thể ghi. Xin lưu ý rằng nếu một nhà cung cấp được bảo vệ bằng cả quyền đọc và ghi, thì việc chỉ giữ quyền ghi không có nghĩa là bạn có thể đọc từ nhà cung cấp.

Các quyền này sẽ được kiểm tra trong lần đầu tiên bạn truy xuất nhà cung cấp (nếu bạn không có quyền nào cả, SecurityExceptionsẽ diễn ra) và khi bạn thực hiện các hoạt động trên nhà cung cấp đó. Để sử dụng ContentResolver.query(), bạn phải có quyền đọc; việc sử dụng ContentResolver.insert(), ContentResolver.update() hoặc ContentResolver.delete() cần có quyền ghi. Trong tất cả những trường hợp này, việc không có quyền cần thiết sẽ dẫn đến SecurityException.

Cho phép truy cập theo từng URI

Hệ thống này cung cấp cho bạn thêm quyền kiểm soát chi tiết về cách các ứng dụng khác có thể truy cập vào nhà cung cấp nội dung trong ứng dụng của bạn. Đặc biệt, nhà cung cấp nội dung của bạn có thể tự bảo vệ bằng quyền đọc và ghi, trong khi vẫn cho phép ứng dụng khách trực tiếp của nhà cung cấp chia sẻ URI cụ thể với các ứng dụng khác. Để khai báo khả năng hỗ trợ của ứng dụng cho mô hình này, hãy sử dụng thuộc tính android:grantUriPermissions hoặc phần tử <grant-uri-permission.

Bạn cũng có thể cấp quyền theo mỗi URI. Khi bắt đầu hoạt động hoặc trả về kết quả cho một hoạt động, hãy đặt cờ ý định Intent.FLAG_GRANT_READ_URI_PERMISSION, cờ ý định Intent.FLAG_GRANT_WRITE_URI_PERMISSION hoặc cả hai cờ. Thao tác này sẽ lần lượt cấp cho ứng dụng khác quyền đọc, ghi và đọc/ghi đối với URI dữ liệu có trong ý định. Ứng dụng kia nhận được các quyền này cho URI cụ thể, bất kể có quyền truy cập vào dữ liệu trong nhà cung cấp nội dung nói chung hay không.

Ví dụ: Giả sử người dùng đang xem email trong ứng dụng của bạn và email này bao gồm một hình ảnh dưới dạng tệp đính kèm. Các ứng dụng khác không thể truy cập vào nội dung email nói chung, nhưng họ có thể muốn xem hình ảnh. Ứng dụng của bạn có thể sử dụng ý định và cờ ý định Intent.FLAG_GRANT_READ_URI_PERMISSION để một ứng dụng xem hình ảnh xem được hình ảnh.

Một yếu tố khác cần cân nhắc là khả năng hiển thị của ứng dụng. Nếu ứng dụng của bạn nhắm mục tiêu đến Android 11 (API cấp 30) trở lên, thì hệ thống sẽ tự động hiển thị một số ứng dụng để ứng dụng của bạn nhìn thấy nhưng sẽ ẩn các ứng dụng khác theo mặc định. Nếu có nhà cung cấp nội dung và đã cấp quyền URI cho một ứng dụng khác, thì ứng dụng của bạn sẽ tự động hiển thị cho ứng dụng khác.

Để biết thêm thông tin, hãy xem tài liệu tham khảo cho phương thức grantUriPermission(), revokeUriPermission(), và checkUriPermission().

Hạn chế tương tác với broadcast receiver trong ứng dụng của bạn

Các quyền áp dụng sử dụng thuộc tính android:permission cho thẻ <receiver> sẽ hạn chế những đối tượng có thể truyền tin đến BroadcastReceiver được liên kết. Quyền này được kiểm tra sau khi Context.sendBroadcast() trả về vì hệ thống cố gắng phân phối tin đã truyền đến đối tượng nhận cụ thể. Do đó, lỗi về quyền sẽ không dẫn đến việc ngoại lệ được trả về cho phương thức gọi; lỗi chỉ không cung cấp Intent.

Tương tự, bạn có thể cấp quyền cho Context.registerReceiver() để kiểm soát đối tượng có thể truyền tin cho đối tượng nhận đã đăng ký theo phương thức lập trình. Trái lại, bạn có thể cung cấp quyền khi gọi Context.sendBroadcast() để hạn chế các broadcast receiver được phép nhận tin truyền.

Lưu ý: Cả đối tượng nhận và truyền tin đều có thể yêu cầu quyền. Khi điều này xảy ra, cả hai bước kiểm tra quyền đều phải đạt thì ý định mới được gửi đến mục tiêu liên quan. Để biết thêm thông tin, xem Hạn chế truyền tin bằng các quyền.

Các bước kiểm tra quyền khác

Có một số cách hữu ích khác giúp bạn kiểm tra quyền:

  • Trong lệnh gọi đến dịch vụ, truyền chuỗi quyền vào Context.checkCallingPermission(). Phương thức này trả về một số nguyên cho biết liệu quyền đó đã được cấp cho quá trình gọi hiện tại hay chưa. Xin lưu ý rằng bạn chỉ có thể sử dụng phương thức này khi thực thi một lệnh gọi đến từ một quy trình khác, thường là thông qua giao diện IDL được phát hành từ một dịch vụ hoặc theo một cách nào đó đối với một quy trình khác.
  • Để kiểm tra xem một quy trình khác đã được cấp quyền cụ thể hay chưa, hãy truyền quy trình đó (PID) vào Context.checkPermission().
  • Để kiểm tra xem một gói khác đã được cấp quyền cụ thể hay chưa, hãy truyền tên gói đó vào PackageManager.checkPermission().