Thiết lập cấu hình được quản lý

Nếu đang phát triển ứng dụng cho thị trường doanh nghiệp, bạn có thể cần phải đáp ứng các yêu cầu cụ thể do chính sách của tổ chức đặt ra. Cấu hình được quản lý (trước đây gọi là quy tắc hạn chế của ứng dụng) cho phép quản trị viên CNTT của tổ chức chỉ định các chế độ cài đặt cho ứng dụng từ xa. Năng lực này đặc biệt hữu ích đối với các ứng dụng được doanh nghiệp phê duyệt đã được triển khai cho hồ sơ công việc.

Ví dụ: một tổ chức có thể yêu cầu các ứng dụng đã phê duyệt cho phép quản trị viên CNTT:

  • Cho phép hoặc chặn URL cho trình duyệt web
  • Định cấu hình xem ứng dụng có được phép đồng bộ hoá nội dung qua mạng di động hay chỉ qua Wi-Fi
  • Định cấu hình chế độ cài đặt email của ứng dụng

Hướng dẫn này cho biết cách triển khai chế độ cài đặt cấu hình được quản lý trong ứng dụng. Để xem các ứng dụng mẫu có cấu hình được quản lý, hãy xem ManagedConfigurations. Nếu bạn là nhà phát triển giải pháp quản lý di động dành cho doanh nghiệp (EMM), hãy tham khảo hướng dẫn về API Quản lý Android.

Lưu ý: Vì lý do lịch sử, các chế độ cài đặt cấu hình này được gọi là hạn chế và được triển khai bằng các tệp và lớp sử dụng thuật ngữ này (chẳng hạn như RestrictionsManager). Tuy nhiên, các hạn chế này thực sự có thể triển khai nhiều tuỳ chọn cấu hình, chứ không chỉ hạn chế chức năng của ứng dụng.

Tổng quan về cấu hình từ xa

Ứng dụng xác định các tuỳ chọn cấu hình được quản lý mà quản trị viên CNTT có thể đặt từ xa. Đây là các chế độ cài đặt tuỳ ý mà nhà cung cấp cấu hình được quản lý có thể thay đổi. Nếu ứng dụng của bạn đang chạy trong hồ sơ công việc, thì quản trị viên CNTT có thể thay đổi cấu hình được quản lý của ứng dụng.

Nhà cung cấp cấu hình được quản lý là một ứng dụng khác chạy trên cùng một thiết bị. Ứng dụng này thường do quản trị viên CNTT kiểm soát. Quản trị viên CNTT thông báo các thay đổi về cấu hình cho ứng dụng nhà cung cấp cấu hình được quản lý. Đổi lại, ứng dụng đó sẽ thay đổi cấu hình trên ứng dụng của bạn.

Cách cung cấp cấu hình được quản lý bên ngoài:

  • Khai báo các cấu hình được quản lý trong tệp kê khai ứng dụng. Việc này cho phép quản trị viên CNTT đọc cấu hình của ứng dụng thông qua API Google Play.
  • Bất cứ khi nào ứng dụng tiếp tục, hãy sử dụng đối tượng RestrictionsManager để kiểm tra các cấu hình được quản lý hiện tại, đồng thời thay đổi giao diện người dùng và hành vi của ứng dụng để tuân thủ các cấu hình đó.
  • Nghe ý định ACTION_APPLICATION_RESTRICTIONS_CHANGED. Khi bạn nhận được thông báo truyền tin này, hãy kiểm tra RestrictionsManager để xem các cấu hình được quản lý hiện tại là gì và thực hiện mọi thay đổi cần thiết đối với hành vi của ứng dụng.

Xác định cấu hình được quản lý

Ứng dụng của bạn có thể hỗ trợ mọi cấu hình được quản lý mà bạn muốn xác định. Bạn khai báo cấu hình được quản lý của ứng dụng trong tệp cấu hình được quản lý và khai báo tệp cấu hình trong tệp kê khai. Việc tạo tệp cấu hình cho phép các ứng dụng khác kiểm tra cấu hình được quản lý mà ứng dụng của bạn cung cấp. Các đối tác EMM có thể đọc cấu hình của ứng dụng bằng cách sử dụng API Google Play.

Để xác định các tuỳ chọn cấu hình từ xa của ứng dụng, hãy đặt phần tử sau vào phần tử <application> của tệp kê khai:

<meta-data android:name="android.content.APP_RESTRICTIONS"
    android:resource="@xml/app_restrictions" />

Tạo một tệp có tên là app_restrictions.xml trong thư mục res/xml của ứng dụng. Cấu trúc của tệp đó được mô tả trong tài liệu tham khảo cho RestrictionsManager. Tệp này có một phần tử <restrictions> cấp cao nhất, chứa một phần tử con <restriction> cho mỗi tuỳ chọn cấu hình mà ứng dụng có.

Lưu ý: Không tạo phiên bản đã bản địa hoá của tệp cấu hình được quản lý. Ứng dụng của bạn chỉ được phép có một tệp cấu hình được quản lý, vì vậy, cấu hình sẽ nhất quán cho ứng dụng của bạn ở mọi ngôn ngữ.

Trong môi trường doanh nghiệp, EMM thường sẽ sử dụng giản đồ cấu hình được quản lý để tạo bảng điều khiển từ xa cho quản trị viên CNTT, nhờ đó, quản trị viên có thể định cấu hình ứng dụng từ xa.

Nhà cung cấp cấu hình được quản lý có thể truy vấn ứng dụng để tìm thông tin chi tiết về các cấu hình có sẵn của ứng dụng, bao gồm cả văn bản mô tả. Nhà cung cấp cấu hình và quản trị viên CNTT có thể thay đổi cấu hình được quản lý của ứng dụng bất cứ lúc nào, ngay cả khi ứng dụng không chạy.

Ví dụ: giả sử bạn có thể định cấu hình từ xa để cho phép hoặc cấm ứng dụng tải dữ liệu xuống qua kết nối di động. Ứng dụng của bạn có thể có phần tử <restriction> như sau:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">

  <restriction
    android:key="downloadOnCellular"
    android:title="@string/download_on_cell_title"
    android:restrictionType="bool"
    android:description="@string/download_on_cell_description"
    android:defaultValue="true" />

</restrictions>

Bạn sử dụng thuộc tính android:key của mỗi cấu hình để đọc giá trị của thuộc tính đó từ gói cấu hình được quản lý. Vì lý do này, mỗi cấu hình phải có một chuỗi khoá duy nhất và chuỗi này không thể được bản địa hoá. Bạn phải chỉ định giá trị này bằng một giá trị cố định dạng chuỗi.

Lưu ý: Trong ứng dụng chính thức, android:titleandroid:description phải được lấy từ tệp tài nguyên được bản địa hoá, như mô tả trong phần Bản địa hoá bằng tài nguyên.

Ứng dụng xác định các quy định hạn chế bằng cách sử dụng các gói trong bundle_array. Ví dụ: một ứng dụng có nhiều tuỳ chọn kết nối VPN có thể xác định từng cấu hình máy chủ VPN trong bundle, với nhiều gói được nhóm lại với nhau trong một mảng gói:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >

  <restriction
    android:key="vpn_configuration_list"
    android:restrictionType="bundle_array">
    <restriction
      android:key="vpn_configuration"
      android:restrictionType="bundle">
      <restriction
        android:key="vpn_server"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_username"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_password"
        android:restrictionType="string"/>
    </restriction>
  </restriction>

</restrictions>

Các loại được hỗ trợ cho phần tử android:restrictionType được liệt kê trong Bảng 1 và được ghi lại trong tài liệu tham khảo cho RestrictionsManagerRestrictionEntry.

Bảng 1. Loại mục nhập hạn chế và cách sử dụng.

Loại android:restrictionType Cách sử dụng thông thường
TYPE_BOOLEAN "bool" Giá trị boolean, đúng hoặc sai.
TYPE_STRING "string" Giá trị chuỗi, chẳng hạn như tên.
TYPE_INTEGER "integer" Một số nguyên có giá trị từ MIN_VALUE đến MAX_VALUE.
TYPE_CHOICE "choice" Giá trị chuỗi được chọn từ android:entryValues, thường được trình bày dưới dạng danh sách chọn một.
TYPE_MULTI_SELECT "multi-select" Một mảng chuỗi có các giá trị được chọn từ android:entryValues. Sử dụng thuộc tính này để hiển thị danh sách nhiều lựa chọn, trong đó có thể chọn nhiều mục, chẳng hạn như để chọn các tiêu đề cụ thể cho danh sách cho phép.
TYPE_NULL "hidden" Loại hạn chế ẩn. Sử dụng loại này cho thông tin cần được chuyển nhưng không được hiển thị cho người dùng trong giao diện người dùng. Lưu trữ một giá trị chuỗi duy nhất.
TYPE_BUNDLE_ARRAY "bundle_array" Sử dụng loại này để lưu trữ các mảng hạn chế bundles. Có trong Android 6.0 (API cấp 23).

Lưu ý: android:entryValues có thể đọc được bằng máy và không thể được bản địa hoá. Sử dụng android:entries để trình bày các giá trị mà con người có thể đọc được và có thể được bản địa hoá. Mỗi mục nhập phải có một chỉ mục tương ứng trong android:entryValues.

Kiểm tra cấu hình được quản lý

Ứng dụng của bạn không tự động được thông báo khi các ứng dụng khác thay đổi chế độ cài đặt cấu hình. Thay vào đó, bạn cần kiểm tra cấu hình được quản lý khi ứng dụng khởi động hoặc tiếp tục, đồng thời theo dõi ý định của hệ thống để tìm hiểu xem cấu hình có thay đổi trong khi ứng dụng đang chạy hay không.

Để tìm hiểu các chế độ cài đặt cấu hình hiện tại, ứng dụng của bạn sẽ sử dụng đối tượng RestrictionsManager. Ứng dụng của bạn phải kiểm tra các cấu hình được quản lý hiện tại vào những thời điểm sau:

Để lấy đối tượng RestrictionsManager, hãy lấy hoạt động hiện tại bằng getActivity(), sau đó gọi phương thức Activity.getSystemService() của hoạt động đó:

Kotlin

var myRestrictionsMgr =
        activity?.getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager

Java

RestrictionsManager myRestrictionsMgr =
    (RestrictionsManager) getActivity()
        .getSystemService(Context.RESTRICTIONS_SERVICE);

Sau khi có RestrictionsManager, bạn có thể lấy chế độ cài đặt cấu hình hiện tại bằng cách gọi phương thức getApplicationRestrictions():

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

Lưu ý: Để thuận tiện, bạn cũng có thể tìm nạp các cấu hình hiện tại bằng UserManager, bằng cách gọi UserManager.getApplicationRestrictions(). Phương thức này hoạt động giống hệt như RestrictionsManager.getApplicationRestrictions().

Phương thức getApplicationRestrictions() yêu cầu đọc từ bộ nhớ dữ liệu, vì vậy, bạn nên sử dụng phương thức này một cách tiết kiệm. Đừng gọi phương thức này mỗi khi bạn cần biết cấu hình hiện tại. Thay vào đó, bạn nên gọi một lần khi ứng dụng khởi động hoặc tiếp tục và lưu gói cấu hình được quản lý đã tìm nạp vào bộ nhớ đệm. Sau đó, hãy theo dõi ý định ACTION_APPLICATION_RESTRICTIONS_CHANGED để tìm hiểu xem cấu hình có thay đổi trong khi ứng dụng của bạn đang hoạt động hay không, như mô tả trong phần Nghe các thay đổi về cấu hình được quản lý.

Đọc và áp dụng cấu hình được quản lý

Phương thức getApplicationRestrictions() trả về một Bundle chứa một cặp khoá-giá trị cho mỗi cấu hình đã được đặt. Tất cả giá trị đều thuộc loại Boolean, int, StringString[]. Sau khi có cấu hình được quản lý Bundle, bạn có thể kiểm tra chế độ cài đặt cấu hình hiện tại bằng các phương thức Bundle chuẩn cho các loại dữ liệu đó, chẳng hạn như getBoolean() hoặc getString().

Lưu ý: Cấu hình được quản lý Bundle chứa một mục cho mỗi cấu hình đã được nhà cung cấp cấu hình được quản lý đặt rõ ràng. Tuy nhiên, bạn không thể giả định rằng một cấu hình sẽ có trong gói chỉ vì bạn đã xác định giá trị mặc định trong tệp XML cấu hình được quản lý.

Ứng dụng của bạn sẽ quyết định hành động thích hợp dựa trên chế độ cài đặt cấu hình được quản lý hiện tại. Ví dụ: nếu ứng dụng của bạn có một cấu hình chỉ định xem ứng dụng có thể tải dữ liệu xuống qua kết nối di động hay không và bạn thấy cấu hình được đặt thành false, thì bạn sẽ phải tắt tính năng tải dữ liệu xuống, ngoại trừ khi thiết bị có kết nối Wi-Fi, như trong mã ví dụ sau:

Kotlin

val appCanUseCellular: Boolean =
        if (appRestrictions.containsKey("downloadOnCellular")) {
            appRestrictions.getBoolean("downloadOnCellular")
        } else {
            // cellularDefault is a boolean using the restriction's default value
            cellularDefault
        }

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Java

boolean appCanUseCellular;

if (appRestrictions.containsKey("downloadOnCellular")) {
    appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
} else {
    // cellularDefault is a boolean using the restriction's default value
    appCanUseCellular = cellularDefault;
}

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Để áp dụng nhiều quy định hạn chế lồng nhau, hãy đọc mục nhập hạn chế bundle_array dưới dạng một tập hợp các đối tượng Parcelable và truyền dưới dạng Bundle. Trong ví dụ này, dữ liệu cấu hình của mỗi VPN được phân tích cú pháp và dùng để tạo danh sách các lựa chọn kết nối máy chủ:

Kotlin

// VpnConfig is a sample class used store config data, not defined
val vpnConfigs = mutableListOf<VpnConfig>()

val parcelables: Array<out Parcelable>? =
        appRestrictions.getParcelableArray("vpn_configuration_list")

if (parcelables?.isNotEmpty() == true) {
    // iterate parcelables and cast as bundle
    parcelables.map { it as Bundle }.forEach { vpnConfigBundle ->
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(VpnConfig()
                .setServer(vpnConfigBundle.getString("vpn_server"))
                .setUsername(vpnConfigBundle.getString("vpn_username"))
                .setPassword(vpnConfigBundle.getString("vpn_password")))
    }
}

if (vpnConfigs.isNotEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Java

// VpnConfig is a sample class used store config data, not defined
List<VpnConfig> vpnConfigs = new ArrayList<>();

Parcelable[] parcelables =
    appRestrictions.getParcelableArray("vpn_configuration_list");

if (parcelables != null && parcelables.length > 0) {
    // iterate parcelables and cast as bundle
    for (int i = 0; i < parcelables.length; i++) {
        Bundle vpnConfigBundle = (Bundle) parcelables[i];
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(new VpnConfig()
            .setServer(vpnConfigBundle.getString("vpn_server"))
            .setUsername(vpnConfigBundle.getString("vpn_username"))
            .setPassword(vpnConfigBundle.getString("vpn_password")));
    }
}

if (!vpnConfigs.isEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Theo dõi các thay đổi về cấu hình được quản lý

Bất cứ khi nào cấu hình được quản lý của ứng dụng thay đổi, hệ thống sẽ kích hoạt ý định ACTION_APPLICATION_RESTRICTIONS_CHANGED. Ứng dụng của bạn phải theo dõi ý định này để bạn có thể thay đổi hành vi của ứng dụng khi chế độ cài đặt cấu hình thay đổi.

Lưu ý: Ý định ACTION_APPLICATION_RESTRICTIONS_CHANGED chỉ được gửi đến trình nghe được đăng ký động, không gửi đến trình nghe được khai báo trong tệp kê khai ứng dụng.

Mã sau đây cho biết cách đăng ký động một broadcast receiver cho ý định này:

Kotlin

val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)

val restrictionsReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        // Get the current configuration bundle
        val appRestrictions = myRestrictionsMgr.applicationRestrictions

        // Check current configuration settings, change your app's UI and
        // functionality as necessary.
    }
}

registerReceiver(restrictionsReceiver, restrictionsFilter)

Java

IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
  @Override public void onReceive(Context context, Intent intent) {

    // Get the current configuration bundle
    Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

    // Check current configuration settings, change your app's UI and
    // functionality as necessary.
  }
};

registerReceiver(restrictionsReceiver, restrictionsFilter);

Lưu ý: Thông thường, ứng dụng của bạn không cần được thông báo về các thay đổi về cấu hình khi bị tạm dừng. Thay vào đó, bạn nên huỷ đăng ký broadcast receiver khi ứng dụng bị tạm dừng. Khi ứng dụng tiếp tục, trước tiên, bạn hãy kiểm tra các cấu hình được quản lý hiện tại (như đã thảo luận trong phần Kiểm tra cấu hình được quản lý), sau đó đăng ký broadcast receiver để đảm bảo bạn được thông báo về các thay đổi về cấu hình xảy ra trong khi ứng dụng đang hoạt động.

Gửi ý kiến phản hồi về cấu hình được quản lý cho EMM

Sau khi áp dụng các thay đổi về cấu hình được quản lý cho ứng dụng, tốt nhất bạn nên thông báo cho EMM về trạng thái của thay đổi. Android hỗ trợ một tính năng có tên là trạng thái ứng dụng được khoá. Bạn có thể sử dụng tính năng này để gửi phản hồi mỗi khi ứng dụng của bạn cố gắng áp dụng các thay đổi về cấu hình được quản lý. Thông tin phản hồi này có thể đóng vai trò là xác nhận rằng ứng dụng của bạn đã thiết lập cấu hình được quản lý thành công hoặc có thể bao gồm thông báo lỗi nếu ứng dụng của bạn không áp dụng được các thay đổi đã chỉ định.

Nhà cung cấp EMM có thể truy xuất và hiển thị ý kiến phản hồi này trong bảng điều khiển của họ để quản trị viên CNTT xem. Hãy xem bài viết Gửi ý kiến phản hồi về ứng dụng cho EMM để biết thêm thông tin về chủ đề này, bao gồm cả hướng dẫn chi tiết về cách thêm tính năng hỗ trợ phản hồi vào ứng dụng.

Mã mẫu khác

Mẫu ManagedConfigurations minh hoạ thêm về cách sử dụng các API được trình bày trên trang này.

Đưa ứng dụng vào danh sách cho phép/chặn trên hồ sơ cá nhân

Các cửa hàng ứng dụng bên thứ ba có thể muốn sử dụng Cấu hình được quản lý để có một cách đáng tin cậy để áp dụng danh sách chặn hoặc danh sách cho phép ứng dụng cho cả hồ sơ cá nhân và tính năng Không gian riêng tư của người dùng. Đây là một không gian cá nhân bổ sung để người dùng lưu trữ các ứng dụng nhạy cảm của họ. Nếu bạn phát triển một cửa hàng ứng dụng dành cho doanh nghiệp và muốn sử dụng tính năng này, hãy gửi biểu mẫu này để bày tỏ sự quan tâm và chọn Muốn đưa vào danh sách cho phép của cửa hàng ứng dụng bên thứ ba làm Lý do trả lời trong biểu mẫu.