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, có thể bạn cần để đá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à hạn chế của ứng dụng, cho phép quản trị viên CNTT của tổ chức chỉ định từ xa các chế độ cài đặt cho của chúng tôi. Tính năng này đặc biệt hữu ích đối với những tổ chức được tổ chức phê duyệt các ứng dụng đượ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 đã được phê duyệt cho phép Quản trị viên CNTT để:

  • Cho phép hoặc chặn URL của một trình duyệt web
  • Định cấu hình xem một ứng dụng được phép đồng bộ hóa 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 trình bày cách triển khai chế độ cài đặt cấu hình được quản lý trong ứng dụng của bạn. Để xem các ứng dụng mẫu có cấu hình được quản lý, hãy xem phần 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ề Android Management API.

Lưu ý: Vì lý do trước đây, những 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 tính năng này cụm từ tìm kiếm (chẳng hạn như RestrictionsManager). Tuy nhiên, những thực sự có thể triển khai nhiều lựa chọn cấu hình, chứ không chỉ các hạn chế về chức năng của ứng dụng.

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

Các ứng dụng xác định những lựa chọn cấu hình được quản lý có thể truy cập từ xa do quản trị viên CNTT thiết lập. Đây là các chế độ cài đặt tuỳ ý có thể đã bị nhà cung cấp cấu hình quản lý 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 đang 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. Chiến lược phát hành đĩa đơn Quản trị viên CNTT thông báo về những thay đổi về cấu hình cho ứng dụng của nhà cung cấp cấu hình. Sau đó, ứ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ấu hình được quản lý trong tệp kê khai ứng dụng. Đang thực hiện để cho phép quản trị viên CNTT đọc 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 hiện tại cấu hình được quản lý, cũng như thay đổi giao diện người dùng và hành vi của ứng dụng thành 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 này truyền tin, hãy kiểm tra RestrictionsManager để xem các cấu hình hiện được quản lý 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ý rồi 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. Đối tác quản lý di động doanh nghiệp (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 lựa chọn cấu hình từ xa của ứng dụng, hãy đặt phần tử sau trong tệp kê khai của bạn Phần tử <application>:

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

Tạo một tệp có tên app_restrictions.xml trong Thư mục res/xml. Cấu trúc của tệp đó được mô tả trong tham chiếu 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 cấu hình mà ứng dụng có.

Lưu ý: Không tạo các 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ý, do đó, các cấu hình sẽ được nhất quán cho ứng dụng của bạn bằng tất cả các ngôn ngữ.

Trong môi trường doanh nghiệp, EMM thường sẽ sử dụng giản đồ cấu hình để tạo một bảng điều khiển từ xa cho bộ phận CNTT quản trị viên để quản trị viên có thể định cấu hình 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 dựa trên các cấu hình có sẵn của ứng dụng, bao gồm cả nội dung 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ý bất cứ lúc nào, ngay cả khi ứng dụng không chạy.

Ví dụ: giả sử ứng dụng của bạn có thể được định cấu hình từ xa để cho phép hoặc cấm để 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 từng cấu hình để đọc giá trị của thông số đó 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 không thể bản địa hoá. Giá trị này phải được chỉ định bằng một giá trị cố định kiểu chuỗi.

Lưu ý: Trong ứng dụng phát hành công khai, android:titleandroid:description phải được vẽ từ một tài nguyên đã bản địa hoá như được mô tả trong Bản địa hoá thông qua phần Tài nguyên.

Một ứng dụng xác định các hạn chế bằng cách sử dụng gói trong bundle_array. Ví dụ: một ứng dụng có nhiều lựa chọn kết nối VPN có thể xác định từng máy chủ VPN cấu hình trong bundle, với nhiều các 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 tham chiếu cho RestrictionsManagerRestrictionEntry.

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

Loại android:restrictionType Mức sử dụng thông thường
TYPE_BOOLEAN "bool" Một giá trị boolean, true hoặc false.
TYPE_STRING "string" Một giá trị chuỗi, chẳng hạn như tên.
TYPE_INTEGER "integer" Số nguyên có giá trị từ MIN_VALUE thành MAX_VALUE
TYPE_CHOICE "choice" Một giá trị chuỗi được chọn từ android:entryValues, thường được hiển thị dưới dạng danh sách một phương án.
TYPE_MULTI_SELECT "multi-select" Một mảng chuỗi với các giá trị được chọn từ android:entryValues. Sử dụng phương thức này để trình bày một danh sách có nhiều phương án bạn có thể chọn mục nhập, chẳng hạn như để chọn bộ phim/chương trình cụ thể vào danh sách cho phép.
TYPE_NULL "hidden" Loại quy định hạn chế đã ẩn. Sử dụng loại này cho thông tin cần được truyền qua 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 đơn.
TYPE_BUNDLE_ARRAY "bundle_array" Sử dụng cách 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 nên không thể đọc được đã bản địa hoá. Sử dụng android:entries để trình bày các giá trị con người có thể đọc được và có thể được bản địa hoá. Mỗi mục 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 sẽ không tự động được thông báo khi các ứng dụng khác thay đổi phần cài đặt cấu hình. Thay vào đó, bạn cần kiểm tra xem là khi ứng dụng của bạn khởi động hoặc tiếp tục và theo dõi hệ thống có ý định tìm hiểu xem cấu hình có thay đổi trong khi ứng dụng của bạn đang chạy.

Để 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ẽ dùng một Đối tượng RestrictionsManager. Ứng dụng của bạn sẽ hãy kiểm tra cấu hình hiện được quản lý tại các thời điểm sau:

Để có đối tượng RestrictionsManager, hãy lấy đối tượng hiện tại hoạt động với 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ể tải 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 giá trị hiện tại các cấu hình có UserManager, bằng cách gọi UserManager.getApplicationRestrictions(). Phương thức này hoạt động chính xác bằng với 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 thực hiện một cách thận trọng. Khô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 lệnh này 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 đó nghe cho ý định ACTION_APPLICATION_RESTRICTIONS_CHANGED để tìm hiểu xem cấu hình thay đổi khi ứng dụng đang hoạt động, như mô tả trong 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ề Bundle chứa cặp khoá-giá trị cho từng cấu hình đã được đặt. Chiến lược phát hành đĩa đơn các giá trị đều thuộc loại Boolean, int, StringString[]. Sau khi cài đặt xong cấu hình được quản lý Bundle, bạn có thể kiểm tra bằng các phương thức Bundle chuẩn cho các kiểu 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 đặt rõ ràng bởi nhà cung cấp cấu hình được quản lý. Tuy nhiên, bạn không thể cho rằng một cấu hình sẽ có trong gói chỉ vì bạn đã xác định một cấu hình mặc định trong tệp XML cấu hình được quản lý.

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

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 hạn chế lồng nhau, hãy đọc bundle_array mục hạn chế 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, 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 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 một ứ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 lắng nghe ý đị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 cho trình nghe được đăng ký động, không cho trình nghe được khai báo trong tệp kê khai ứng dụng.

Đoạn mã sau đây minh hoạ cách đăng ký linh độ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 nhận thông báo về các thay đổi về cấu hình khi cấu hình bị tạm dừng. Thay vào đó, bạn nên huỷ đăng ký broadcast receiver của bạn khi ứng dụng bị tạm dừng. Khi ứng dụng được tiếp tục, bạn kiểm tra trước các cấu hình hiện được quản lý (như được thảo luận trong Kiểm tra cấu hình được quản lý), sau đó đăng ký broadcast receiver của bạn để đảm bảo bạn được thông báo về các thay đổi về cấu hình xảy ra khi ứng dụng đang hoạt động.

Gửi 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 của bạn, cách tốt nhất là thông báo cho EMM về trạng thái của thay đổi. Android hỗ trợ tính năng có tên là trạng thái ứng dụng theo khoá. Bạn có thể dùng để 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ý. Chiến dịch này phản hồi có thể đóng vai trò xác nhận rằng ứng dụng của bạn đã thiết lập thành công cấu hình được quản lý, hoặc gửi kèm thông báo lỗi nếu ứng dụng của bạn không áp dụng được những thay đổi được chỉ định.

Các nhà cung cấp dịch vụ EMM có thể truy xuất và hiển thị phản hồi này trong bảng điều khiển của họ dành cho bộ phận CNTT quản trị viên để xem. Xem bài viết Gửi ý kiến phản hồi về ứng dụng cho dịch vụ EMM để biết thêm thông tin 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

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