בקשת הרשאות בזמן ריצה

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

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

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

עקרונות בסיסיים

אלה העקרונות הבסיסיים לבקשת הרשאות בזמן ריצה:

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

תהליך העבודה לבקשת הרשאות

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

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

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

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

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

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

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

  7. בודקים את התשובה של המשתמש – אם הוא בחר להעניק או לדחות את ההרשאה בסביבת זמן הריצה.

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

איור 1 ממחיש את תהליך העבודה ואת קבוצת ההחלטות שמשויכות לתהליך הזה:

איור 1. דיאגרמה שמראה את תהליך העבודה להצהרה על הרשאות בסביבת זמן ריצה ובקשת הרשאות כאלה ב-Android.

איך בודקים אם האפליקציה כבר קיבלה את ההרשאה

כדי לבדוק אם המשתמש כבר העניק לאפליקציה הרשאה מסוימת, מעבירים את ההרשאה הזו ל-method‏ ContextCompat.checkSelfPermission(). השיטה הזו מחזירה את הערך PERMISSION_GRANTED או את הערך PERMISSION_DENIED, בהתאם לכך שיש לאפליקציה את ההרשאה או לא.

הסבר למה לאפליקציה שלך נדרשת ההרשאה

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

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

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

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

אם השיטה ContextCompat.checkSelfPermission() מחזירה את הערך PERMISSION_DENIED, צריך לבצע קריאה ל-shouldShowRequestPermissionRationale(). אם השיטה הזו מחזירה את הערך true, מציגים למשתמש ממשק משתמש חינוכי. בממשק המשתמש הזה, מתארים למה נדרשת הרשאה מסוימת כדי להפעיל את התכונה שהמשתמש רוצה להפעיל.

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

בקשת הרשאות

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

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

מתן הרשאה למערכת לנהל את קוד הבקשה להרשאה

כדי לאפשר למערכת לנהל את קוד הבקשה שמשויך לבקשת ההרשאות, מוסיפים יחסי תלות בספריות הבאות בקובץ build.gradle של המודול:

לאחר מכן תוכלו להשתמש באחת מהכיתות הבאות:

בשלבים הבאים מוסבר איך להשתמש בחוזה RequestPermission. התהליך כמעט זהה בחוזה RequestMultiplePermissions.

  1. בלוגיקה של האיניציאליזציה של הפעילות או של הפלח, מעבירים הטמעה של ActivityResultCallback לקריאה ל-registerForActivityResult(). הערך של ActivityResultCallback מגדיר איך האפליקציה מטפלת בתשובה של המשתמש לבקשת ההרשאה.

    שומרים הפניה לערך המוחזר של registerForActivityResult(), שהוא מסוג ActivityResultLauncher.

  2. כדי להציג את תיבת הדו-שיח של הרשאות המערכת במקרה הצורך, צריך להפעיל את השיטה launch() במכונה של ActivityResultLauncher ששמרתם בשלב הקודם.

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

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

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

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

Kotlin

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // feature requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    }

Java

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // feature requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    });

קטע הקוד הזה מדגים את התהליך המומלץ לבדיקה של הרשאה ולבקשת הרשאה מהמשתמש במקרה הצורך:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

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

במקום לאפשר למערכת לנהל את קוד הבקשה להרשאה, אפשר לנהל את קוד הבקשה להרשאה בעצמכם. כדי לעשות זאת, צריך לכלול את קוד הבקשה בקריאה ל-requestPermissions().

קטע הקוד הבא מראה איך לבקש הרשאה באמצעות קוד בקשה:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

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

Kotlin

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return
        }

        // Add other 'when' lines to check for other
        // permissions this app might request.
        else -> {
            // Ignore all other requests.
        }
    }
}

Java

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

שליחת בקשה להרשאות מיקום

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

מיקום בחזית

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

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

המערכת מתייחסת לאפליקציה כאל אפליקציה שמשתמשת במיקום בחזית אם תכונה באפליקציה ניגשת למיקום הנוכחי של המכשיר באחת מהסיטואציות הבאות:

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

    ב-Android 10 (רמת API‏ 29) ואילך, צריך להצהיר על סוג של שירות שפועל בחזית מסוג location, כפי שמתואר בקטע הקוד הבא. בגרסאות קודמות של Android, מומלץ להצהיר על סוג השירות הזה שפועל בחזית.

    <!-- Recommended for Android 9 (API level 28) and lower. -->
    <!-- Required for Android 10 (API level 29) and higher. -->
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        <!-- Any inner elements go here. -->
    </service>

מכריזים על צורך במיקום בחזית כאשר האפליקציה מבקשת את ההרשאה ACCESS_COARSE_LOCATION או את ההרשאה ACCESS_FINE_LOCATION, כפי שמוצג בקטע הקוד הבא:

<manifest ... >
  <!-- Include this permission any time your app needs location information. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

מיקום ברקע

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

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

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

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

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

טיפול בדחייה של הרשאה

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

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

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

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

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

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

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

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

בדיקת סטטוס הדחייה במהלך בדיקה וניפוי באגים

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

adb shell dumpsys package PACKAGE_NAME

כאשר PACKAGE_NAME הוא שם החבילה שרוצים לבדוק.

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

...
runtime permissions:
  android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET|USER_FIXED|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.BLUETOOTH_CONNECT: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
...

הרשאות שנדחו פעם אחת על ידי המשתמש מסומנות ב-USER_SET. הרשאות שנדחו באופן סופי על ידי בחירה באפשרות דחייה פעמיים מסומנות ב-USER_FIXED.

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

adb shell pm clear-permission-flags PACKAGE_NAME PERMISSION_NAME user-set user-fixed

PERMISSION_NAME הוא שם ההרשאה שרוצים לאפס.

כדי לראות רשימה מלאה של הרשאות לאפליקציות ל-Android, אפשר לעיין בדף ההפניה של ה-API להרשאות.

הרשאות חד-פעמיות

האפשרות &#39;רק הפעם&#39; היא הלחצן השני מתוך שלושה לחצנים בתיבת הדו-שיח.
איור 2. תיבת דו-שיח של מערכת שמופיעה כשאפליקציה מבקשת הרשאה חד-פעמית.

החל מגרסה 11 של Android‏ (רמת API 30), בכל פעם שהאפליקציה מבקשת הרשאה שקשורה למיקום, למיקרופון או למצלמה, תיבת הדו-שיח של ההרשאות שמוצגת למשתמש מכילה את האפשרות רק הפעם, כפי שמוצג באיור 2. אם המשתמש יבחר באפשרות הזו בתיבת הדו-שיח, לאפליקציה תוענק הרשאה חד-פעמית זמנית.

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

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

תהליך האפליקציה מסתיים כשההרשאה מבוטלת

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

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

איפוס הרשאות שלא בשימוש

ב-Android יש כמה דרכים לאפס הרשאות זמן ריצה שלא בשימוש למצב ברירת המחדל שלהן, 'נדחתה':

הסרת הגישה של האפליקציה

ב-Android 13 ואילך (רמת API 33 ואילך), אפשר להסיר מהאפליקציה את הגישה להרשאות בסביבת זמן הריצה שהאפליקציה כבר לא זקוקה להן. כשמעדכנים את האפליקציה, כדאי לבצע את השלב הזה כדי להגדיל את הסיכוי שהמשתמשים יבינו למה האפליקציה ממשיכה לבקש הרשאות ספציפיות. הידע הזה עוזר לכם לבנות את האמון של המשתמשים באפליקציה.

כדי להסיר את הגישה להרשאה בסביבת זמן הריצה, מעבירים את שם ההרשאה ל-revokeSelfPermissionOnKill(). כדי להסיר גישה לקבוצה של הרשאות בסביבת זמן ריצה בו-זמנית, מעבירים אוסף של שמות הרשאות אל revokeSelfPermissionsOnKill(). תהליך הסרת ההרשאות מתבצע באופן אסינכררוני ומפסיק את כל התהליכים המשויכים למזהה ה-UID של האפליקציה.

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

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

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

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

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

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

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

מתן כל ההרשאות בסביבת זמן הריצה למטרות בדיקה

כדי להעניק באופן אוטומטי את כל ההרשאות בסביבת זמן הריצה כשמתקינים אפליקציה באמולטור או במכשיר בדיקה, משתמשים באפשרות -g בפקודה adb shell install, כפי שמתואר בקטע הקוד הבא:

adb shell install -g PATH_TO_APK_FILE

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

מידע נוסף על הרשאות זמין במאמרים הבאים:

מידע נוסף על בקשות להרשאות זמין בדוגמאות להרשאות

אפשר גם להשלים את ה-codelab הזה שמראה שיטות מומלצות לשמירה על פרטיות.