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