הגדרה של הגדרות מנוהלות

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

לדוגמה, ארגון עשוי לדרוש שאפליקציות שאושרו יאפשרו אדמין ב-IT:

  • אישור או חסימה של כתובות URL בדפדפן אינטרנט
  • ניתן לקבוע אם אפליקציה יכולה לסנכרן תוכן דרך רשת סלולרית או רק באמצעות Wi-Fi
  • קביעת הגדרות האימייל של האפליקציה

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

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

סקירה כללית על הגדרת תצורה מרחוק

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

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

כדי לספק הגדרות שמנוהלות באופן חיצוני:

  • צריך להצהיר על ההגדרות המנוהלות בקובץ המניפסט של האפליקציה. ביצוע ולכן מנהל ה-IT יכול לקרוא את באמצעות ממשקי API של Google Play.
  • בכל פעם שהאפליקציה ממשיכה, יש להשתמש באובייקט RestrictionsManager כדי לבדוק את והגדרות מנוהלות, ולשנות את ממשק המשתמש וההתנהגות של האפליקציה תואמים לתצורות האלה.
  • האזנה ל Intent מסוג ACTION_APPLICATION_RESTRICTIONS_CHANGED. כשמקבלים את ההודעה הזו שידור, אפשר לראות ב-RestrictionsManager הן ההגדרות המנוהלות הנוכחיות, ולבצע את השינויים הנדרשים ההתנהגות של האפליקציה.

הגדרה של הגדרות מנוהלות

האפליקציה יכולה לתמוך בכל הגדרה מנוהלת שברצונך להגדיר. את/ה מצהיר/ה את התצורות המנוהלות של האפליקציה בקובץ הגדרות מנוהלות, ולהצהיר את קובץ התצורות שבמניפסט. יצירת קובץ הגדרות מאפשרת כדי לבדוק את ההגדרות המנוהלות שהאפליקציה מספקת. שותפי EMM יכול לקרוא את תצורות האפליקציה באמצעות ממשקי API של Google Play.

כדי להגדיר את אפשרויות ההגדרה מרחוק של האפליקציה, צריך לשים את הרכיב הבא במניפסט רכיב <application>:

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

יוצרים קובץ בשם app_restrictions.xml באפליקציה הספרייה res/xml. המבנה של הקובץ מתואר ההפניה אל RestrictionsManager. לקובץ יש מאפיין רכיב <restrictions> אחד ברמה העליונה, שמכיל רכיב צאצא אחד מסוג <restriction> לכל הגדרה שיש באפליקציה.

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

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

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

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

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

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

הערה: באפליקציה בסביבת הייצור, android:title וגם יש לשלוף את android:description ממשאב שמותאם לשוק המקומי של Google, כפי שמתואר התאמה לשוק המקומי באמצעות משאבים

האפליקציה מגדירה הגבלות לשימוש בחבילות בתוך bundle_array. לדוגמה, אפליקציה עם כמה אפשרויות חיבור דרך VPN יכולה להגדיר כל שרת VPN הגדרה אישית במסגרת bundle, עם חבילות שמקובצות יחד במערך חבילות:

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

הסוגים הנתמכים של הרכיב android:restrictionType רשומות בטבלה 1 ומתועדות ב: ההפניה עבור RestrictionsManager וגם RestrictionEntry

טבלה 1. סוגי הכניסה להגבלות והשימוש בהן.

סוג android:restrictionType שימוש אופייני
TYPE_BOOLEAN "bool" ערך בוליאני: true או false.
TYPE_STRING "string" ערך מחרוזת, כמו שם.
TYPE_INTEGER "integer" מספר שלם עם ערך מ- MIN_VALUE עד MAX_VALUE.
TYPE_CHOICE "choice" ערך מחרוזת שנבחר מתוך android:entryValues, מוצגות בדרך כלל כרשימה של בחירה יחידה.
TYPE_MULTI_SELECT "multi-select" מערך מחרוזת עם ערכים שנבחרו מתוך android:entryValues. ניתן להשתמש באפשרות זו להצגת רשימה של בחירה מרובה שבה יש יותר מאישור אחד ניתן לבחור רשומה, למשל כדי לבחור כותרים ספציפיים להוספה לרשימת ההיתרים.
TYPE_NULL "hidden" סוג ההגבלה מוסתרת. הסוג הזה משמש לקבלת מידע צריך להעביר אותו הלאה, אבל לא להציג אותו המשתמש בממשק המשתמש. מאחסן ערך של מחרוזת יחידה.
TYPE_BUNDLE_ARRAY "bundle_array" משתמשים בו לאחסון מערכי הגבלות bundles התכונה זמינה ב-Android 6.0 (רמת API 23).

הערה: השדות android:entryValues קריאים למחשבים ולא ניתן לקרוא אותם מותאם לשוק המקומי. משתמשים ב-android:entries כדי להציג ערכים קריאים לאנשים שאפשר להתאים לשוק המקומי. לכל רשומה חייב להיות אינדקס תואם ב-android:entryValues.

בדיקת ההגדרות המנוהלות

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

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

כדי לקבל אובייקט RestrictionsManager, צריך לקבל את הערך הנוכחי פעילות עם getActivity(), ואז קוראים ל-method Activity.getSystemService() של הפעילות הזו:

Kotlin

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

Java

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

ברגע שיהיה לך RestrictionsManager, אתה יכול לקבל את להגדרות האישיות הנוכחיות באמצעות קריאה getApplicationRestrictions() method:

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

הערה: לנוחיותכם, אפשר גם לאחזר את הנתונים הנוכחיים הגדרות אישיות עם UserManager, באמצעות UserManager.getApplicationRestrictions() השיטה הזו פועלת בדיוק בדיוק כמו RestrictionsManager.getApplicationRestrictions().

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

קריאה והחלה של הגדרות מנוהלות

ה-method getApplicationRestrictions() מחזירה Bundle שמכיל צמד מפתח/ערך לכל הגדרה שהוגדרה. כל הערכים הם מסוג Boolean, int, String ו-String[]. אחרי שמשיגים הגדרות מנוהלות Bundle, אפשר לבדוק את ההגדרה הנוכחית הגדרות אישיות עם השיטות הסטנדרטיות של Bundle סוגי הנתונים האלה, כמו getBoolean() או getString()

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

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

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
}

כדי להחיל כמה הגבלות בתצוגת עץ: bundle_array רשומת הגבלה כאוסף של Parcelable אובייקטים ולהפעיל Cast של Bundle. בדוגמה הזו, ההגדרות של כל VPN הנתונים מנותחים ומשמשים ליצירת רשימה של אפשרויות החיבור לשרת:

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
}

האזנה לשינויים בהגדרות מנוהלות

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

הערה: ה-Intent ACTION_APPLICATION_RESTRICTIONS_CHANGED נשלח רק למאזינים שרשומות באופן דינמי, לא למאזינים שהוצהרו בקובץ המניפסט של האפליקציה.

הקוד הבא מראה איך לבצע רישום דינמי של מקלט שידורים הכוונה הזו:

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

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

שליחת משוב על ההגדרות האישיות המנוהלות ל-EMM

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

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

דוגמאות קוד נוספות

הגדרות ManagedConfiguration שממחישה גם את השימוש בממשקי ה-API שמפורטים בדף הזה.