כל אפליקציית Android פועלת בארגז חול עם גישה מוגבלת. אם האפליקציה שלכם צריכה להשתמש במשאבים או במידע מחוץ לארגז החול שלה, תוכלו להצהיר על הרשאה בסביבת זמן הריצה ולהגדיר בקשת הרשאה שמספקת את הגישה הזו. השלבים האלה הם חלק מתהליך העבודה לשימוש בהרשאות.
אם אתם מגדירים הרשאות מסוכנות, ואם האפליקציה שלכם מותקנת במכשיר עם Android בגרסה 6.0 ומעלה (רמת API 23), עליכם לבקש את ההרשאות המסוכנות בזמן הריצה לפי השלבים שמפורטים במדריך הזה.
אם לא תצהירו על הרשאות מסוכנות, או אם האפליקציה מותקנת במכשיר עם Android 5.1 (רמת API 22) ואילך, ההרשאות יינתנו באופן אוטומטי ולא תצטרכו להשלים אף אחד מהשלבים הנותרים בדף הזה.
עקרונות בסיסיים
אלה העקרונות הבסיסיים לבקשת הרשאות בזמן ריצה:
- כדאי לבקש הרשאה בהקשר, כשהמשתמש מתחיל לבצע פעולה שדורשת את ההרשאה.
- לא לחסום את המשתמש. תמיד צריך לספק אפשרות לבטל תהליך UI חינוכי, למשל תהליך שמסביר את הסיבה לבקשת ההרשאות.
- אם המשתמש דוחה או מבטל הרשאה שנדרשת לתכונה מסוימת, צריך לשדרג לאחור את האפליקציה בצורה חלקה כדי שהמשתמש יוכל להמשיך להשתמש בה. למשל, אפשר להשבית את התכונה שנדרשת להרשאה.
- אל תניח שום התנהגות של המערכת. לדוגמה, אל תניחו שההרשאות מופיעות באותה קבוצת הרשאות. קבוצת הרשאות עוזרת למערכת לצמצם את מספר תיבת הדו-שיח של המערכת שמוצגות למשתמש כשאפליקציה מבקשת הרשאות שקשורות זו לזו.
תהליך העבודה לבקשת הרשאות
לפני שמצהירים על הרשאות בסביבת זמן הריצה ומבקשים אותן באפליקציה, צריך להעריך אם האפליקציה צריכה לעשות זאת. אפשר למלא תרחישי שימוש רבים באפליקציה, כמו צילום תמונות, השהיה של הפעלת מדיה והצגת מודעות רלוונטיות, בלי להצהיר על הרשאות.
אם הגעתם למסקנה שהאפליקציה שלכם צריכה להצהיר על הרשאות זמן ריצה ולבקש אותן, עליכם לבצע את השלבים הבאים:
- בקובץ המניפסט של האפליקציה, מגדירים את ההרשאות שהאפליקציה עשויה להזדקק להן.
- כדאי לתכנן את חוויית המשתמש של האפליקציה כך שפעולות ספציפיות באפליקציה ישויכו להרשאות ספציפיות בסביבת זמן הריצה. עליכם להודיע למשתמשים אילו פעולות עשויות לחייב אותם להעניק לאפליקציה הרשאת גישה לנתונים הפרטיים שלהם.
- מתיינים שהמשתמש יפעיל את המשימה או הפעולה באפליקציה שדורשות גישה לנתונים פרטיים ספציפיים של משתמשים. אחרי זה, האפליקציה יכולה לבקש את ההרשאה הדרושה בתחילת ההפעלה כדי לגשת לנתונים האלה.
בודקים אם המשתמש כבר העניק את הרשאת זמן הריצה שנדרשת לאפליקציה. אם כן, לאפליקציה תהיה גישה לנתוני המשתמש הפרטיים. אם לא, ממשיכים לשלב הבא.
בכל פעם שמבצעים פעולה שדורשת את ההרשאה הזו, צריך לבדוק אם יש לכם הרשאה.
בודקים אם צריך להציג למשתמשים באפליקציה הסבר על הסיבה לכך שהם צריכים להעניק לה הרשאה מסוימת בזמן ריצה. אם המערכת קובעת שלא צריך להציג הסבר באפליקציה, ממשיכים ישירות לשלב הבא בלי להציג רכיב ממשק משתמש.
עם זאת, אם המערכת תקבע שהאפליקציה צריכה להציג נימוק, תוכלו להציג את הנימוק למשתמש ברכיב בממשק המשתמש. בהסבר הזה, צריך להסביר בבירור לאילו נתונים האפליקציה מנסה לגשת ואילו יתרונות האפליקציה יכולה לספק למשתמש אם הוא יעניק לה הרשאה בזמן ריצה. אחרי שהמשתמש יאשר את הנימוקים, ממשיכים לשלב הבא.
מבקשים את ההרשאה בתחילת ההפעלה שנדרשת לאפליקציה כדי לגשת לנתוני המשתמש הפרטיים. המערכת תציג בקשה להרשאה בסביבת זמן הריצה, כמו זו שמוצגת בדף הסקירה הכללית של ההרשאות.
בודקים את התשובה של המשתמש – אם הוא בחר להעניק או לדחות את הרשאת זמן הריצה.
אם המשתמש העניק לאפליקציה הרשאה, תוכלו לגשת לנתוני המשתמש הפרטיים. אם המשתמש דחה את ההרשאה, הורידו את רמת חוויית השימוש באפליקציה כך שהיא תספק למשתמש את הפונקציונליות הנדרשת, בלי המידע שמוגן על ידי ההרשאה הזו.
איור 1 ממחיש את תהליך העבודה ואת קבוצת ההחלטות שמשויכות לתהליך הזה:
איך בודקים אם האפליקציה כבר קיבלה את ההרשאה
כדי לבדוק אם המשתמש כבר העניק לאפליקציה הרשאה מסוימת, מעבירים את ההרשאה הזו ל-method ContextCompat.checkSelfPermission()
. השיטה הזו מחזירה את הערך PERMISSION_GRANTED
או את הערך PERMISSION_DENIED
, בהתאם לכך שיש לאפליקציה את ההרשאה או לא.
צריך להסביר למה לאפליקציה שלך נדרשת הרשאה
בתיבת הדו-שיח של ההרשאות שמוצגת על ידי המערכת כשקוראים ל-requestPermissions()
מצוין מהי ההרשאה שהאפליקציה מבקשת, אבל לא מצוין למה. במקרים מסוימים, המשתמש עשוי למצוא את זה תמוה. כדאי להסביר למשתמשים למה
האפליקציה מבקשת את ההרשאות לפני שמתקשרים אל
requestPermissions()
.
מחקרים מראים שמשתמשים הרבה יותר מרגישים בנוח עם בקשות להרשאות אם הם יודעים למה האפליקציה צריכה אותן, למשל אם ההרשאה נדרשת כדי לתמוך בתכונה עיקרית באפליקציה או לצורכי פרסום. לכן, אם אתם משתמשים רק בחלק מהקריאות ל-API שנכללות בקבוצת הרשאות מסוימת, כדאי לציין במפורש באילו מההרשאות האלה אתם משתמשים ומדוע. לדוגמה, אם אתם משתמשים רק במיקום משוער, עליכם להודיע על כך למשתמש בתיאור האפליקציה או במאמרי העזרה לגבי האפליקציה.
בתנאים מסוימים, מומלץ גם להודיע למשתמשים על גישה למידע רגיש בזמן אמת. לדוגמה, אם אתם ניגשים למצלמה או למיקרופון, מומלץ להודיע על כך למשתמש באמצעות סמל התראה באפליקציה או בסרגל ההתראות (אם האפליקציה פועלת ברקע), כדי שלא ייראה שאתם אוספים נתונים בחשאי.
בסופו של דבר, אם אתם צריכים לבקש הרשאה כדי שחלק מהתכונות באפליקציה יפעלו, אבל הסיבה לא ברורה למשתמש, עליכם למצוא דרך להסביר למשתמש למה אתם צריכים את ההרשאות הרגישות ביותר.
אם השיטה ContextCompat.checkSelfPermission()
מחזירה את הערך PERMISSION_DENIED
, צריך לבצע קריאה ל-shouldShowRequestPermissionRationale()
.
אם השיטה הזו מחזירה את הערך true
, מציגים למשתמש ממשק משתמש חינוכי. בממשק המשתמש הזה, מתארים למה נדרשת הרשאה מסוימת כדי להפעיל את התכונה שהמשתמש רוצה להפעיל.
בנוסף, אם האפליקציה מבקשת הרשאה שקשורה למיקום, למיקרופון או למצלמה, אפשר להסביר למה האפליקציה צריכה גישה למידע הזה.
בקשת הרשאות
אחרי שהמשתמש צופה בממשק משתמש חינוכי, או אם הערך המוחזר של shouldShowRequestPermissionRationale()
מציין שאין צורך להציג ממשק משתמש חינוכי, מבקשים את ההרשאה. המשתמשים רואים תיבת דו-שיח עם הרשאת מערכת, שבה הם יכולים לבחור אם להעניק הרשאה מסוימת לאפליקציה.
כדי לעשות זאת, משתמשים בחוזה RequestPermission
, שמופיע בספריית AndroidX, שבו מאפשרים למערכת לנהל את קוד הבקשה להרשאה בשבילכם. השימוש בחוזה RequestPermission
מפשט את הלוגיקה, ולכן זהו הפתרון המומלץ כשהדבר אפשרי. עם זאת, במקרה הצורך, תוכלו גם לנהל קוד בקשה בעצמכם כחלק מבקשת ההרשאה, ולכלול את קוד הבקשה הזה בלוגיקת הקריאה החוזרת של ההרשאה.
מתן הרשאה למערכת לנהל את קוד הבקשה להרשאה
כדי לאפשר למערכת לנהל את קוד הבקשה שמשויך לבקשת ההרשאות, מוסיפים יחסי תלות בספריות הבאות בקובץ build.gradle
של המודול:
androidx.activity
, גרסה 1.2.0 ואילךandroidx.fragment
, גרסה 1.3.0 ואילך
לאחר מכן תוכלו להשתמש באחת מהכיתות הבאות:
- כדי לבקש הרשאה אחת, משתמשים ב-
RequestPermission
. - כדי לבקש כמה הרשאות בו-זמנית, משתמשים ב-
RequestMultiplePermissions
.
בשלבים הבאים מוסבר איך להשתמש בחוזה RequestPermission
. התהליך כמעט זהה בחוזה RequestMultiplePermissions
.
בלוגיקה של האיניציאליזציה של הפעילות או של הפלח, מעבירים הטמעה של
ActivityResultCallback
לקריאה ל-registerForActivityResult()
. הערך שלActivityResultCallback
מגדיר איך האפליקציה מטפלת בתשובה של המשתמש לבקשת ההרשאה.שומרים הפניה לערך המוחזר של
registerForActivityResult()
, שהוא מסוגActivityResultLauncher
.כדי להציג את תיבת הדו-שיח של הרשאות המערכת במקרה הצורך, צריך להפעיל את השיטה
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 להרשאות.
הרשאות חד-פעמיות
החל מגרסה 11 של Android (רמת API 30), בכל פעם שהאפליקציה מבקשת הרשאה שקשורה למיקום, למיקרופון או למצלמה, תיבת הדו-שיח של ההרשאות שמוצגת למשתמש מכילה את האפשרות רק הפעם, כפי שמוצג באיור 2. אם המשתמש בוחר באפשרות הזו בתיבת הדו-שיח, האפליקציה מקבלת הרשאה חד-פעמית זמנית.
לאחר מכן, האפליקציה תהיה מסוגלת לגשת לנתונים הקשורים למשך פרק זמן שנקבע בהתאם להתנהגות האפליקציה ולפעולות של המשתמש:
- כשהפעילות של האפליקציה גלויה, האפליקציה יכולה לגשת לנתונים.
- אם המשתמש שולח את האפליקציה לרקע, האפליקציה יכולה להמשיך לגשת לנתונים למשך פרק זמן קצר.
- אם תפעילו שירות בחזית בזמן שהפעילות גלויה, ואז המשתמש יעביר את האפליקציה לרקע, האפליקציה תוכל להמשיך לגשת לנתונים עד שהשירות בחזית ייפסק.
תהליך האפליקציה מסתיים כשההרשאה מבוטלת
אם המשתמש יבטל את ההרשאה החד-פעמית, למשל בהגדרות המערכת, לאפליקציה לא תהיה גישה לנתונים, גם אם השקתם שירות בחזית. כמו בכל הרשאה, אם המשתמש מבטל את ההרשאה החד-פעמית של האפליקציה, התהליך של האפליקציה מסתיים.
בפעם הבאה שהמשתמש יפתח את האפליקציה ותכונה באפליקציה תבקש גישה למיקום, למיקרופון או למצלמה, המשתמש יתבקש לתת את ההרשאה שוב.
איפוס הרשאות שלא בשימוש
ב-Android יש כמה דרכים לאפס הרשאות זמן ריצה שלא בשימוש למצב ברירת המחדל שלהן, 'נדחתה':
- ממשק API שבו אפשר להסיר באופן יזום את הגישה של האפליקציה להרשאה בסביבת זמן ריצה שלא בשימוש.
- מנגנון מערכת שמאפס באופן אוטומטי את ההרשאות של אפליקציות שלא בשימוש.
הסרת הגישה של האפליקציה
ב-Android 13 ואילך (רמת API 33 ואילך), אפשר להסיר מהאפליקציה את הגישה להרשאות בסביבת זמן הריצה שהאפליקציה כבר לא זקוקה להן. כשמעדכנים את האפליקציה, כדאי לבצע את השלב הזה כדי להגדיל את הסיכוי שהמשתמשים יבינו למה האפליקציה ממשיכה לבקש הרשאות ספציפיות. הידע הזה עוזר לבנות אמון בקרב המשתמשים באפליקציה.
כדי להסיר את הגישה להרשאה בסביבת זמן הריצה, מעבירים את שם ההרשאה ל-revokeSelfPermissionOnKill()
.
כדי להסיר גישה לקבוצה של הרשאות בסביבת זמן ריצה בו-זמנית, מעבירים אוסף של שמות הרשאות אל revokeSelfPermissionsOnKill()
.
תהליך הסרת ההרשאות מתבצע באופן אסינכררוני ומפסיק את כל התהליכים המשויכים למזהה ה-UID של האפליקציה.
כדי שהמערכת תוכל להסיר את הגישה של האפליקציה להרשאות, צריך להפסיק את כל התהליכים שקשורים לאפליקציה. כשאתם קוראים ל-API, המערכת קובעת מתי בטוח להפסיק את התהליכים האלה. בדרך כלל, המערכת ממתינה עד שהאפליקציה תפעל במשך פרק זמן ארוך ברקע במקום בחזית.
כדי להודיע למשתמש שלא נדרשת לאפליקציה יותר גישה להרשאות ספציפיות בזמן ריצה, אפשר להציג תיבת דו-שיח בפעם הבאה שהמשתמש יפעיל את האפליקציה. תיבת הדו-שיח הזו יכולה לכלול את רשימת ההרשאות.
איפוס אוטומטי של הרשאות לאפליקציות שלא בשימוש
אם האפליקציה מטרגטת את Android 11 (רמת API 30) ואילך ולא משתמשים בה במשך מספר חודשים, המערכת מגינה על נתוני המשתמשים באמצעות איפוס אוטומטי של הרשאות זמן הריצה הרגישות שהמשתמש העניק לאפליקציה. מידע נוסף זמין במדריך על מצב תנומה של אפליקציה.
אם צריך, מבקשים להפוך ל-handler שמוגדר כברירת מחדל
אפליקציות מסוימות תלויות בגישה למידע רגיש של משתמשים שקשור ליומני שיחות ולהודעות SMS. אם אתם רוצים לבקש את ההרשאות הספציפיות ליומני שיחות ולהודעות SMS ולפרסם את האפליקציה בחנות Play, עליכם לבקש מהמשתמש להגדיר את האפליקציה כ-handler ברירת המחדל לפונקציית ליבה של המערכת לפני שתבקשו את ההרשאות בתחילת ההפעלה.
למידע נוסף על בוררי ברירת מחדל, כולל הנחיות להצגת הנחיה של בורר ברירת מחדל למשתמשים, עיינו במדריך בנושא הרשאות שנעשה בהן שימוש רק בבוררי ברירת מחדל.
מתן כל ההרשאות בסביבת זמן הריצה למטרות בדיקה
כדי להעניק באופן אוטומטי את כל ההרשאות בסביבת זמן הריצה כשמתקינים אפליקציה באמולטור או במכשיר בדיקה, משתמשים באפשרות -g
בפקודה adb shell install
, כפי שמתואר בקטע הקוד הבא:
adb shell install -g PATH_TO_APK_FILE
מקורות מידע נוספים
מידע נוסף על הרשאות זמין במאמרים הבאים:
למידע נוסף על בקשות להרשאות, אפשר לעיין בדוגמאות להרשאות
אפשר גם להשלים את ה-codelab הזה שמראה שיטות מומלצות לשמירה על פרטיות.