פרופילים של עבודה

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

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

סקירה כללית

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

כדי להתמודד עם המצב הזה, מערכת Android 5.0 (רמת API 21) מאפשרת לארגונים להגדיר פרופילים של עבודה. אם למכשיר יש פרופיל עבודה, ההגדרות נמצאות בשליטת האדמין ב-IT. אדמין ב-IT יכול לבחור אילו אפליקציות מורשות לפרופיל הזה, וגם שליטה בתכונות המכשיר שיהיו זמינות לפרופיל.

אם למכשיר יש פרופיל עבודה, יש השלכות על האפליקציות פועלות במכשיר, בלי קשר לפרופיל שבו האפליקציה פועלת:

  • כברירת מחדל, רוב הכוונות לא עוברות מפרופיל אחד לפרופיל אחר. אם אפליקציה שפועלת בפרופיל מפעילה Intent, אין handler של ה-Intent את הפרופיל הזה, ואסור ל-Intent לעבור אל הפרופיל האחר בגלל הגבלות הפרופיל, הבקשה תיכשל והאפליקציה עלולה להיסגר באופן בלתי צפוי.
  • האדמין ב-IT של הפרופיל יכול להגביל את אפליקציות המערכת שיהיו זמינות פרופיל העבודה. ההגבלה הזו גם עשויה לגרום לכך שאין handler עבור כמה כוונות נפוצות בפרופיל העבודה.
  • מאחר שלפרופיל האישי ולפרופיל העבודה יש אזורי אחסון נפרדים, ה-URI של הקובץ החוקי בפרופיל אחד לא חוקי בפרופיל אחר. כלשהו כוונה שהופעלה בפרופיל אחד עשויה להיות תטופל בפרופיל השני (בהתאם לפרופיל ), לכן לא בטוח לצרף מזהי URI של קבצים ל-Intents.

מניעת כוונות שנכשלו

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

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

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

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

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

שיתוף קבצים בין פרופילים

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

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

במקום זאת, צריך לשתף קבצים עם מזהי URI של תוכן. מזהי URI של תוכן לזהות את הקובץ באופן מאובטח יותר שניתן לשתף. ה-URI של התוכן מכיל את נתיב הקובץ, אבל גם את הרשות שמספקת את הקובץ ומספר המזהה לזיהוי הקובץ. אפשר ליצור מזהה תוכן לכל קובץ באמצעות FileProvider לאחר מכן תוכלו לשתף את התוכן הזה להזדהות עם אפליקציות אחרות (גם בפרופיל האחר). הנמען יכול להשתמש Content ID כדי לקבל גישה לקובץ עצמו.

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

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

כשקוראים ל-method getUriForFile(), צריך לכלול את הרשות של ספק הקובץ (בדוגמה הזו, "com.example.myapp.fileprovider"), שמצוין ב <provider> רכיב בקובץ המניפסט של האפליקציה. למידע נוסף על שיתוף קבצים עם מזהי URI של תוכן, ראו חלוקת הכנסות קבצים

האזנה להתראות

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

בפרופיל עבודה

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

בפרופיל אישי

כשהאפליקציה פועלת בפרופיל האישי, יכול להיות שלא יתקבלו התראות לאפליקציות שפועלות בפרופיל העבודה. כברירת מחדל, כל האפליקציות בפרופיל האישי לקבל קריאות חוזרות, אבל אדמין ב-IT יכול להוסיף לרשימת ההיתרים פרופיל אישי אחד או יותר שמאפשרות האזנה לשינויים בהתראות. לאחר מכן המערכת חוסמת אפליקציות שאינן ברשימת ההיתרים. ב-Android מגרסה 8.0 (רמת API 26) ואילך, מדיניות מכשיר בקר (DPC) שמנהל את פרופיל העבודה עלול לחסום את אפשרות ההאזנה לאפליקציה שלך להתראות של פרופיל העבודה באמצעות DevicePolicyManager אמצעי תשלום אחד setPermittedCrossProfileNotificationListeners(). האפליקציה שלך עדיין מקבלת התקשרות חזרה לגבי התראות המפורסמות בדף האישי פרופיל.

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

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

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

  • לציין אילו אפליקציות ברירת מחדל יהיו זמינות בתצוגה המנוהלת פרופיל
  • הגדרת הכוונות (Intent) שמורשות לעבור מפרופיל אחד אל השני

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

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

בדיקה בפרופילים של עבודה: טיפים וטריקים

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

  • כפי שצוין, כשטוענים אפליקציה ממקור לא ידוע במכשיר של פרופיל עבודה, שמותקנים בשני הפרופילים. אם רוצים, אפשר למחוק את האפליקציה מפרופיל אחד. ולהשאיר אותה בצד השני.
  • רוב הפקודות של מנהל הפעילות זמינות במעטפת Android Debug Bridge (adb) תומכים בדגל --user, שמאפשר לציין איזה משתמש להריץ בתור. כשמציינים משתמש, אפשר לבחור אם להריץ אותו כמשתמש הראשי הלא מנוהל או פרופיל העבודה. למידע נוסף, ראו ADB פקודות Shell.
  • כדי למצוא את המשתמשים הפעילים במכשיר, צריך להשתמש הפקודה list users. המספר הראשון במחרוזת הפלט הוא User ID, שאפשר להשתמש בו עם הדגל --user. לקבלת מידע נוסף מידע נוסף, ראו ADB Shell פקודות.

לדוגמה, כדי למצוא את המשתמשים במכשיר, מריצים את הפקודה הבאה:

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

במקרה הזה, למשתמש הראשי ("Drew") יש את מזהה המשתמש 0, פרופיל העבודה כולל את מזהה המשתמש 10. כדי להריץ אפליקציה בפרופיל העבודה, תשתמש בפקודה כזו:

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER