ספר מתכונים לשימוש במכשירים ייעודיים

ספר המתכונים הזה עוזר למפתחים ולמטמיעי מערכות לשפר את במכשיר. כדאי לעקוב אחר המתכונים שלנו כדי למצוא פתרונות למכשיר ייעודי והתנהגויות. ספר המתכונים הזה מתאים במיוחד למפתחים שכבר יש להם אפליקציה לניהול מכשיר משני – אם רק התחלתם להשתמש באפליקציה, מומלץ לקרוא את המאמר מכשירים ייעודיים סקירה כללית.

אפליקציות דף בית בהתאמה אישית

המתכונים האלה שימושיים אם אתם מפתחים אפליקציה שתחליף את Android Home במסך ובמרכז האפליקציות.

אפליקציית דף הבית

ניתן להגדיר את האפליקציה כאפליקציית דף הבית של המכשיר כדי שהיא תושק באופן אוטומטי כשהמכשיר מופעל. אפשר גם להפעיל את דף הבית לחצן שמוביל את האפליקציה שברשימת ההיתרים לחזית במסך הנעילה במצב משימה.

כל אפליקציות הבית מתייחסות לקטגוריית ה-Intent CATEGORY_HOME – זו הוא האופן שבו המערכת מזהה אפליקציית דף בית. כדי להפוך לאפליקציית ברירת המחדל לדף הבית, צריך להגדיר אחת של הפעילויות של האפליקציה בתור ה-handler המועדף של Intent Home, על ידי קריאה DevicePolicyManager.addPersistentPreferredActivity() כפי שאפשר לראות בדוגמה הבאה:

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);

עדיין לא צריך להצהיר על מסנן כוונת רכישה בקובץ המניפסט של האפליקציה, כפי שמוצג בקטע הקוד הבא בפורמט XML:

<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>

בדרך כלל לא רוצים שאפליקציית מרכז האפליקציות תופיע במסך הסקירה הכללית. עם זאת, לא צריך להוסיף את התג excludeFromRecents הצהרת הפעילות כי מרכז האפליקציות של Android מסתיר את פעילות כשהמערכת פועלת במצב 'נעילה'.

הצגת משימות נפרדות

FLAG_ACTIVITY_NEW_TASK יכול להיות סימון מועיל עבור באפליקציות מסוג מרכז אפליקציות מפני שכל משימה חדשה מופיעה כפריט נפרד מסך סקירה כללית. למידע נוסף על משימות במסך הסקירה הכללית אפשר לקרוא לאחרונה מסך.

קיוסקים ציבוריים

המתכונים האלה מעולים למכשירים שאפשר להשתמש בהם במקומות ציבוריים, אבל הם יכולים גם עוזרים למשתמשים ייעודיים רבים להתמקד במשימות שלהם.

נעילת המכשיר

כדי לוודא שהמכשירים משמשים למטרה שלשמה נועדו, אפשר להוסיף הגבלות המשתמשים המפורטות בטבלה 1.

טבלה 1. הגבלות משתמשים במכשירי קיוסק
הגבלת משתמשים תיאור
DISALLOW_FACTORY_RESET מונע ממשתמש לאפס את המכשיר להגדרות ברירת המחדל של היצרן. אדמינים של מכשירים מנוהלים והמשתמשים הראשיים יכולים להגדיר את האפשרות הזו המוגבלות של המשאבים.
DISALLOW_SAFE_BOOT מונע ממשתמש במכשיר להפעיל את המכשיר מצב בטוח שבו המערכת לא תפעיל את האפליקציה באופן אוטומטי. אדמינים של כל במכשירים מנוהלים והמשתמש הראשי יכולים להגדיר את ההגבלה הזאת.
DISALLOW_MOUNT_PHYSICAL_MEDIA מונע ממשתמשי המכשיר לטעון נפחי אחסון שעשויים להיות זמינים מחוברים למכשיר. אדמינים של מכשירים מנוהלים והמשתמש הראשי יכולים להגדיר את ההגבלה הזו.
DISALLOW_ADJUST_VOLUME השתקת המכשיר ומניעת שינוי הצליל של המשתמש במכשיר הגדרות של עוצמת קול ורטט. בודקים שאין צורך באודיו במכשיר הקיוסק להפעלת מדיה או לתכונות נגישות. אדמינים של חשבונות מנוהלים המשתמשים הראשיים, המשתמשים הראשיים, המשתמשים המשניים ופרופילים של העבודה יכולים להגדיר את האפשרות הזו המוגבלות של המשאבים.
DISALLOW_ADD_USER מונע ממשתמשים חדשים להוסיף משתמשים במכשיר, כמו משתמשים משניים או למשתמשים מוגבלים. המערכת מוסיפה באופן אוטומטי את הגבלת המשתמש הזו במכשירים מנוהלים, אבל יכול להיות שהוא הוסר. אדמינים של כל במכשירים מנוהלים והמשתמש הראשי יכולים להגדיר את ההגבלה הזאת.

בקטע הקוד הבא מוסבר איך להגדיר את ההגבלות:

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);

מומלץ להסיר את ההגבלות האלה כשהאפליקציה במצב אדמין, שאדמין ב-IT עדיין יכול להשתמש בתכונות האלה לתחזוקת מכשירים. כדי לנקות ההגבלה, שיחה DevicePolicyManager.clearUserRestriction()

הסתרה של תיבות דו-שיח של שגיאות

בסביבות מסוימות, למשל הדגמות קמעונאות או מידע ציבורי יכול להיות שלא תרצו להציג למשתמשים תיבות דו-שיח של שגיאות. ב-Android 9.0 (API) ברמה 28) ומעלה, אפשר להסתיר תיבות דו-שיח של שגיאות מערכת במקרים של קריסות או אפליקציות שלא מגיבות על ידי הוספת משתמש ב-DISALLOW_SYSTEM_ERROR_DIALOGS המוגבלות של המשאבים. המערכת מפעילה מחדש אפליקציות שלא מגיבות, כאילו המשתמש במכשיר נסגר את האפליקציה בתיבת הדו-שיח. הדוגמה הבאה מראה איך לעשות זאת:

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);
}

אם אדמין של המשתמש הראשי או של המשתמש המשני הגדיר את ההגבלה הזאת, המערכת מסתיר תיבות דו-שיח של שגיאות רק למשתמש הזה. אם אדמין של חשבון מנוהל המכשיר מגדיר את ההגבלה הזו, והמערכת מבטלת את תיבות הדו-שיח לכל המשתמשים.

השארת המסך פועל

אם בונים קיוסק, אפשר לעצור מכשיר שעוברים אל שינה כשהאפליקציה מריצה את הפעילות שלה. הוסף דגל הפריסה FLAG_KEEP_SCREEN_ON חלון כמו שמוצג בדוגמה הבאה:

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);
}

כדאי לבדוק שהמכשיר מחובר ל-AC, ל-USB או לחשמל מטען. רישום לשידורי שינוי סוללה ושימוש ב-BatteryManager כדי לגלות את מצב הטעינה. אפשר אפילו לשלוח התראות מרחוק ל-IT אם המכשיר מנותק. לקבלת הוראות מפורטות, אפשר לקרוא את מעקב אחר רמת הטעינה של הסוללה והטעינה מדינה (State).

אפשר גם להגדיר את STAY_ON_WHILE_PLUGGED_IN הגדרה גלובלית שנועדה למנוע מהמכשיר להיכנס למצב שינה בזמן שהוא מחובר למקור חשמל. אדמינים של מכשירים מנוהלים, ב-Android 6.0 (רמת API 23) ואילך, יכולים התקשרות אל DevicePolicyManager.setGlobalSetting() כפי שמוצג בדוגמה הבאה:

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));

חבילות אפליקציה

הקטע הזה כולל מתכונים להתקנה יעילה של אפליקציות במכשירים ייעודיים.

חבילות אפליקציה לשמירה במטמון

אם המשתמשים במכשיר משותף חולקים קבוצה משותפת של אפליקציות, יכול להיות להימנע מהורדת אפליקציות ככל האפשר. כדי לייעל את השימוש ניהול הקצאות ידני במכשירים משותפים עם קבוצת משתמשים קבועה, כמו מכשירים עבור shift Worker, ב-Android 9.0 (רמת API 28) ואילך, ניתן לשמור אפליקציה במטמון חבילות (APK) שנחוצות לסשנים של משתמשים מרובים.

התקנת APK שנשמר במטמון (שכבר מותקן במכשיר) מתבצעת שני שלבים:

  1. רכיב הניהול של מכשיר מנוהל באופן מלא (או משתמש עם הרשאות גישה לחשבון) – למידע נוסף הבא) מגדיר את רשימת חבילות ה-APK שיש לשמור במכשיר.
  2. רכיבי אדמין של משתמשים משניים משויכים (או המשתמשים שקיבלו הרשאה) להתקין את ה-APK שנשמר במטמון בשם המשתמש. אדמינים של החשבון המנוהל במלואו במכשיר, המשתמש הראשי או פרופיל עבודה משויך (או בעלי גישה) יכולים גם להתקין את האפליקציה שנשמרה במטמון במקרה הצורך.

כדי להגדיר את רשימת חבילות ה-APK שיישמרו במכשיר, האדמין מתקשר DevicePolicyManager.setKeepUninstalledPackages() השיטה הזו לא בודקת שה-APK מותקן במכשיר – מועיל אם כשרוצים להתקין אפליקציה ממש לפני שהמשתמש צריך אותה. כדי לקבל רשימה של חבילות שכבר הוגדרו, אפשר להתקשר DevicePolicyManager.getKeepUninstalledPackages() אחרי קריאה אל setKeepUninstalledPackages() עם שינויים, או המשתמש נמחק, המערכת מוחקת את כל חבילות ה-APK שנשמרו במטמון שאינן נחוצות יותר.

כדי להתקין APK שנשמר במטמון, התקשר DevicePolicyManager.installExistingPackage() השיטה הזו יכולה להתקין רק אפליקציה שהמערכת כבר שמרה במטמון – על פתרון ייעודי למכשיר (או המשתמש במכשיר) להתקין קודם את האפליקציה במכשיר, לפני שאפשר לקרוא לשיטה הזו.

הדוגמה הבאה ממחישה איך אפשר להשתמש בקריאות האלה ל-API במנהל המערכת של מכשיר מנוהל ומשתמש משני:

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);

הענקת גישה לאפליקציות

אתם יכולים להעניק גישה לאפליקציה אחרת לניהול שמירת האפליקציות במטמון. תוכל לעשות זאת כדי להפריד את התכונות של הפתרון שלך או להציע למנהלי IT את היכולת להשתמש אפליקציות משלהם. האפליקציה שהענקתם לה גישה מקבלת את אותן הרשאות שיש לאדמין לרכיב הזה. לדוגמה, אדמין של משתמש משני יכול להתקשר אל האפליקציה installExistingPackage() אבל לא ניתן להתקשר אל setKeepUninstalledPackages().

כדי לתת למשתמש אחר גישה אליו DevicePolicyManager.setDelegatedScopes() וכוללות DELEGATION_KEEP_UNINSTALLED_PACKAGES בארגומנט 'היקפים'. הדוגמה הבאה מראה איך יוצרים אפליקציה נוספת בעל הגישה:

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 ...
}

אם הכול תקין, האפליקציה להענקת גישה מקבלת את ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED והופך אותו לנגיש. האפליקציה יכולה לקרוא לשיטות במדריך הזה כאילו היה הבעלים של המכשיר או הבעלים של הפרופיל. בשיחה DevicePolicyManager שיטות, בעל הגישה מעביר null בשביל האדמין של רכיב מסוים.

התקנה של חבילות אפליקציה

לפעמים כדאי להתקין אפליקציה מותאמת אישית שנשמרה באופן מקומי במטמון במכשיר. לדוגמה, מכשירים ייעודיים פרוסים לעיתים קרובות בסביבות או באזורים שמוגבלים ברוחב פס, בלי חיבור לאינטרנט. שלך בפתרון ייעודי למכשיר צריך להביא בחשבון את רוחב הפס של הלקוחות. שלך האפליקציה יכולה להתחיל בהתקנה של חבילת אפליקציה אחרת (APK) באמצעות PackageInstaller כיתות.

כל אפליקציה יכולה להתקין חבילות APK, אבל אדמינים במכשירים מנוהלים יכולים להתקין (או להסיר) חבילות ללא אינטראקציה של המשתמש. האדמין יכול לנהל המכשיר, משתמש משני משויך או פרופיל עבודה משויך. אחרי בסיום ההתקנה, המערכת תפרסם התראה שכל משתמשי המכשיר לראות. ההתראה מיידעת את המשתמשים במכשיר שהאפליקציה הותקנה (או עודכן) על ידי האדמין שלו.

טבלה 2. גרסאות Android שתומכות בהתקנת חבילות ללא אינטראקציה של המשתמש
גרסת Android רכיב אדמין להתקנה ולהסרה
Android 9.0 (רמת API 28) ואילך משתמשים משניים משויכים ופרופילים של עבודה – שניהם בחשבונות מנוהלים מכשירים
Android 6.0 (רמת API 23) ואילך מכשירים מנוהלים

אופן ההפצה של עותק אחד או יותר של ה-APK למכשירים ייעודיים יגרום תלויים במרחק בין המכשירים, ולפעמים גם המרחק ביניהם בין המכשירים הם ביחד. הפתרון צריך לפעול בהתאם לשיטות המומלצות בנושא אבטחה לפני שמתקינים חבילות APK במכשירים ייעודיים.

אפשר להשתמש ב-PackageInstaller.Session כדי ליצור סשן בתור חבילות APK או יותר להתקנה. בדוגמה הבאה אנחנו מקבלים סטטוס בפעילות שלנו (במצב singleTop), אבל אפשר להשתמש שירות או מקלט שידורים:

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);

בסשן נשלח משוב סטטוס לגבי ההתקנה באמצעות Intent. לבדיקה השדה EXTRA_STATUS של כל Intent כדי לקבל סטטוס. חשוב לזכור שהאדמינים לא מקבלים את עדכון הסטטוס של STATUS_PENDING_USER_ACTION כי המשתמש במכשיר לא צריך לאשר את ההתקנה.

כדי להסיר אפליקציות, אפשר להתקשר למספר PackageInstaller.uninstall. אדמינים של מכשירים מנוהלים, משתמשים ופרופילים של עבודה יכולים להסיר חבילות ללא אינטראקציה של המשתמש שפועלות בו גרסאות Android נתמכות (ראו טבלה 2).

הקפאת עדכוני המערכת

מכשירי Android מקבלים עדכוני OTA למערכת ולאפליקציה תוכנה. כדי להקפיא את גרסת מערכת ההפעלה על פני תקופות קריטיות, כמו חגים או בזמנים עמוסים אחרים, מכשירים ייעודיים יכולים להשעות עדכוני מערכת OTA למשך עד 90 ימים. מידע נוסף זמין במאמר בנושא ניהול עדכוני מערכת.

הגדרת תצורה מרחוק

ההגדרות המנוהלות של Android מאפשרות לאדמינים ב-IT להגדיר מרחוק את האפליקציה. יכול להיות שתרצו לחשוף הגדרות כמו רשימות היתרים, מארחי רשתות או כתובות URL של התוכן כדי שהאפליקציה תהיה שימושית יותר ל-IT ב-Google Workspace for Education.

אם האפליקציה חושפת את ההגדרות שלה, חשוב לכלול את ההגדרות התיעוד. למידע נוסף על חשיפת הגדרות האפליקציה והתגובה אליהן שינויים בהגדרות, קראו את המאמר הגדרת הגדרות מנוהלות.

הגדרת פיתוח

כשאתם מפתחים את הפתרון שלכם למכשירים ייעודיים, לפעמים שימושי אם רוצים להגדיר את האפליקציה כאדמין של מכשיר מנוהל ללא צורך במפעל לאתחל. כדי להגדיר את האדמין של מכשיר מנוהל, צריך לפעול לפי השלבים הבאים:

  1. יוצרים ומתקינים במכשיר את אפליקציית בקר מדיניות המכשיר (DPC).
  2. צריך לבדוק שאין חשבונות במכשיר.
  3. מריצים את הפקודה הבאה במעטפת Android Debug Bridge (adb). שלך צריך להחליף את com.example.dpc/.MyDeviceAdminReceiver בדוגמה עם השם של רכיב האדמין של האפליקציה:

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

כדי לעזור ללקוחות לפרוס את הפתרון שלך, עליך לבדוק מקורות מידע אחרים שיטות. אנחנו ממליצים על הרשמה באמצעות קוד QR למכשירים ייעודיים.

מקורות מידע נוספים

כדי לקבל מידע נוסף על מכשירים ייעודיים, כדאי לקרוא את המסמכים הבאים: