Intent
הוא אובייקט להעברת הודעות שאפשר להשתמש בו כדי לבקש פעולה
מרכיב אפליקציה אחר.
על אף שכוונות מסייעות לתקשורת בין רכיבים במספר דרכים, יש
תרחישים בסיסיים לדוגמה:
- התחלת פעילות
Activity
מייצג מסך יחיד באפליקציה. אפשר להתחיל שיחה חדשה שלActivity
על ידי העברת הערךIntent
אלstartActivity()
.Intent
מתאר את הפעילות שמתחילה ומעביר את כל הנתונים הנחוצים.אם רוצים לקבל תוצאה מהפעילות כשהיא מסתיימת, קוראים לפונקציה
startActivityForResult()
. הפעילות מקבלת את התוצאה כאובייקטIntent
נפרד בקריאה החוזרת (callback) של הפעילות שלך ב-onActivityResult()
. מידע נוסף זמין במדריך הפעילויות. - הפעלת שירות
Service
הוא רכיב שמבצע פעולות ברקע ללא ממשק משתמש. ב-Android 5.0 (רמת API 21) ואילך, אפשר להפעיל שירות עםJobScheduler
. אפשר לקבל מידע נוסף מידע עלJobScheduler
, ראהAPI-reference documentation
.בגרסאות שקודמות ל-Android 5.0 (רמת API 21), אפשר להפעיל שירות באמצעות שיטות למחלקה
Service
. יש לך אפשרות להפעיל שירות לביצוע פעולה חד-פעמית (למשל, הורדת קובץ) על ידי העברת קובץIntent
אלstartService()
.Intent
מתאר את השירות שצריך להפעיל ומעביר את כל הנתונים הנחוצים.אם השירות מיועד באמצעות ממשק לקוח לשרת, אפשר לקשר לשירות מרכיב אחר על ידי העברת
Intent
אלbindService()
. מידע נוסף זמין במדריך שירותים. - העברת שידור
שידור הוא הודעה שכל אפליקציה יכולה לקבל. המערכת מספקת מגוון שידורים עבור אירועי מערכת, למשל כאשר המערכת באתחול או כשהמכשיר מתחיל להיטען. אפשר להעביר שידור לאפליקציות אחרות על ידי העברת
Intent
אלsendBroadcast()
אוsendOrderedBroadcast()
.
בהמשך הדף הזה מוסבר איך פועלות הכוונות ואיך להשתמש בהן. מידע קשור זמין במאמר אינטראקציה עם אפליקציות אחרות ושיתוף תוכן.
סוגי Intent
יש שני סוגים של כוונות:
- כוונות מפורשות מציין איזה רכיב של האפליקציה יענה על הכוונה, על ידי ציון
ComponentName
מלא. אפשר משתמשים בדרך כלל בכוונה מפורשת להפעיל רכיב שלכם, כי אתם יודעים את שם הכיתה של הפעילות או השירות שאתם רוצים להתחיל. עבור לדוגמה, אפשר להתחיל פעילות חדשה באפליקציה בתגובה לפעולת משתמש, או להתחיל פעילות שירות להורדת קובץ ברקע. - אובייקטים מרומזים של Intent לא מציינים שם של רכיב ספציפי, אלא מצהירים על פעולה כללית. לביצועים, שמאפשר לרכיב מאפליקציה אחרת לטפל בו. לדוגמה, אם רוצים להציג למשתמש מיקום במפה, ניתן להשתמש מתוך כוונה מרומזת כדי לבקש שמשתמש אחר יוכל האפליקציה מציגה מיקום ספציפי במפה.
איור 1 מראה איך המערכת משתמשת בכוונה כשמתחילים פעילות. כאשר
Intent
מציין שם של רכיב פעילות ספציפי באופן מפורש, המערכת
רכיב זה מפעיל מיד את הרכיב.
![](https://developer.android.com/static/images/components/intent-filters_2x.png?authuser=4&hl=he)
איור 1. איך הכוונה מרומזת
שהועברו דרך המערכת כדי להתחיל פעילות נוספת: [1] פעילות א' יוצרת פעילות
Intent
עם תיאור פעולה ומעביר אותו אל startActivity()
. [2] מערכת Android מחפשת הכול
אפליקציות למסנן Intent שתואם ל-Intent. כשנמצאת התאמה, [3] המערכת
מתחילה את פעילות ההתאמה (פעילות ב') על ידי הפעלת השיטה onCreate()
שלה והעברת הערך Intent
.
כשמשתמשים באובייקט Intent מרומז, מערכת Android מוצאת את הרכיב המתאים שצריך להפעיל
על ידי השוואת התוכן של ה-Intent למסנני כוונת הרכישה שמוצהרים בקובץ המניפסט של אפליקציות אחרות ב
במכשיר. אם ה-Intent תואם למסנן Intent, המערכת מפעילה את הרכיב הזה ומספקת אותו
את האובייקט Intent
. אם יש כמה מסנני Intent תואמים, המערכת
מציג תיבת דו-שיח שבה המשתמש יכול לבחור באיזו אפליקציה להשתמש.
מסנן Intent הוא ביטוי בקובץ המניפסט של האפליקציה. מציין את סוג ה-Intent שהרכיב שרוצים לקבל. לדוגמה, אם אתם מצהירים על מסנן Intent לפעילות מסוימת, כך יש אפשרות לאפליקציות אחרות להתחיל את הפעילות ישירות עם כוונה מסוימת. באופן דומה, אם לא הצהרתם על מסנני Intent בפעילות מסוימת, תוכלו להפעיל את התכונה הזו. רק מתוך כוונה מפורשת.
זהירות: כדי לוודא שהאפליקציה מאובטחת, תמיד
להשתמש
כשמתחילים ב-Service
ולא
להצהיר על מסנני Intent עבור השירותים שלך שימוש מתוך כוונה מרומזת להפעלת שירות הוא
מכיוון שלא ניתן להיות בטוחים איזה שירות יגיב לכוונה,
והמשתמש לא יכול לראות איזה שירות מתחיל. החל מ-Android 5.0 (רמת API 21), המערכת
מקפיצה הודעת שגיאה (throw) לחריגה אם מתקשרים ל-bindService()
מתוך כוונה מרומזת.
בניית כוונה
אובייקט Intent
נושא מידע שמערכת Android משתמשת בו
כדי לקבוע איזה רכיב להפעיל (למשל: השם או הרכיב המדויק של הרכיב)
הקטגוריה שבה צריך לקבל את הכוונה), וגם מידע שבו רכיב הנמען משתמש
כדי לבצע את הפעולה בצורה תקינה (למשל: הפעולה שצריך לבצע והנתונים שצריך לפעול לפיהם).
המידע העיקרי שנכלל ב-Intent
הוא:
- שם הרכיב
- שם הרכיב שצריך להתחיל.
זה מידע אופציונלי, אבל זה המידע הקריטי שיוצר את הכוונה explicit – כלומר, הכוונה צריכה להישלח רק לרכיב האפליקציה מוגדר על ידי שם הרכיב. בלי שם רכיב, הכוונה היא מרומזת המערכת מחליטה איזה רכיב יקבל את הכוונה על סמך הפרטים האחרים של Intent (כמו הפעולה, הנתונים והקטגוריה, כפי שמתואר בהמשך). אם אתם צריכים להפעיל של הרכיב באפליקציה שלכם, עליכם לציין את שם הרכיב.
הערה: כשמתחילים ב-
Service
, יש לציין תמיד את שם הרכיב. אחרת, לא ניתן לדעת בוודאות באיזה שירות יגיב לכוונה, והמשתמש לא יוכל לראות איזה שירות מתחיל.השדה הזה ב-
Intent
הוא אובייקטComponentName
, שאותו אפשר לציין באמצעות שם הסיווג המתאים של רכיב היעד, כולל שם החבילה של האפליקציה, לדוגמה,com.example.ExampleActivity
. אפשר להגדיר את שם הרכיב עםsetComponent()
,setClass()
,setClassName()
, או באמצעותIntent
constructor. - פעולה
- מחרוזת שמציינת את הפעולה הכללית שיש לבצע (כמו צפייה או בחירה).
במקרה של כוונת שידור, זו הפעולה שהתרחשה והדיווח מדווח. הפעולה קובעת במידה רבה את המבנה של שאר הכוונה, במיוחד את המידע שכלול בנתונים ובתוספות.
ניתן לציין פעולות משלך לשימוש על ידי כוונות בתוך האפליקציה (או לשימוש של גורמים אחרים) כדי להפעיל רכיבים באפליקציה), אבל בדרך כלל מציינים קבועים של פעולות. הוגדרו על ידי המחלקה
Intent
או סיווגי framework אחרים. הנה כמה דוגמאות פעולות נפוצות להתחלת פעילות:ACTION_VIEW
- השתמשו בפעולה הזו בכוונה עם
startActivity()
כשיש לכם מידע מסוים פעילות יכולה להופיע למשתמש, כמו תמונה לצפייה באפליקציית גלריה, או כתובת להציג באפליקציית מפה. ACTION_SEND
- נקרא גם כוונת שיתוף. צריך להשתמש בה ב-Intent עם
startActivity()
כשיש לכם נתונים מסוימים שהמשתמש יכול לשתף באמצעות אפליקציה אחרת, כמו אפליקציית אימייל או אפליקציית שיתוף ברשתות חברתיות.
מידע נוסף זמין במאמר בנושא
Intent
של הכיתה קבועים שמגדירים פעולות כלליות. פעולות אחרות הוגדרו במקומות אחרים במסגרת Android, למשל ב-Settings
לפעולות שפותחים מסכים מסוימים באפליקציית ההגדרות של המערכת.אפשר לציין את הפעולה עבור Intent באמצעות
setAction()
או באמצעות constructor שלIntent
.אם הגדרת פעולות משלך, חשוב לכלול את שם החבילה של האפליקציה כקידומת, כמו בדוגמה הבאה:
Kotlin
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Java
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
- נתונים
- ה-URI (אובייקט
Uri
) שמפנה את הנתונים אל ייעשה בו ו/או סוג ה-MIME של הנתונים האלה. סוג הנתונים שמסופקים בדרך כלל נקבע על ידי הפעולה של הכוונה. עבור לדוגמה, אם הפעולה היאACTION_EDIT
, הנתונים צריכים להכיל את הפונקציה ה-URI של המסמך לעריכה.כשיוצרים כוונה, לעיתים קרובות חשוב לציין את סוג הנתונים (סוג ה-MIME שלו) בנוסף ל-URI שלהם. לדוגמה, פעילות שיכולה להציג תמונות כנראה לא תאפשר כדי להפעיל קובץ אודיו, למרות שהפורמטים של ה-URI עשויים להיות דומים. ציון סוג ה-MIME של הנתונים עוזר ל-Android למצוא את הרכיב הטוב ביותר כדי לקבל את הכוונה שלך. עם זאת, לפעמים ניתן להסיק את סוג ה-MIME מה-URI - במיוחד כאשר הנתונים הם URI של
content:
. URI שלcontent:
מציין שהנתונים נמצאים במכשיר ונשלטים על ידיContentProvider
, שהופך את סוג ה-MIME של הנתונים לגלוי למערכת.כדי להגדיר רק את ה-URI של הנתונים, צריך לקרוא ל-
setData()
. כדי להגדיר רק סוג MIME, צריך להפעיל אתsetType()
. במקרה הצורך, הן יכולות להגדיר במפורש את שתיהן עםsetDataAndType()
.זהירות: אם אתם רוצים להגדיר גם URI וגם סוג MIME, אל תתקשרו אל
setData()
וsetType()
כי כל אחת מהן מבטלת את שוויון של האחר. יש להשתמש תמיד ב-setDataAndType()
כדי להגדיר את שתי האפשרויות URI וסוג MIME. - קטגוריה
- מחרוזת שמכילה מידע נוסף על סוג הרכיב
שאמורה להתמודד עם הכוונה. כל מספר של תיאורי קטגוריות יכול להיות
בתוך כוונה, אבל רוב הכוונות לא מחייבות קטגוריה.
לפניכם כמה קטגוריות נפוצות:
CATEGORY_BROWSABLE
- דפדפן אינטרנט יכול להפעיל את פעילות היעד כדי להציג נתונים מקישור, כמו תמונה או הודעת אימייל.
CATEGORY_LAUNCHER
- הפעילות היא הפעילות הראשונית של משימה, והיא מופיעה ברשימה מרכז האפליקציות של המערכת.
אפשר לעיין בתיאורי הכיתה ב
Intent
כדי לראות את הרשימה המלאה של קטגוריות.אפשר לציין קטגוריה באמצעות
addCategory()
.
המאפיינים שמפורטים למעלה (שם הרכיב, פעולה, נתונים וקטגוריה) מייצגים את המאפיינים של כוונה. על ידי קריאת המאפיינים האלה, מערכת Android מסוגל לפתור את רכיב האפליקציה שהוא צריך להפעיל. עם זאת, כוונת רכישה יכולה להוביל מידע נוסף שאינו משפיע על איך הוא מתבצע לרכיב אפליקציה. Intent יכול גם לספק את המידע הבא:
- תוספות
- צמדי מפתח/ערך שנושאים מידע נוסף שנדרש כדי
את הפעולה המבוקשת.
בדיוק כמו שפעולות מסוימות משתמשות בסוגים מסוימים של URI של נתונים, פעולות מסוימות כוללות גם תוספות מסוימות.
אפשר להוסיף עוד נתונים בשיטות שונות של
putExtra()
, שכל אחד מהם מקבל שני פרמטרים: שם המפתח והערך. אפשר גם ליצור אובייקטBundle
עם כל הנתונים הנוספים, ואז להוסיףBundle
בIntent
עםputExtras()
.לדוגמה, כשיוצרים כוונה לשלוח אימייל עם
ACTION_SEND
, אפשר לציין את הנמען אל עם מקשEXTRA_EMAIL
, ומציינים את הנושא עם מקשEXTRA_SUBJECT
.המחלקה
Intent
מציינת קבועים רבים שלEXTRA_*
לסוגי נתונים סטנדרטיים. אם תצטרכו להצהיר על מפתחות נוספים משלכם (למטרות Intent, שהאפליקציה שלך מקבלת), צריך לכלול את שם החבילה של האפליקציה כקידומת, כמו בדוגמה הבאה:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
זהירות: אין להשתמש באפשרויות
Parcelable
או נתוניSerializable
כששולחים Intent שציפיתם לקבל אפליקציה אחרת. אם האפליקציה מנסה לגשת לנתונים באובייקטBundle
אבל לא לקבל גישה למחלקה המחולקת או למחלקה בסדרה, המערכת מעלהRuntimeException
. - סימונים
- דגלים מוגדרים במחלקה
Intent
שמתפקדים כמטא-נתונים של בכוונה טובה. הדגלים עשויים להורות למערכת Android איך להפעיל פעילות (לדוגמה, משימה הפעילות צריכה להיות שייכת ל) ואיך לטפל בו לאחר ההשקה (לדוגמה, אם הוא נכלל ברשימת ).למידע נוסף, אפשר לעיין ב-method
setFlags()
.
דוגמה לכוונת רכישה מפורשת
כוונת רכישה מפורשת היא כזו שבה משתמשים כדי להפעיל רכיב ספציפי באפליקציה, כמו
פעילות או שירות מסוימים באפליקציה. כדי ליצור כוונה מפורשת, צריך להגדיר
שם הרכיב של האובייקט Intent
— הכול
מאפיינים אחרים של Intent הם אופציונליים.
לדוגמה, אם יצרתם באפליקציה שירות בשם DownloadService
,
שנועד להוריד קובץ מהאינטרנט, אפשר להתחיל אותו עם הקוד הבא:
Kotlin
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
Java
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse
(fileUrl)); startService(downloadIntent);
Intent(Context, Class)
constructor מספק את האפליקציה Context
רכיב של אובייקט Class
. לכן,
ה-Intent הזה מפעיל באופן מפורש את המחלקה DownloadService
באפליקציה.
למידע נוסף על יצירה והפעלה של שירות, אפשר לעיין במאמר המדריך שירותים.
דוגמה לאובייקט Intent מרומז
אובייקט Intent מרומז מציין פעולה שיכולה להפעיל כל אפליקציה במכשיר. כדי לבצע את הפעולה. השימוש בכוונת רכישה מרומזת הוא שימושי כאשר האפליקציה לא יכולה לבצע את אבל סביר להניח שאפליקציות אחרות כן יוכלו לעשות זאת, ואתם רוצים שהמשתמש יבחר באיזו אפליקציה להשתמש.
לדוגמה, אם יש לכם תוכן שאתם רוצים שהמשתמש ישתף עם אנשים אחרים,
ליצור כוונה
עם הפעולה ACTION_SEND
ולהוסיף תוספות שמציינות את התוכן שרוצים לשתף. כשמתקשרים
startActivity()
עם הכוונה הזו, המשתמש יכול
לבחור אפליקציה שבאמצעותה תשתפו את התוכן.
Kotlin
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// Create the text message with a string. Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
כשמתבצעת קריאה אל startActivity()
, המערכת
ובוחן את כל האפליקציות המותקנות כדי לקבוע אילו מהן יכולות להתמודד עם כוונה כזו (
Intent עם הפעולה ACTION_SEND
ושכוללת "טקסט/פשוט"
). אם יש רק אפליקציה אחת שיכולה לטפל בעניין, היא תיפתח מיד ותקבל את ההרשאה
בכוונה טובה. אם אין אפליקציות אחרות שיכולות לטפל בכך, האפליקציה יכולה לקלוט את
ActivityNotFoundException
שהתרחש. אם יש כמה פעילויות שמקבלות את הכוונה, המערכת
מציגה תיבת דו-שיח כמו זו שמוצגת באיור 2, כך שהמשתמש יכול לבחור באיזו אפליקציה להשתמש.
מידע נוסף על השקת אפליקציות אחרות מופיע במדריך על שליחת המשתמש אל אפליקציה אחרת.
![](https://developer.android.com/static/images/training/basics/intent-chooser.png?authuser=4&hl=he)
איור 2. תיבת דו-שיח של בורר.
אילוץ של בוחר אפליקציות
אם יש יותר מאפליקציה אחת שמגיבה לכוונה המרומזת שלכם, המשתמש יכול לבחור באיזו אפליקציה להשתמש ולהפוך אותה לבחירת ברירת המחדל פעולה. היכולת לבחור ברירת מחדל מועילה בעת ביצוע פעולה שעבורה המשתמש מבצע סביר להניח שהוא רוצה להשתמש באותה אפליקציה בכל פעם, למשל בעת פתיחת דף אינטרנט (משתמשים בדרך כלל מעדיפים דפדפן אינטרנט אחד בלבד).
עם זאת, אם מספר אפליקציות יכולות להגיב לכוונה, והמשתמש ירצה להשתמש
בכל פעם, עליך להציג באופן מפורש תיבת דו-שיח של בורר. בתיבת הדו-שיח של הבורר שואלת
משתמש כדי לבחור באיזו אפליקציה לבצע את הפעולה (המשתמש לא יכול לבחור אפליקציית ברירת מחדל עבור
הפעולה). לדוגמה, כשהאפליקציה מבצעת 'שיתוף' עם הפעולה ACTION_SEND
, ייתכן שהמשתמשים ירצו לשתף באמצעות אפליקציה אחרת, בהתאם
במצב הנוכחי שלהם, לכן עליך להשתמש תמיד בתיבת הדו-שיח של הבורר, כפי שמוצג באיור 2.
כדי להציג את ה-Selecter, צריך ליצור Intent
באמצעות createChooser()
ולהעביר אותו אל startActivity()
, כמו בדוגמה הבאה.
בדוגמה הזו מוצגת תיבת דו-שיח עם רשימת אפליקציות שמגיבות ל-Intent שהועבר ל-method createChooser()
, ומשתמשת בטקסט שסופק
כותרת של תיבת דו-שיח.
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Java
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... // Always use string resources for UI text. // This says something like "Share this photo with" String title = getResources().getString(R.string.chooser_title); // Create intent to show the chooser dialog Intent chooser = Intent.createChooser(sendIntent, title); // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
זיהוי הפעלות של כוונת רכישה לא בטוחה
האפליקציה עשויה להפעיל כוונות מודעה כדי לנווט בין רכיבים בתוך האפליקציה, או לבצע פעולה בשם אפליקציה אחרת. כדי לשפר את אבטחת הפלטפורמה, ב-Android 12 (רמת API 31) ואילך יש תכונה לניפוי באגים שמזהירה אתכם אם האפליקציה מבצעת הפעלה לא בטוחה של Intent. לדוגמה, ייתכן שהאפליקציה לבצע השקה לא בטוחה של אובייקט Intent בתוך רכיב, שדומה ל-Intent שמועבר כתוספת בכוונה אחרת.
אם האפליקציה תבצע את שתי הפעולות הבאות, המערכת תזהה השקת Intent והפרה של StrictMode קורה:
- האפליקציה שלך מפענחת אובייקט שנמצא בתוך Intent מתוך התוספות של כוונת רכישה שהועברה.
- האפליקציה שלך מפעילה אפליקציה באופן מיידי
ברכיב מסוים באמצעות ה-Intent המקונן הזה,
כמו העברת הכוונה אל
startActivity()
,startService()
, אוbindService()
.
כדי לקבל פרטים נוספים שמסבירים איך לזהות את המצב הזה ולבצע שינויים באפליקציה, לקריאת הפוסט בבלוג על Android Nesting כוונות ב-Medium.
בדיקה אם יש הפעלות של Intent לא בטוח
כדי לבדוק אם יש הפעלות של כוונת רכישה לא בטוחה באפליקציה, צריך להתקשר
detectUnsafeIntentLaunch()
כשמגדירים את VmPolicy
, כפי שמוצג בקטע הקוד הבא. אם המיקום
שהאפליקציה מזהה הפרה של StrictMode. כדאי להפסיק את הפעלת האפליקציה כדי
להגן על מידע שעשוי להיות רגיש.
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
Java
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
שימוש בכוונות בצורה אחראית יותר
כדי לצמצם את הסיכויים להשקת Intent לא בטוחה ולהפרה של StrictMode, כדאי לפעול לפי השיטות המומלצות האלו.
מעתיקים רק את התוספות החיוניות מתוך Intent, ומבצעים את כל מה שצריך
תברואה ואימות. האפליקציה שלך עשויה להעתיק את התוספות מהפניה אחת אל
כוונה אחרת שמשמשת להשקת רכיב חדש. מצב זה מתרחש כאשר
שיחות מהאפליקציה
putExtras(Intent)
או
putExtras(Bundle)
אם האפליקציה מבצעת אחת מהפעולות האלה, העתיקו רק את התוספות
שהרכיב המקבל מצפה לקבל. אם כוונת המשתמש האחרת (שמקבלת את העותק)
מפעיל רכיב
לייצא, לחיטוי
לאמת את התוספות לפני שמעתיקים אותן אל הכוונה שמפעילה את
לרכיב הזה.
אל תייצאו את רכיבי האפליקציה ללא צורך. לדוגמה, אם
מתכוונים להפעיל רכיב אפליקציה באמצעות Intent פנימי מקונן,
המאפיין android:exported
של הרכיב ל-false
.
שימוש ב-PendingIntent
במקום ב-
Intent בתצוגת עץ. כך, כשאפליקציה אחרת פורקת את PendingIntent
של שלה
שמכיל את Intent
, האפליקציה האחרת יכולה להפעיל את PendingIntent
באמצעות
בזהות של האפליקציה. ההגדרה הזו מאפשרת לאפליקציה השנייה להפעיל בבטחה
רכיב כלשהו באפליקציה, כולל רכיב שלא מיוצא.
בתרשים באיור 2 ניתן לראות איך המערכת מעבירה את השליטה מהלקוח (לקוח) לאפליקציה אחרת (שירות) וחזרה לאפליקציה:
- האפליקציה שלכם יוצרת כוונה שמובילה לפעילות באפליקציה אחרת. בטווח של
את הכוונה הזו, מוסיפים אובייקט
PendingIntent
כתוספת. Intent בהמתנה מפעיל רכיב באפליקציה. הרכיב הזה לא מיוצא. - עם קבלת הכוונה של האפליקציה, האפליקציה השנייה מחלצת את הנתונים שהוצבו
אובייקט
PendingIntent
. - האפליקציה השנייה מפעילה את ה-method
send()
באובייקטPendingIntent
. - אחרי שתחזירו את השליטה לאפליקציה, המערכת תפעיל את מצב המתנה בכוונה טובה, באמצעות ההקשר של האפליקציה.
איור 2. תרשים של תקשורת בין אפליקציות בזמן שימוש במשתנה מסוג 'בהמתנה' בכוונה טובה.
קבלת כוונה מרומזת
כדי לפרסם אובייקטים מרומזים של Intent שהאפליקציה יכולה לקבל, צריך להצהיר על מסנן Intent אחד או יותר
כל אחד מרכיבי האפליקציה עם <intent-filter>
בקובץ המניפסט.
כל מסנן Intent מציין את סוג ה-Intents שהוא מקבל על סמך הפעולה של Intent,
לפי נתונים וקטגוריה. המערכת מספקת כוונה מרומזת לרכיב האפליקציה רק אם
Intent יכול לעבור דרך אחד ממסנני Intent שלכם.
הערה: כוונה מפורשת תמיד נמסרת ליעד שלה, ללא קשר למסננים של Intent שמוצהר על ידי הרכיב.
רכיב אפליקציה צריך להצהיר על מסננים נפרדים לכל משימה ייחודית שהוא יכול לבצע.
לדוגמה, פעילות אחת באפליקציה של גלריית התמונות עשויה לכלול שני מסננים: מסנן אחד
כדי להציג תמונה, ומסנן נוסף לעריכת תמונה. כשהפעילות מתחילה,
הוא בודק את Intent
ומחליטים איך לפעול על סמך המידע
ב-Intent
(למשל, כדי להציג או לא להציג את פקדי העריכה).
כל מסנן Intent מוגדר על ידי <intent-filter>
בקובץ המניפסט של האפליקציה, מקונן ברכיב האפליקציה המתאים (כמו
בתור <activity>
).
בכל רכיב אפליקציה שכולל רכיב <intent-filter>
,
להגדיר במפורש ערך עבור
android:exported
.
המאפיין הזה מציין אם רכיב האפליקציה נגיש לאפליקציות אחרות. בחלק מהמקרים
מצבים כאלה, כמו פעילויות שמסנני הכוונה שלהן כוללים
LAUNCHER
מומלץ להגדיר את המאפיין הזה כ-true
. אחרת,
בטוח יותר להגדיר את המאפיין הזה ל-false
.
אזהרה: אם מדובר בפעילות, בשירות או בשידור
מקבל האפליקציה באפליקציה משתמש במסנני Intent ולא מגדיר במפורש את הערך
עבור android:exported
, לא ניתן להתקין את האפליקציה שלך במכשיר
מערכת ההפעלה Android מגרסה 12 ואילך.
בתוך <intent-filter>
,
אפשר לציין את סוג ה-Intent שאתם רוצים לאשר באמצעות הגדרה אחת או יותר
מבין שלושת הרכיבים האלה:
<action>
- מצהירה על פעולת ה-Intent שהתקבלה, במאפיין
name
. הערך חייב להיות ערך מחרוזת מילולי של פעולה, לא קבוע המחלקה. <data>
- מציין את סוג הנתונים הקבילים, באמצעות מאפיין אחד או יותר שמציינים ערכים שונים
היבטים שונים של ה-URI של הנתונים (
scheme
,host
,port
,path
) וסוג MIME. <category>
- מצהירה על קטגוריית ה-Intent הקבילה, במאפיין
name
. הערך חייב להיות ערך המחרוזת הליטרלי של פעולה, לא קבוע המחלקה.הערה: כדי לקבל כוונות מרומזות, חייבת לכלול את הקטע בקטגוריה
CATEGORY_DEFAULT
במסנן Intent. השיטותstartActivity()
והקבוצהstartActivityForResult()
מתייחסים לכל הכוונות כאילו הם הצהירו על הקטגוריהCATEGORY_DEFAULT
. אם לא תציינו את הקטגוריה הזו במסנן Intent שלכם, אף אובייקט Intent מרומז לא יתייחס בפעילות שלכם.
לדוגמה, הנה הצהרת פעילות עם מסנן Intent כדי לקבל
Intent מסוג ACTION_SEND
כשסוג הנתונים הוא טקסט:
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
אפשר ליצור מסנן שכולל יותר ממופע אחד של
<action>
<data>
, או
<category>
.
אם כן, עליך להיות בטוח שהרכיב יכול לטפל בכל
חדשים של אלמנטים כאלה.
כשרוצים לטפל בכמה סוגים של כוונות, אבל רק בשילובים ספציפיים של פעולה, נתונים וסוג קטגוריה, עליכם ליצור מספר מסנני Intent.
Intent מרומז נבדק מול מסנן על ידי השוואת הכוונה לכל אחד בשלושה רכיבים. כדי להימסר לרכיב, הכוונה חייבת לעבור את כל שלושת הבדיקות. אם לא תמצא התאמה אפילו לאחד מהם, מערכת Android לא תספק את הכוונה לרכיב הזה. עם זאת, מאחר שלרכיב מסוים יכולים להיות כמה מסנני Intent, אובייקט עם Intent אם לא יעבור דרך אחד מהמסננים של רכיב מסוים, יכול להיות שהוא יגיע דרך מסנן אחר. מידע נוסף על האופן שבו המערכת מזהה כוונות זמין בקטע שבהמשך. על פתרון של Intent.
זהירות: שימוש במסנן Intent אינו דרך מאובטחת למנוע מאפליקציות אחרות להפעיל
הרכיבים שלך. אף על פי שמסנני Intent מגבילים רכיב להגיב רק לרכיב מסוים.
סוגים מסוימים של כוונות מרומזות, אפליקציה אחרת יכולה להפעיל את רכיב האפליקציה שלכם
באמצעות שימוש בכוונת רכישה מפורשת אם המפתח קובע את שמות הרכיבים שלך.
אם חשוב רק האפליקציה שלכם תוכל להפעיל אחד מהרכיבים,
לא להצהיר על מסנני Intent במניפסט. במקום זאת, הגדירו
מאפיין exported
אל "false"
לרכיב הזה.
באופן דומה, כדי למנוע הפעלה בטעות של אפליקציה אחרת
Service
, תמיד צריך להשתמש בכוונה מפורשת להתחיל שירות משלך.
הערה:
עבור כל הפעילויות, עליכם להצהיר על מסנני Intent בקובץ המניפסט.
עם זאת, ניתן לרשום מסננים למקלטי שידורים באופן דינמי באמצעות קריאה
registerReceiver()
אחר כך אפשר לבטל את הרישום של המקבל אצל unregisterReceiver()
. כך תאפשר לאפליקציה שלך
להאזין לשידורים ספציפיים במהלך פרק זמן ספציפי בלבד, בזמן שהאפליקציה
פועלת.
מסננים לדוגמה
כדי להדגים חלק מההתנהגויות של מסנני Intent, הנה דוגמה מקובץ המניפסט של אפליקציה לשיתוף חברתי:
<activity android:name="MainActivity" android:exported="true"> <!-- This activity is the main entry, should appear in app launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ShareActivity" android:exported="false"> <!-- This activity handles "SEND" actions with text data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/vnd.google.panorama360+jpg"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity>
הפעילות הראשונה, MainActivity
, היא נקודת הכניסה הראשית של האפליקציה – הפעילות ש
נפתח כשהמשתמש מפעיל לראשונה את האפליקציה בעזרת סמל מרכז האפליקציות:
- הפעולה
ACTION_MAIN
מציין שזו נקודת הכניסה העיקרית ולא מצפה לנתונים לגבי כוונת רכישה. - הקטגוריה
CATEGORY_LAUNCHER
מציינת שהפעילות הזו יש למקם את הסמל במרכז האפליקציות של המערכת. אם הרכיב<activity>
לא מציין סמל עםicon
, המערכת משתמשת בסמל מ-<application>
לרכיב מסוים.
יש לחבר בין שני הסוגים האלה כדי שהפעילות תופיע במרכז האפליקציות.
הפעילות השנייה, ShareActivity
, נועדה לאפשר שיתוף של טקסט ומדיה
תוכן. למרות שמשתמשים יכולים להיכנס לפעילות הזו על ידי ניווט אליה מ-MainActivity
,
הם יכולים גם להזין את ShareActivity
ישירות מאפליקציה אחרת שגורמת להטמעה משתמעת
שתואם לאחד משני מסנני ה-Intent.
הערה: סוג MIME,
application/vnd.google.panorama360+jpg
, הוא סוג מיוחד של נתונים שמציין
תמונות פנורמיות, שניתן לטפל בהן באמצעות Google
ממשקי API של פנורמה.
התאמת כוונות לאפליקציות אחרות מסנני Intent
אם אפליקציה אחרת מטרגטת את Android 13 (רמת API 33) ואילך, היא יכולה לטפל ב
לכוונת האפליקציה רק אם הכוונה שלכם תואמת את הפעולות והקטגוריות של
רכיב <intent-filter>
באפליקציה האחרת. אם המערכת לא מוצאת
זורקת
ActivityNotFoundException
.
האפליקציה השולחת חייבת לטפל
במקרה הזה.
באופן דומה, אם מעדכנים את האפליקציה כך שהיא תטרגט את Android 13
ומעלה, כל הכוונות שמקורם באפליקציות חיצוניות מועברות אל
של הרכיב שייצאתם באפליקציה שלכם רק אם הכוונה שלו תואמת את הפעולות
קטגוריות של רכיב <intent-filter>
שהאפליקציה שלך מצהירה עליהן. ההתנהגות הזו
מתרחשת ללא קשר לגרסת היעד של ה-SDK של האפליקציה השולח.
במקרים הבאים לא מתבצעת אכיפה של התאמת Intent:
- אובייקטים מסוג Intent נשלחים לרכיבים שלא מוצהרים בהם מסנני Intent.
- כוונות שמקורם בתוך אותה האפליקציה.
- מנגנוני Intent שמקורם במערכת. כלומר, כוונות שנשלחות
'UID של המערכת' (uid=1000). אפליקציות המערכת כוללות את
system_server
ואפליקציות שהוגדרוandroid:sharedUserId
עדandroid.uid.system
. - Intents שמקורם מהרמה הבסיסית (root).
מידע נוסף על התאמה של כוונת רכישה
שימוש ב-Intent בהמתנה
אובייקט PendingIntent
הוא wrapper מסביב לאובייקט Intent
. המטרה העיקרית של PendingIntent
הוא להעניק אישור לבקשה זרה
כדי להשתמש ב-Intent
הכלול כאילו הוא בוצע מתוך
התהליך של האפליקציה עצמה.
תרחישי שימוש עיקריים עבור Intent בהמתנה כוללים את אלה:
- הצהרה על כוונה לביצוע כשהמשתמש מבצע פעולה באמצעות ההתראה
(ה-
NotificationManager
של מערכת Android מפעיל אתIntent
). - הצהרה על כוונה להוציא לפועל כשהמשתמש מבצע פעולה עם
ווידג'ט לאפליקציה
(אפליקציית מסך הבית מפעילה את
Intent
). - הצהרה על כוונה להוציא לפועל בזמן עתידי מסוים (ה-Android
AlarmManager
של המערכת יריץ אתIntent
).
בדיוק כמו שכל אובייקט Intent
מיועד לטיפול על ידי מודל אבטחה ספציפי
הסוג של רכיב האפליקציה (Activity
, Service
או
a BroadcastReceiver
), ולכן גם PendingIntent
צריך להיות
שנוצר עם אותו שיקול דעת. כשמשתמשים ב-Intent בהמתנה, האפליקציה לא
לבצע את ה-Intent באמצעות קריאה כמו startActivity()
. במקום זאת, עליכם להצהיר על סוג הרכיב המיועד כשיוצרים את הרכיב
PendingIntent
באמצעות קריאה לשיטה המתאימה של היוצר:
PendingIntent.getActivity()
עבורIntent
שמתחיל ב-Activity
.PendingIntent.getService()
עבורIntent
שמתחיל ב-Service
.PendingIntent.getBroadcast()
עבורIntent
שמתחיל ב-BroadcastReceiver
.
אלא אם האפליקציה מקבלת כוונות בהמתנה מאפליקציות אחרות,
השיטות שלמעלה ליצירת PendingIntent
הן ככל הנראה השיטה היחידה
PendingIntent
שיטות להשתמש בהן.
כל שיטה לוקחת את האפליקציה הנוכחית Context
,
Intent
שרוצים לכלול, ודגל אחד או יותר המציינים
איך צריך להשתמש בכוונה (למשל אם אפשר להשתמש בכוונה יותר מפעם אחת).
למידע נוסף על השימוש באובייקטים מסוג Intent בהמתנה, ניתן לעיין במסמכים של כל אחד מהם של התרחישים הרלוונטיים, כמו בהתראות ומדריכים לממשק ה-API של ווידג'טים של אפליקציות.
ציון יכולת ההשתנות
אם האפליקציה מטרגטת את Android 12 ואילך, צריך לציין את
את יכולת השינוי של כל אובייקט PendingIntent
שהאפליקציה שלך יוצרת. כדי להצהיר כי
אובייקט PendingIntent
נתון ניתן לשינוי או בלתי ניתן לשינוי, משתמשים
PendingIntent.FLAG_MUTABLE
או
PendingIntent.FLAG_IMMUTABLE
בהתאמה,
אם האפליקציה מנסה ליצור אובייקט PendingIntent
בלי להגדיר אף אחד מהדגלים של יכולת שינוי, המערכת תגרור
IllegalArgumentException
, וגם
ההודעה הבאה מופיעה ב-Logcat:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
כשאפשר, יצירת Intents בהמתנה שאינם ניתנים לשינוי
ברוב המקרים, האפליקציה צריכה ליצור אובייקטים מסוג PendingIntent
שלא ניתנים לשינוי, כמו
שמוצגת בקטע הקוד הבא. אם אובייקט PendingIntent
לא ניתן לשינוי,
אפליקציות אחרות לא יוכלו לשנות את הכוונה ולהתאים את התוצאה של הפעלת
בכוונה טובה.
Kotlin
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
אבל בתרחישי שימוש מסוימים יש צורך באובייקטים PendingIntent
שניתנים לשינוי במקום זאת:
- תמיכה בפעולות של תשובה ישירה במסגרת
התראות.
כדי להשיב הישירה צריך לשנות את נתוני הקליפ באובייקט PendingIntent
שמשויכים לתשובה. בדרך כלל, כדי לבקש את השינוי הזה,
FILL_IN_CLIP_DATA
כדגלfillIn()
. - שיוך התראות ל-framework של Android Auto באמצעות מופעים של
CarAppExtender
- מיקום שיחות בבועות באמצעות מופעים
מתוך
PendingIntent
. אובייקטPendingIntent
ניתן לשינוי מאפשר למערכת להחיל הדגלים הנכונים,FLAG_ACTIVITY_MULTIPLE_TASK
וגםFLAG_ACTIVITY_NEW_DOCUMENT
. - בקשת פרטי מיקום של המכשיר
requestLocationUpdates()
או ממשקי API דומים. אובייקטPendingIntent
הניתן לשינוי מאפשר למערכת להוסיף תוספות Intent שמייצגות אירועים במחזור החיים של המיקום. האירועים האלה כוללים שינוי במיקום וזמינות של ספק. - תזמון התראות באמצעות
AlarmManager
. אובייקטPendingIntent
הניתן לשינוי מאפשר למערכת להוסיף אתEXTRA_ALARM_COUNT
כוונה נוספת. הנתון הזה מייצג את מספר הפעמים שבהן התראה חוזרת הופעל. הכללת התוספת הזו תאפשר ל-Intent להודיע באופן מדויק אפליקציה שמציינת אם התראה חוזרת הופעלה כמה פעמים, למשל כשהמכשיר היה במצב שינה.
אם האפליקציה יוצרת אובייקט PendingIntent
שניתן לשינוי, מומלץ מאוד לעשות זאת
שאתם משתמשים בכוונה מפורשת וממלאים את
ComponentName
כך, בכל פעם
אפליקציה אחרת מפעילה את PendingIntent
ומעבירה את הבקרה בחזרה לאפליקציה,
אותו רכיב באפליקציה מתחיל תמיד.
שימוש באובייקטים מפורשים של Intent בתוך כוונות בהמתנה
כדי להגדיר טוב יותר איך אפליקציות אחרות יכולות להשתמש בכוונות בהמתנה של האפליקציה, תמיד תחום של Intent בהמתנה סביב אובייקט Intent מפורש. כדי לפעול בהתאם לשיטה המומלצת הזו, כדאי לבצע את הפעולות הבאות:
- צריך לבדוק את השדות 'פעולה', 'חבילה' ו'רכיב' של Intent הבסיס מוגדרות.
-
שימוש ב-
FLAG_IMMUTABLE
, שנוספו ב-Android 6.0 (רמת API 23), כדי ליצור אובייקטים מסוג Intent בהמתנה. הדגל הזה מונע מאפליקציות שקיבלוPendingIntent
למלא נכסים שאינם מאוכלסים. אםminSdkVersion
של האפליקציה הוא22
ומטה, אפשר לספק בטיחות ותאימות ביחד באמצעות הקוד הבא:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
זיהוי Intent
כשהמערכת מקבלת כוונה מרומזת להתחיל פעילות, היא מחפשת הפעילות הטובה ביותר עבור הכוונה, על ידי השוואתה למסנני Intent על סמך שלושה היבטים:
- פעולה.
- נתונים (גם URI וגם סוג הנתונים).
- קטגוריה.
בקטעים הבאים מתואר האופן שבו הכוונות מותאמות לרכיבים המתאימים בהתאם להצהרה של מסנן Intent בקובץ המניפסט של האפליקציה.
בדיקת פעולה
כדי לציין פעולות קבילות של Intent, מסנן Intent יכול להצהיר על אפס או יותר
רכיבי <action>
, כמו בדוגמה הבאה:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
כדי להעביר את המסנן הזה, הפעולה שצוינה בIntent
חייבים להתאים לאחת מהפעולות שמופיעות במסנן.
אם המסנן לא מציג פעולות כלשהן, אין
כוונה להתאים, כך שכל הכוונות נכשלות במבחן. אבל אם Intent
אינו מציין פעולה, הוא עובר את הבדיקה כל עוד
מכיל פעולה אחת לפחות.
בדיקת קטגוריה
כדי לציין קטגוריות מקובלות של Intent, מסנן Intent יכול להצהיר על אפס או יותר.
רכיבי <category>
, כמו בדוגמה הבאה:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
כדי לעבור את בדיקת הקטגוריה, כל קטגוריה בIntent
חייבת להתאים לקטגוריה במסנן. ההפך אינו הכרחי - מסנן Intent
להצהיר על יותר קטגוריות מאלה שצוינו ב-Intent
Intent
עדיין מסירות. לכן, כוונה ללא קטגוריות
תמיד עובר את הבדיקה הזו, ללא קשר לקטגוריות שמוצהרות במסנן.
הערה:
מערכת Android מחילה את הקטגוריה CATEGORY_DEFAULT
באופן אוטומטי
לכל הכוונות המרומזות שמועברות אל startActivity()
ואל startActivityForResult()
.
אם אתם רוצים שהפעילות שלכם תקבל כוונות מרומזות, עליה
כוללים קטגוריה של "android.intent.category.DEFAULT"
במסנני Intent שלו, למשל
שמוצגת בדוגמה הקודמת (<intent-filter>
).
בדיקת נתונים
כדי לציין נתונים קבילים של כוונת רכישה, מסנן Intent יכול להצהיר על אפס או יותר
רכיבי <data>
, כמו בדוגמה הבאה:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
בכל <data>
הרכיב יכול לציין מבנה URI וסוג נתונים (סוג מדיה MIME).
כל חלק ב-URI הוא
מאפיין: scheme
, host
, port
,
ו-path
:
<scheme>://<host>:<port>/<path>
בדוגמה הבאה אפשר לראות את הערכים האפשריים של המאפיינים האלה:
content://com.example.project:200/folder/subfolder/etc
ב-URI הזה, הסכמה היא content
, המארח הוא com.example.project
,
היציאה היא 200
והנתיב הוא folder/subfolder/etc
.
כל אחד מהמאפיינים האלה הוא אופציונלי ברכיב <data>
,
אבל יש יחסי תלות לינאריים:
- אם לא מצוינת סכמה, המערכת מתעלמת מהמארח.
- אם לא מצוין מארח, המערכת תתעלם מהיציאה.
- אם לא מציינים גם את הסכימה וגם את המארח, המערכת מתעלמת מהנתיב.
כשמשווים את ה-URI ב-Intent למפרט URI במסנן, הוא בהשוואה רק לחלקים של ה-URI שכלולים במסנן. לדוגמה:
- אם מסנן מציין רק סכימה, כל מזהי ה-URI עם הסכמה זו תואמים את המסנן.
- אם מסנן מציין סכמה ורשות אבל לא נתיב, כל מזהי ה-URI בעלי אותה הסכמה וסמכות מעבירים את המסנן, בלי קשר לנתיבים שלהם.
- אם מסנן מציין סכמה, סמכות ונתיב, רק מזהי URI עם אותה סכימה, ונתיב מעבירים את המסנן.
הערה: מפרט נתיב להכיל כוכבית עם תו כללי לחיפוש (*), כדי לדרוש רק התאמה חלקית של שם הנתיב.
בדיקת הנתונים משווה גם את ה-URI וגם את סוג ה-MIME ב-Intent ל-URI וסוג ה-MIME שצוינו במסנן. אלה הכללים:
- Intent שלא מכיל URI או סוג MIME עובר את רק אם המסנן לא מציין URI או סוגי MIME.
- אובייקט Intent שמכיל URI אבל לא סוג MIME (לא מפורש ולא ניתן להסיק URI) עובר את הבדיקה רק אם ה-URI שלו תואם לפורמט ה-URI של המסנן וגם המסנן לא מציין סוג MIME.
- Intent שמכיל סוג MIME אבל לא URI עובר את הבדיקה. רק אם המסנן מציג את אותו סוג MIME ולא מציין פורמט URI.
- אובייקט Intent שמכיל גם URI וגם סוג MIME (מבוטאת או מסולפת מתוך
URI) מעביר את החלק מסוג MIME בבדיקה רק אם
הסוג תואם לסוג שמצוין במסנן. היא מעבירה את חלק ה-URI של הבדיקה
אם ה-URI שלו תואם ל-URI במסנן או אם יש לו
content:
אוfile:
URI והמסנן לא מציין URI. במילים אחרות, הנחה שרכיב מסוים תומך בנתונים שלcontent:
ו-file:
אם המסנן מפרט רק סוג MIME.
הערה: אם ה-Intent מציין סוג URI או MIME, בדיקת הנתונים
תיכשל אם אין רכיבי <data>
ב-<intent-filter>
.
הכלל האחרון, כלל (d), משקף את הציפייה
הרכיבים יכולים לקבל נתונים מקומיים מקובץ או מספק תוכן.
לכן המסננים שלהם יכולים לציין רק את סוג הנתונים, והם לא צריכים להוסיף
נותנים שם לסכמות content:
ו-file:
.
הדוגמה הבאה מציגה מקרה אופייני שבו הרכיב <data>
מנחה את Android שהרכיב יכול לקבל נתוני תמונה מתוכן
הספק ומציג אותו:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
מסננים לציין סוג נתונים אך לא URI הם כנראה הנפוצים ביותר, מפני שהרוב חלק מספקי התוכן מפוזרים.
הגדרה נפוצה אחרת היא מסנן עם סכמה וסוג נתונים. עבור
לדוגמה, <data>
כמו בדוגמה הבאה, אומר ל-Android
הרכיב יכול לאחזר נתוני וידאו מהרשת כדי לבצע את הפעולה:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
התאמה של כוונת רכישה
מתבצעת התאמה בין הכוונות לבין מסנני Intent לא רק כדי לגלות יעד
להפעיל, אבל גם לגלות משהו על קבוצת
הרכיבים במכשיר. לדוגמה, אפליקציית Home מאכלסת את מרכז האפליקציות
על ידי מציאת כל הפעילויות עם מסנני Intent שמציינים את
פעולה אחת (ACTION_MAIN
) ו
הקטגוריה CATEGORY_LAUNCHER
.
התאמה מצליחה רק אם הפעולות והקטגוריות ב-Intent תואמים
מול המסנן, כפי שמתואר בתיעוד של IntentFilter
בכיתה.
האפליקציה שלך יכולה להשתמש בהתאמת Intent באופן דומה לאופן הפעולה של אפליקציית Home.
ב-PackageManager
יש קבוצה של query...()
שמחזירות את כל הרכיבים שיכולים לקבל כוונה מסוימת
סדרה דומה של resolve...()
שיטות שקובעות
כדי להגיב לכוונה. לדוגמה,
הפונקציה queryIntentActivities()
מחזירה רשימה של כל הפעילויות שיכולות לבצע
את Intent שמועבר כארגומנט, ו-queryIntentServices()
מחזירה רשימה דומה של שירותים.
אף אחת מהשיטות לא מפעילה את הרכיבים. הם פשוט מציינים את התוצאות
יכול להגיב. יש שיטה דומה,
queryBroadcastReceivers()
, למקלטי שידורים.