Sổ tay thiết kế riêng cho thiết bị

Sổ tay nấu ăn này giúp các nhà phát triển và nhà tích hợp hệ thống cải thiện giải pháp thiết bị chuyên dụng của họ. Hãy làm theo công thức hướng dẫn của chúng tôi để tìm giải pháp cho các hành vi trên thiết bị chuyên dụng. Sổ tay nấu ăn này phù hợp nhất với các nhà phát triển đã có ứng dụng thiết bị chuyên dụng. Nếu bạn mới bắt đầu, hãy đọc phần Tổng quan về thiết bị chuyên dụng.

Ứng dụng tuỳ chỉnh trên màn hình chính

Các công thức này sẽ hữu ích nếu bạn đang phát triển một ứng dụng thay thế Màn hình chính và Trình chạy Android.

Là ứng dụng trên màn hình chính

Bạn có thể đặt ứng dụng của mình làm ứng dụng trên màn hình chính của thiết bị để ứng dụng đó tự động chạy khi thiết bị khởi động. Bạn cũng có thể bật nút Màn hình chính để đưa ứng dụng của bạn vào danh sách cho phép lên nền trước ở chế độ khoá tác vụ.

Tất cả ứng dụng trên màn hình chính đều xử lý danh mục ý định CATEGORY_HOME – đây là cách hệ thống nhận dạng ứng dụng trên màn hình chính. Để trở thành ứng dụng trên màn hình chính mặc định, hãy đặt một trong các hoạt động của ứng dụng làm trình xử lý ý định Home ưu tiên, bằng cách gọi DevicePolicyManager.addPersistentPreferredActivity() như trong ví dụ sau:

Kotlin

// Create an intent filter to specify the Home category.
val filter = IntentFilter(Intent.ACTION_MAIN)
filter.addCategory(Intent.CATEGORY_HOME)
filter.addCategory(Intent.CATEGORY_DEFAULT)

// Set the activity as the preferred option for the device.
val activity = ComponentName(context, KioskModeActivity::class.java)
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
dpm.addPersistentPreferredActivity(adminName, filter, activity)

Java

// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);

// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);

Bạn vẫn cần khai báo bộ lọc ý định trong tệp kê khai ứng dụng như minh hoạ trong đoạn mã XML sau:

<activity
        android:name=".KioskModeActivity"
        android:label="@string/kiosk_mode"
        android:launchMode="singleInstance"
        android:excludeFromRecents="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.HOME"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Thông thường, bạn không muốn ứng dụng trình chạy của mình xuất hiện trong màn hình Tổng quan. Tuy nhiên, bạn không cần thêm excludeFromRecents vào phần khai báo hoạt động vì Trình chạy của Android sẽ ẩn hoạt động đã chạy ban đầu khi hệ thống đang chạy ở chế độ khoá tác vụ.

Hiện các việc cần làm riêng biệt

FLAG_ACTIVITY_NEW_TASK có thể là một cờ hữu ích cho các ứng dụng loại trình chạy vì mỗi tác vụ mới sẽ xuất hiện dưới dạng một mục riêng trên màn hình Tổng quan. Để tìm hiểu thêm về các thao tác trên màn hình Tổng quan, hãy đọc bài viết Màn hình gần đây.

Ki-ốt công cộng

Những công thức này phù hợp với các thiết bị không có người giám sát ở nơi công cộng, nhưng cũng có thể giúp nhiều người dùng thiết bị chuyên dụng tập trung vào nhiệm vụ của họ.

Khoá thiết bị

Để đảm bảo sử dụng thiết bị đúng mục đích, bạn có thể thêm các hạn chế đối với người dùng được liệt kê trong bảng 1.

Bảng 1. Hạn chế người dùng đối với thiết bị kiosk
Giới hạn đối với người dùng Nội dung mô tả
DISALLOW_FACTORY_RESET Ngăn người dùng thiết bị đặt lại thiết bị về mặc định ban đầu. Quản trị viên của các thiết bị được quản lý hoàn toàn và người dùng chính có thể đặt quy tắc hạn chế này.
DISALLOW_SAFE_BOOT Không cho phép người dùng thiết bị khởi động thiết bị ở chế độ an toàn, nơi hệ thống sẽ không tự động khởi chạy ứng dụng. Quản trị viên của các thiết bị được quản lý hoàn toàn và người dùng chính có thể đặt giới hạn này.
DISALLOW_MOUNT_PHYSICAL_MEDIA Ngăn người dùng thiết bị gắn bất kỳ phương tiện bộ nhớ nào mà họ có thể gắn vào thiết bị. Quản trị viên của các thiết bị được quản lý hoàn toàn và người dùng chính có thể đặt quy định hạn chế này.
DISALLOW_ADJUST_VOLUME Tắt tiếng thiết bị và ngăn người dùng thiết bị thay đổi các chế độ cài đặt âm lượng và rung. Hãy kiểm tra để đảm bảo rằng kiosk của bạn không cần âm thanh để phát nội dung nghe nhìn hoặc sử dụng bộ tính năng hỗ trợ tiếp cận. Quản trị viên của các thiết bị được quản lý hoàn toàn, người dùng chính, người dùng phụ và hồ sơ công việc có thể đặt quy định hạn chế này.
DISALLOW_ADD_USER Ngăn người dùng thiết bị thêm người dùng mới, chẳng hạn như người dùng phụ hoặc người dùng bị hạn chế. Hệ thống tự động thêm chế độ hạn chế đối với người dùng này vào các thiết bị được quản lý hoàn toàn, nhưng có thể chế độ hạn chế này đã bị xoá. Quản trị viên của các thiết bị được quản lý hoàn toàn và người dùng chính có thể đặt quy định hạn chế này.

Đoạn mã sau đây cho biết cách bạn có thể đặt các quy định hạn chế:

Kotlin

// If the system is running in lock task mode, set the user restrictions
// for a kiosk after launching the activity.
arrayOf(
        UserManager.DISALLOW_FACTORY_RESET,
        UserManager.DISALLOW_SAFE_BOOT,
        UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
        UserManager.DISALLOW_ADJUST_VOLUME,
        UserManager.DISALLOW_ADD_USER).forEach { dpm.addUserRestriction(adminName, it) }

Java

// If the system is running in lock task mode, set the user restrictions
// for a kiosk after launching the activity.
String[] restrictions = {
    UserManager.DISALLOW_FACTORY_RESET,
    UserManager.DISALLOW_SAFE_BOOT,
    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
    UserManager.DISALLOW_ADJUST_VOLUME,
    UserManager.DISALLOW_ADD_USER};

for (String restriction: restrictions) dpm.addUserRestriction(adminName, restriction);

Bạn nên xoá các hạn chế này khi ứng dụng của bạn ở chế độ quản trị viên để quản trị viên CNTT vẫn có thể sử dụng các tính năng này cho việc bảo trì thiết bị. Để xoá quy định hạn chế này, hãy gọi DevicePolicyManager.clearUserRestriction().

Loại bỏ hộp thoại lỗi

Trong một số môi trường, chẳng hạn như minh hoạ bán lẻ hoặc hiển thị thông tin công khai, bạn có thể không muốn hiển thị hộp thoại lỗi cho người dùng. Trong Android 9.0 (API cấp 28) trở lên, bạn có thể ngăn hộp thoại lỗi hệ thống đối với các ứng dụng gặp sự cố hoặc không phản hồi bằng cách thêm giới hạn người dùng DISALLOW_SYSTEM_ERROR_DIALOGS. Hệ thống khởi động lại các ứng dụng không phản hồi như thể người dùng thiết bị đóng ứng dụng trong hộp thoại. Ví dụ sau cho thấy cách thực hiện việc này:

Kotlin

override fun onEnabled(context: Context, intent: Intent) {
    val dpm = getManager(context)
    val adminName = getWho(context)

    dpm.addUserRestriction(adminName, UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS)
}

Java

public void onEnabled(Context context, Intent intent) {
  DevicePolicyManager dpm = getManager(context);
  ComponentName adminName = getWho(context);

  dpm.addUserRestriction(adminName, UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS);
}

Nếu quản trị viên của người dùng chính hoặc phụ đặt ra quy định hạn chế này, thì hệ thống sẽ chỉ áp dụng các hộp thoại báo lỗi cho người dùng đó. Nếu quản trị viên của một thiết bị được quản lý toàn bộ đặt ra hạn chế này, hệ thống sẽ chặn hộp thoại đối với tất cả người dùng.

Luôn bật màn hình

Nếu đang xây dựng kiosk, bạn có thể dừng thiết bị chuyển sang chế độ ngủ khi thiết bị đang chạy hoạt động của ứng dụng. Thêm cờ bố cục FLAG_KEEP_SCREEN_ON vào cửa sổ ứng dụng như minh hoạ trong ví dụ sau:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Keep the screen on and bright while this kiosk activity is running.
    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // Keep the screen on and bright while this kiosk activity is running.
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

Bạn nên kiểm tra xem thiết bị đã được cắm vào nguồn AC, USB hoặc bộ sạc không dây chưa. Đăng ký các thông báo thay đổi pin và sử dụng các giá trị BatteryManager để khám phá trạng thái sạc. Thậm chí, bạn có thể gửi cảnh báo từ xa tới quản trị viên CNTT nếu thiết bị chưa cắm điện. Để biết hướng dẫn từng bước, hãy đọc nội dung Theo dõi mức pin và trạng thái sạc.

Bạn cũng có thể đặt chế độ cài đặt chung STAY_ON_WHILE_PLUGGED_IN để thiết bị luôn bật trong khi kết nối với nguồn điện. Quản trị viên của các thiết bị được quản lý toàn diện, trong Android 6.0 (API cấp 23) trở lên, có thể gọi DevicePolicyManager.setGlobalSetting() như trong ví dụ sau:

Kotlin

val pluggedInto = BatteryManager.BATTERY_PLUGGED_AC or
        BatteryManager.BATTERY_PLUGGED_USB or
        BatteryManager.BATTERY_PLUGGED_WIRELESS
dpm.setGlobalSetting(adminName,
        Settings.Global.STAY_ON_WHILE_PLUGGED_IN, pluggedInto.toString())

Java

int pluggedInto = BatteryManager.BATTERY_PLUGGED_AC |
    BatteryManager.BATTERY_PLUGGED_USB |
    BatteryManager.BATTERY_PLUGGED_WIRELESS;
dpm.setGlobalSetting( adminName,
    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, String.valueOf(pluggedInto));

Gói ứng dụng

Phần này chứa các công thức để cài đặt ứng dụng một cách hiệu quả trên thiết bị chuyên dụng.

Lưu gói ứng dụng vào bộ nhớ đệm

Nếu người dùng cùng một thiết bị dùng chung đều dùng chung một bộ ứng dụng, thì bạn không nên tải ứng dụng xuống bất cứ khi nào có thể. Để đơn giản hoá việc cấp phép cho người dùng trên các thiết bị dùng chung có một nhóm người dùng cố định, chẳng hạn như các thiết bị dành cho worker chuyển dịch, trong Android 9.0 (API cấp 28) trở lên, bạn có thể lưu các gói ứng dụng (APK) cần thiết cho phiên nhiều người dùng vào bộ nhớ đệm.

Quá trình cài đặt tệp APK đã lưu vào bộ nhớ đệm (đã cài đặt trên thiết bị) sẽ diễn ra theo 2 giai đoạn:

  1. Thành phần quản trị của một thiết bị được quản lý hoàn toàn (hoặc một thiết bị được uỷ quyền – xem phần sau đây) sẽ đặt danh sách tệp APK cần giữ lại trên thiết bị.
  2. Các thành phần quản trị của người dùng phụ được liên kết (hoặc người được uỷ quyền) có thể thay mặt người dùng cài đặt tệp APK đã lưu vào bộ nhớ đệm. Quản trị viên của thiết bị được quản lý toàn bộ, người dùng chính hoặc hồ sơ công việc liên kết (hoặc người được uỷ quyền của họ) cũng có thể cài đặt ứng dụng đã lưu vào bộ nhớ đệm nếu cần.

Để thiết lập danh sách tệp APK cần giữ lại trên thiết bị, quản trị viên sẽ gọi DevicePolicyManager.setKeepUninstalledPackages(). Phương thức này không kiểm tra xem tệp APK đã được cài đặt trên thiết bị hay chưa. Phương thức này rất hữu ích nếu bạn muốn cài đặt một ứng dụng ngay trước khi người dùng cần ứng dụng đó. Để lấy danh sách các gói đã đặt trước đó, bạn có thể gọi DevicePolicyManager.getKeepUninstalledPackages(). Sau khi bạn gọi setKeepUninstalledPackages() kèm theo các thay đổi hoặc khi người dùng phụ bị xoá, hệ thống sẽ xoá mọi tệp APK đã lưu vào bộ nhớ đệm không còn cần thiết nữa.

Để cài đặt một tệp APK đã lưu vào bộ nhớ đệm, hãy gọi DevicePolicyManager.installExistingPackage(). Phương thức này chỉ có thể cài đặt một ứng dụng mà hệ thống đã lưu vào bộ nhớ đệm – trước tiên, giải pháp dành riêng cho thiết bị của bạn (hoặc người dùng thiết bị) phải cài đặt ứng dụng trên thiết bị thì bạn mới có thể gọi phương thức này.

Mẫu sau đây cho biết cách bạn có thể sử dụng các lệnh gọi API này trong tài khoản quản trị viên của một thiết bị được quản lý toàn bộ và người dùng phụ:

Kotlin

// Set the package to keep. This method assumes that the package is already
// installed on the device by managed Google Play.
val cachedAppPackageName = "com.example.android.myapp"
dpm.setKeepUninstalledPackages(adminName, listOf(cachedAppPackageName))

// ...

// The admin of a secondary user installs the app.
val success = dpm.installExistingPackage(adminName, cachedAppPackageName)

Java

// Set the package to keep. This method assumes that the package is already
// installed on the device by managed Google Play.
String cachedAppPackageName = "com.example.android.myapp";
List<String> packages = new ArrayList<String>();
packages.add(cachedAppPackageName);
dpm.setKeepUninstalledPackages(adminName, packages);

// ...

// The admin of a secondary user installs the app.
boolean success = dpm.installExistingPackage(adminName, cachedAppPackageName);

Ủy quyền ứng dụng

Bạn có thể uỷ quyền cho một ứng dụng khác quản lý việc lưu ứng dụng vào bộ nhớ đệm. Bạn có thể làm việc này để phân tách các tính năng của giải pháp hoặc cho phép quản trị viên CNTT dùng ứng dụng của riêng họ. Ứng dụng uỷ quyền có các quyền tương tự như thành phần quản trị. Ví dụ: một uỷ quyền ứng dụng của quản trị viên của người dùng phụ có thể gọi installExistingPackage() nhưng không thể gọi setKeepUninstalledPackages().

Để thực hiện lệnh gọi uỷ quyền DevicePolicyManager.setDelegatedScopes() và đưa DELEGATION_KEEP_UNINSTALLED_PACKAGES vào đối số phạm vi. Ví dụ sau đây cho thấy cách bạn có thể làm cho một ứng dụng khác làm đại biểu:

Kotlin

var delegatePackageName = "com.example.tools.kept_app_assist"

// Check that the package is installed before delegating.
try {
    context.packageManager.getPackageInfo(delegatePackageName, 0)
    dpm.setDelegatedScopes(
            adminName,
            delegatePackageName,
            listOf(DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES))
} catch (e: PackageManager.NameNotFoundException) {
    // The delegate app isn't installed. Send a report to the IT admin ...
}

Java

String delegatePackageName = "com.example.tools.kept_app_assist";

// Check that the package is installed before delegating.
try {
  context.getPackageManager().getPackageInfo(delegatePackageName, 0);
  dpm.setDelegatedScopes(
      adminName,
      delegatePackageName,
      Arrays.asList(DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES));
} catch (PackageManager.NameNotFoundException e) {
  // The delegate app isn't installed. Send a report to the IT admin ...
}

Nếu mọi thứ diễn ra suôn sẻ, ứng dụng uỷ quyền sẽ nhận được thông báo ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED và trở thành thực thể được uỷ quyền. Ứng dụng có thể gọi các phương thức trong hướng dẫn này như thể ứng dụng là chủ sở hữu thiết bị hoặc chủ sở hữu hồ sơ. Khi gọi các phương thức DevicePolicyManager, lớp uỷ quyền sẽ truyền null cho đối số thành phần quản trị.

Cài đặt gói ứng dụng

Đôi khi, bạn nên cài đặt một ứng dụng tuỳ chỉnh được lưu vào bộ nhớ đệm cục bộ trên một thiết bị chuyên dụng. Ví dụ: các thiết bị chuyên dụng thường được triển khai ở những môi trường hoặc khu vực có băng thông hạn chế, không có kết nối Internet. Giải pháp dành riêng cho thiết bị của bạn cần lưu ý đến băng thông của khách hàng. Ứng dụng của bạn có thể bắt đầu cài đặt một gói ứng dụng (APK) khác bằng các lớp PackageInstaller.

Mặc dù mọi ứng dụng đều có thể cài đặt tệp APK, nhưng quản trị viên trên các thiết bị được quản lý toàn bộ có thể cài đặt (hoặc gỡ cài đặt) các gói mà không cần sự tương tác của người dùng. Quản trị viên có thể quản lý thiết bị, người dùng phụ được liên kết hoặc hồ sơ công việc được liên kết. Sau khi hoàn tất quá trình cài đặt, hệ thống sẽ đăng một thông báo để tất cả người dùng thiết bị đều nhìn thấy. Thông báo này cho người dùng thiết bị biết rằng quản trị viên đã cài đặt (hoặc cập nhật) ứng dụng.

Bảng 2. Các phiên bản Android hỗ trợ việc cài đặt gói mà không cần sự tương tác của người dùng
Phiên bản Android Thành phần quản trị để cài đặt và gỡ cài đặt
Android 9.0 (API cấp 28) trở lên Người dùng phụ được liên kết và hồ sơ công việc – cả hai đều trên thiết bị được quản lý hoàn toàn
Android 6.0 (API cấp 23) trở lên Thiết bị được quản lý toàn bộ

Cách bạn phân phối một hoặc nhiều bản sao của tệp APK cho các thiết bị chuyên dụng sẽ phụ thuộc vào khoảng cách của các thiết bị và có thể là khoảng cách giữa các thiết bị. Giải pháp của bạn cần tuân theo các phương pháp bảo mật hay nhất trước khi cài đặt tệp APK trên các thiết bị chuyên dụng.

Bạn có thể sử dụng PackageInstaller.Session để tạo một phiên đưa một hoặc nhiều tệp APK vào hàng đợi để cài đặt. Trong ví dụ sau, chúng tôi nhận được phản hồi về trạng thái ở chế độ singleTop) nhưng bạn có thể sử dụng một dịch vụ hoặc broadcast receiver:

Kotlin

// First, create a package installer session.
val packageInstaller = context.packageManager.packageInstaller
val params = PackageInstaller.SessionParams(
        PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = packageInstaller.createSession(params)
val session = packageInstaller.openSession(sessionId)

// Add the APK binary to the session. The APK is included in our app binary
// and is read from res/raw but file storage is a more typical location.
// The I/O streams can't be open when installation begins.
session.openWrite("apk", 0, -1).use { output ->
    getContext().resources.openRawResource(R.raw.app).use { input ->
        input.copyTo(output, 2048)
    }
}

// Create a status receiver to report progress of the installation.
// We'll use the current activity.
// Here we're requesting status feedback to our Activity but this can be a
// service or broadcast receiver.
val intent = Intent(context, activity.javaClass)
intent.action = "com.android.example.APK_INSTALLATION_ACTION"
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
val statusReceiver = pendingIntent.intentSender

// Start the installation. Because we're an admin of a fully managed device,
// there isn't any user interaction.
session.commit(statusReceiver)

Java

// First, create a package installer session.
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);

// Add the APK binary to the session. The APK is included in our app binary
// and is read from res/raw but file storage is a more typical location.
try (
    // These I/O streams can't be open when installation begins.
    OutputStream output = session.openWrite("apk", 0, -1);
    InputStream input = getContext().getResources().openRawResource(R.raw.app);
) {
  byte[] buffer = new byte[2048];
  int n;
  while ((n = input.read(buffer)) >= 0) {
    output.write(buffer, 0, n);
  }
}

// Create a status receiver to report progress of the installation.
// We'll use the current activity.
// Here we're requesting status feedback to our Activity but this can be a
// service or broadcast receiver.
Intent intent = new Intent(context, getActivity().getClass());
intent.setAction("com.android.example.APK_INSTALLATION_ACTION");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
IntentSender statusReceiver = pendingIntent.getIntentSender();

// Start the installation. Because we're an admin of a fully managed device,
// there isn't any user interaction.
session.commit(statusReceiver);

Phiên này sử dụng ý định để gửi phản hồi về trạng thái của việc cài đặt. Kiểm tra trường EXTRA_STATUS của từng ý định để biết trạng thái. Hãy nhớ rằng quản trị viên không nhận được thông tin cập nhật trạng thái STATUS_PENDING_USER_ACTION vì người dùng thiết bị chưa cần phê duyệt việc cài đặt.

Để gỡ cài đặt ứng dụng, bạn có thể gọi hàm PackageInstaller.uninstall. Quản trị viên của các thiết bị, người dùng và hồ sơ công việc được quản lý toàn diện có thể gỡ cài đặt các gói mà không cần sự tương tác của người dùng chạy các phiên bản Android được hỗ trợ (xem bảng 2).

Cố định bản cập nhật hệ thống

Thiết bị Android nhận các bản cập nhật qua mạng không dây (OTA) cho hệ thống và phần mềm ứng dụng. Để đóng băng phiên bản hệ điều hành trong các khoảng thời gian quan trọng, chẳng hạn như ngày lễ hoặc các thời điểm khác, các thiết bị chuyên dụng có thể tạm ngưng bản cập nhật hệ thống OTA trong tối đa 90 ngày. Để tìm hiểu thêm, hãy đọc bài viết Quản lý bản cập nhật hệ thống.

Cấu hình từ xa

Cấu hình được quản lý của Android cho phép quản trị viên CNTT định cấu hình ứng dụng của bạn từ xa. Bạn nên hiển thị các chế độ cài đặt như danh sách cho phép, máy chủ mạng hoặc URL nội dung để giúp ứng dụng của bạn hữu ích hơn cho quản trị viên CNTT.

Nếu ứng dụng của bạn tiết lộ cấu hình của nó, hãy nhớ đưa chế độ cài đặt vào tài liệu. Để tìm hiểu thêm về việc hiển thị cấu hình của ứng dụng và phản ứng với những thay đổi trong chế độ cài đặt, hãy đọc bài viết Thiết lập cấu hình được quản lý.

Thiết lập quá trình phát triển

Trong khi phát triển giải pháp cho các thiết bị chuyên dụng, đôi khi, bạn nên đặt ứng dụng của mình làm quản trị viên của một thiết bị được quản lý hoàn toàn mà không cần đặt lại về trạng thái ban đầu. Để thiết lập quản trị viên của một thiết bị được quản lý hoàn toàn, hãy làm theo các bước sau:

  1. Tạo và cài đặt ứng dụng trình kiểm soát chính sách thiết bị (DPC) trên thiết bị.
  2. Kiểm tra để đảm bảo không có tài khoản nào trên thiết bị.
  3. Chạy lệnh sau trong shell Cầu gỡ lỗi Android (adb). Bạn cần thay thế com.example.dpc/.MyDeviceAdminReceiver trong ví dụ bằng tên thành phần quản trị của ứng dụng:

    adb shell dpm set-device-owner com.example.dpc/.MyDeviceAdminReceiver

Để giúp khách hàng triển khai giải pháp của bạn, bạn sẽ cần xem xét các phương thức đăng ký khác. Bạn nên đăng ký mã QR cho các thiết bị chuyên dụng.

Tài nguyên khác

Để tìm hiểu thêm về các thiết bị chuyên dụng, hãy đọc các tài liệu sau: