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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

כדי לבדוק אם המשתמש כבר העניק לאפליקציה שלכם הרשאה מסוימת, מעבירים את ההרשאה הזו לשיטה 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, אפשר לעיין בדף ההפניה של Permissions API.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

adb shell install -g PATH_TO_APK_FILE

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

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

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

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