Hồ sơ công việc

Nền tảng Android cho phép các thiết bị có hồ sơ công việc (đôi khi còn gọi là hồ sơ được quản lý). Hồ sơ công việc do một quản trị viên CNTT kiểm soát và chức năng có sẵn trong hồ sơ này được thiết lập riêng biệt với chức năng trong hồ sơ chính của người dùng. Phương pháp này cho phép các tổ chức kiểm soát môi trường nơi các ứng dụng và dữ liệu của công ty đang chạy trên thiết bị của người dùng, trong khi vẫn cho phép người dùng sử dụng các ứng dụng và hồ sơ cá nhân của họ.

Bài học này sẽ hướng dẫn bạn cách sửa đổi ứng dụng để ứng dụng hoạt động đáng tin cậy trên thiết bị có hồ sơ công việc. Bạn không cần làm gì ngoài các phương pháp hay nhất thông thường để phát triển ứng dụng. Tuy nhiên, một số phương pháp hay nhất trong số này trở nên đặc biệt quan trọng trên các thiết bị có hồ sơ công việc. Tài liệu này nêu bật những vấn đề mà bạn cần lưu ý.

Tổng quan

Người dùng thường muốn sử dụng thiết bị cá nhân trong môi trường doanh nghiệp. Tình huống này có thể khiến các tổ chức rơi vào thế tiến thoái lưỡng nan. Nếu người dùng có thể sử dụng thiết bị của riêng mình, tổ chức phải lo lắng rằng thông tin bảo mật (như email và danh bạ của nhân viên) có trên thiết bị mà tổ chức không kiểm soát.

Để giải quyết trường hợp này, Android 5.0 (API cấp 21) cho phép các tổ chức thiết lập hồ sơ công việc. Nếu thiết bị có hồ sơ công việc, thì chế độ cài đặt của hồ sơ sẽ thuộc sự kiểm soát của quản trị viên CNTT. Quản trị viên CNTT có thể chọn những ứng dụng được phép sử dụng cho hồ sơ đó và có thể kiểm soát chỉ những tính năng nào của thiết bị được cung cấp cho hồ sơ.

Nếu một thiết bị có hồ sơ công việc, thì các ứng dụng chạy trên thiết bị sẽ có ảnh hưởng nhất định, bất kể ứng dụng đó đang chạy trong hồ sơ nào:

  • Theo mặc định, hầu hết các ý định không chuyển từ hồ sơ này sang hồ sơ khác. Nếu một ứng dụng chạy trên hồ sơ kích hoạt một ý định, thì ý định trên hồ sơ đó sẽ không có trình xử lý, đồng thời ý định đó không được phép chuyển sang hồ sơ khác do các hạn chế về hồ sơ, thì yêu cầu sẽ không thành công và ứng dụng có thể bị tắt ngoài ý muốn.
  • Quản trị viên CNTT của hồ sơ có thể giới hạn những ứng dụng hệ thống nào có trên hồ sơ công việc. Hạn chế này cũng có thể dẫn đến việc không có trình xử lý cho một số ý định phổ biến trên hồ sơ công việc.
  • Vì hồ sơ cá nhân và hồ sơ công việc có khu vực lưu trữ riêng biệt, nên một URI tệp hợp lệ trên một hồ sơ thì không hợp lệ trên hồ sơ còn lại. Mọi ý định được kích hoạt trên một hồ sơ có thể được xử lý trên hồ sơ khác (tuỳ thuộc vào chế độ cài đặt hồ sơ). Vì vậy, việc đính kèm URI tệp vào ý định sẽ không an toàn.

Ngăn ý định không thực hiện được

Trên một thiết bị có hồ sơ công việc, sẽ có các hạn chế về việc liệu ý định có thể chuyển từ hồ sơ này sang hồ sơ khác hay không. Trong hầu hết các trường hợp, khi một ý định bị kích hoạt, ý định đó sẽ được xử lý trên cùng một hồ sơ nơi ý định được kích hoạt. Nếu không có trình xử lý cho ý định trên hồ sơ đó, thì ý định sẽ không được xử lý và ứng dụng kích hoạt ý định đó có thể tắt đột ngột – ngay cả khi có một trình xử lý cho ý định trên hồ sơ khác.

Quản trị viên hồ sơ có thể chọn ý định được phép chuyển từ hồ sơ này sang hồ sơ khác. Vì quản trị viên CNTT đưa ra quyết định này nên bạn không thể biết trước những ý định nào được phép vượt qua ranh giới này. Quản trị viên CNTT đặt ra chính sách này và bạn có thể thay đổi chính sách này bất cứ lúc nào.

Trước khi ứng dụng bắt đầu một hoạt động, bạn nên xác minh rằng có giải pháp phù hợp. Bạn có thể xác minh rằng có độ phân giải chấp nhận được bằng cách gọi Intent.resolveActivity(). Nếu không có cách nào để phân giải ý định, phương thức sẽ trả về null. Nếu phương thức này trả về giá trị khác rỗng, thì có ít nhất một cách để giải quyết ý định và có thể kích hoạt ý định đó một cách an toàn. Trong trường hợp này, ý định có thể giải quyết được vì có một trình xử lý trong hồ sơ hiện tại hoặc vì ý định được phép chuyển sang một trình xử lý trên hồ sơ khác. (Để biết thêm thông tin về việc giải quyết ý định, hãy xem bài viết Các ý định phổ biến.)

Ví dụ: nếu cần hẹn giờ, ứng dụng của bạn cần kiểm tra để đảm bảo có trình xử lý hợp lệ cho ý định ACTION_SET_TIMER. Nếu không thể giải quyết ý định thì ứng dụng phải có hành động thích hợp (chẳng hạn như hiện thông báo lỗi).

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

Chia sẻ tệp giữa nhiều hồ sơ

Đôi khi, một ứng dụng cần cấp cho các ứng dụng khác quyền truy cập vào các tệp của chính ứng dụng đó. Ví dụ: một ứng dụng thư viện hình ảnh có thể muốn chia sẻ hình ảnh của ứng dụng đó với trình chỉnh sửa hình ảnh. Có hai cách bạn thường chia sẻ một tệp: bằng URI tệp hoặc URI nội dung.

URI tệp bắt đầu bằng tiền tố file:, theo sau là đường dẫn tuyệt đối của tệp trên bộ nhớ của thiết bị. Tuy nhiên, vì hồ sơ công việc và hồ sơ cá nhân sử dụng các khu vực lưu trữ riêng biệt, nên một URI tệp hợp lệ trên hồ sơ này lại không hợp lệ trên hồ sơ kia. Trường hợp này có nghĩa là nếu bạn đính kèm URI tệp vào một ý định và ý định đó được xử lý trên hồ sơ khác, thì trình xử lý không thể truy cập vào tệp đó.

Thay vào đó, bạn nên chia sẻ tệp với URI nội dung. URI nội dung xác định tệp theo cách an toàn hơn và có thể chia sẻ. URI nội dung không chỉ chứa đường dẫn tệp, mà còn chứa đơn vị quản lý cung cấp tệp và mã số nhận dạng dùng để xác định tệp. Bạn có thể tạo mã nội dung cho bất kỳ tệp nào bằng cách sử dụng FileProvider. Sau đó, bạn có thể chia sẻ mã nội dung đó với các ứng dụng khác (ngay cả trên hồ sơ khác). Người nhận có thể sử dụng mã nội dung để truy cập vào tệp thực tế.

Ví dụ: dưới đây là cách bạn sẽ lấy URI nội dung cho một URI tệp cụ thể:

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

Khi gọi phương thức getUriForFile(), bạn phải thêm quyền của trình cung cấp tệp (trong ví dụ này là "com.example.myapp.fileprovider"), được chỉ định trong phần tử <provider> của tệp kê khai ứng dụng. Để biết thêm thông tin về cách chia sẻ tệp bằng URI nội dung, hãy xem phần Chia sẻ tệp.

Nghe thông báo

Ứng dụng thường cung cấp lớp con NotificationListenerService để nhận lệnh gọi lại từ hệ thống về các thay đổi đối với thông báo. Các thiết bị có hồ sơ công việc có thể ảnh hưởng đến cách NotificationListenerService hoạt động với ứng dụng của bạn.

Trong hồ sơ công việc

Bạn không thể sử dụng NotificationListenerService của một ứng dụng chạy trong hồ sơ công việc. Khi ứng dụng của bạn đang chạy trong một hồ sơ công việc, hệ thống sẽ bỏ qua NotificationListenerService của ứng dụng. Tuy nhiên, các ứng dụng chạy trong hồ sơ cá nhân có thể theo dõi thông báo.

Trong hồ sơ cá nhân

Khi ứng dụng của bạn chạy trong hồ sơ cá nhân, có thể bạn sẽ không nhận được thông báo về các ứng dụng chạy trong hồ sơ công việc. Theo mặc định, tất cả các ứng dụng hồ sơ cá nhân đều nhận được lệnh gọi lại. Tuy nhiên, quản trị viên CNTT có thể đưa một hoặc nhiều ứng dụng hồ sơ cá nhân vào danh sách cho phép theo dõi các thay đổi về thông báo. Sau đó, hệ thống sẽ chặn các ứng dụng không có trong danh sách cho phép. Trong Android 8.0 (API cấp 26) trở lên, trình kiểm soát chính sách thiết bị (DPC) quản lý hồ sơ công việc có thể chặn ứng dụng theo dõi thông báo của hồ sơ công việc bằng phương thức DevicePolicyManager setPermittedCrossProfileNotificationListeners(). Ứng dụng vẫn nhận được lệnh gọi lại về các thông báo được đăng trong hồ sơ cá nhân.

Kiểm tra khả năng tương thích của ứng dụng với Hồ sơ công việc

Bạn nên kiểm thử ứng dụng trong môi trường hồ sơ công việc để phát hiện các vấn đề có thể khiến ứng dụng của bạn không hoạt động được trên thiết bị có hồ sơ công việc. Cụ thể, việc kiểm thử trên thiết bị hồ sơ công việc là một cách hay để đảm bảo ứng dụng của bạn xử lý các ý định đúng cách: không kích hoạt các ý định không xử lý được, không đính kèm URI không hoạt động trên nhiều hồ sơ, v.v.

Chúng tôi đã cung cấp một ứng dụng mẫu, TestDPC, bạn có thể sử dụng ứng dụng này để thiết lập hồ sơ công việc trên thiết bị Android chạy Android 5.0 (API cấp 21) trở lên. Ứng dụng này cung cấp cho bạn một cách đơn giản để kiểm thử ứng dụng của mình trong môi trường hồ sơ công việc. Bạn cũng có thể sử dụng ứng dụng này để định cấu hình hồ sơ công việc như sau:

  • Chỉ định những ứng dụng mặc định có sẵn trong hồ sơ được quản lý
  • Định cấu hình những ý định được phép chuyển từ hồ sơ này sang hồ sơ khác

Nếu bạn cài đặt một ứng dụng theo cách thủ công qua cáp USB vào một thiết bị có hồ sơ công việc, thì ứng dụng đó sẽ được cài đặt trên cả hồ sơ cá nhân và hồ sơ công việc. Sau khi cài đặt ứng dụng, bạn có thể kiểm thử ứng dụng trong các điều kiện sau:

  • Nếu một ý định thường được ứng dụng mặc định (chẳng hạn như ứng dụng camera), hãy thử tắt ứng dụng mặc định đó trên hồ sơ công việc và xác minh rằng ứng dụng xử lý việc này một cách phù hợp.
  • Nếu bạn kích hoạt một ý định và muốn một số ứng dụng khác xử lý ý định đó, hãy thử bật và tắt quyền chuyển ý định từ hồ sơ này sang hồ sơ khác. Xác minh rằng ứng dụng hoạt động đúng cách trong cả hai trường hợp. Nếu ý định không được phép chuyển đổi giữa các hồ sơ, hãy xác minh hành vi của ứng dụng cả khi có một trình xử lý phù hợp trên hồ sơ ứng dụng và khi chưa có trình xử lý phù hợp. Ví dụ: nếu ứng dụng của bạn kích hoạt một ý định liên quan đến bản đồ, hãy thử từng trường hợp sau:
    • Thiết bị cho phép ánh xạ ý định chuyển từ hồ sơ này sang hồ sơ khác, và có một trình xử lý phù hợp trên hồ sơ khác (hồ sơ mà ứng dụng không chạy trên đó)
    • Thiết bị không cho phép ánh xạ ý định giữa các hồ sơ, nhưng có một trình xử lý phù hợp trên hồ sơ ứng dụng
    • Thiết bị không cho phép ánh xạ ý định giữa các hồ sơ và không có trình xử lý phù hợp nào cho ý định ánh xạ trên hồ sơ thiết bị
  • Nếu bạn đính kèm nội dung vào một ý định, hãy xác minh rằng ý định đó hoạt động đúng cách cả khi được xử lý trên hồ sơ ứng dụng lẫn khi chuyển đổi giữa các hồ sơ.

Kiểm thử trên hồ sơ công việc: mẹo và thủ thuật

Có một số thủ thuật có thể giúp ích cho bạn khi kiểm thử trên thiết bị có hồ sơ công việc.

  • Như đã lưu ý, khi bạn tải một ứng dụng không qua cửa hàng trên thiết bị có hồ sơ công việc, ứng dụng đó sẽ được cài đặt trên cả hai hồ sơ. Nếu muốn, bạn có thể xoá ứng dụng khỏi một hồ sơ và để lại ứng dụng trên hồ sơ còn lại.
  • Hầu hết các lệnh của trình quản lý hoạt động có trong shell Cầu gỡ lỗi Android (adb) đều hỗ trợ cờ --user để cho phép bạn chỉ định người dùng nào cần chạy. Bằng cách chỉ định một người dùng, bạn có thể chọn chạy ứng dụng dưới dạng người dùng chính hoặc hồ sơ công việc không được quản lý. Để biết thêm thông tin, hãy xem phần Lệnh ADB Shell.
  • Để tìm người dùng đang hoạt động trên một thiết bị, hãy sử dụng lệnh list users của trình quản lý gói adb. Số đầu tiên trong chuỗi đầu ra là mã nhận dạng người dùng mà bạn có thể sử dụng với cờ --user. Để biết thêm thông tin, hãy xem phần Lệnh ADB Shell.

Ví dụ: để tìm người dùng trên một thiết bị, bạn sẽ chạy lệnh sau:

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

Trong trường hợp này, người dùng chính("Drew") có mã nhận dạng người dùng là 0 và hồ sơ công việc có mã nhận dạng người dùng là 10. Để chạy một ứng dụng trong hồ sơ công việc, bạn sẽ sử dụng một lệnh như sau:

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER