במסמך הזה מתוארים כמה תרחישים לדוגמה נפוצים שבהם יש אינטראקציה בין אפליקציה לבין אפליקציות אחרות. בכל קטע מוסבר איך להשיג את הפונקציונליות של האפליקציה עם חשיפה מוגבלת של החבילה. כדאי להביא זאת בחשבון אם האפליקציה שלכם מטרגטת ל-Android 11 (רמת API 30) ואילך.
כשאפליקציה שמטרגטת Android 11 ואילך משתמשת ב-Intent כדי להפעיל פעילות באפליקציה אחרת, הגישה הפשוטה ביותר היא להפעיל את ה-Intent ולטפל בחריגה ActivityNotFoundException
אם אין אפליקציה זמינה.
אם חלק מהאפליקציה תלוי לדעת אם הקריאה ל-startActivity()
יכולה להצליח, למשל להציג ממשק משתמש, צריך להוסיף רכיב לרכיב <queries>
במניפסט של האפליקציה. בדרך כלל זהו רכיב <intent>
.
פתיחה של כתובות ה-URL
בקטע הזה מתוארות דרכים שונות לפתוח כתובות URL באפליקציה שמטרגטת את Android מגרסה 11 ואילך.
פתיחת כתובות URL בדפדפן או באפליקציה אחרת
כדי לפתוח כתובת URL, משתמשים ב-Intent שמכיל את פעולת ה-Intent ACTION_VIEW
, כפי שמתואר במדריך לטעינה של כתובת URL לאתר. אחרי שמפעילים את startActivity()
באמצעות הכוונה הזו, מתרחשת אחת מהאפשרויות הבאות:
- כתובת ה-URL נפתחת באפליקציית דפדפן אינטרנט.
- כתובת ה-URL תיפתח באפליקציה שתומכת בכתובת ה-URL כקישור עומק.
- תופיע תיבת דו-שיח להבחנה, שמאפשרת למשתמש לבחור איזו אפליקציה תפתח את כתובת ה-URL.
השגיאה
ActivityNotFoundException
מתרחשת כי אין במכשיר אפליקציה שיכולה לפתוח את כתובת ה-URL. (הדבר הזה לא רגיל).מומלץ לאתר את הבעיה
ActivityNotFoundException
ולטפל בה באפליקציה אם היא מתרחשת.
מכיוון ששימוש ב-method startActivity()
לא מחייב הרשאות גישה לחבילה כדי להתחיל פעילות של אפליקציה אחרת, לא צריך להוסיף רכיב <queries>
למניפסט של האפליקציה או לבצע שינויים ברכיב <queries>
קיים. הדבר נכון גם לגבי כוונות מרומזות וגם מפורשות שפותחים כתובת URL.
איך בודקים אם דפדפן זמין
במקרים מסוימים, יכול להיות שהאפליקציה תצטרך לוודא שיש לפחות דפדפן אחד זמין במכשיר, או שדפדפן ספציפי הוא דפדפן ברירת המחדל, לפני שתנסה לפתוח כתובת URL. במקרים כאלה, צריך לכלול את האלמנט <intent>
כחלק מהאלמנט <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent>
כשקוראים ל-queryIntentActivities()
ומעבירים כערך ארגומנטים את הכוונה לאינטרנט, בחלק מהמקרים הרשימה שמוחזרת כוללת את אפליקציות הדפדפן הזמינות. אם המשתמש הגדיר את כתובת ה-URL לפתיחה באפליקציה שאינה דפדפן כברירת מחדל, הרשימה לא כוללת אפליקציות דפדפן.
פתיחת כתובות URL בכרטיסיות מותאמות אישית
כרטיסיות בהתאמה אישית מאפשרות לאפליקציה להתאים אישית את המראה והתחושה של הדפדפן. אתם יכולים לפתוח כתובת URL בכרטיסייה בהתאמה אישית בלי להוסיף או לשנות את הרכיב <queries>
במניפסט של האפליקציה.
עם זאת, כדאי לבדוק אם במכשיר יש דפדפן שתומך בכרטיסיות בהתאמה אישית או לבחור דפדפן ספציפי להפעלה עם כרטיסיות בהתאמה אישית באמצעות CustomTabsClient.getPackageName()
.
במקרים כאלה, צריך לכלול את האלמנט <intent>
הבא כחלק מהאלמנט <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.support.customtabs.action.CustomTabsService" /> </intent>
איך מאפשרים לאפליקציות שאינן דפדפנים לטפל בכתובות URL
גם אם האפליקציה שלכם יכולה לפתוח כתובות URL באמצעות כרטיסיות בהתאמה אישית, מומלץ לאפשר לאפליקציה שאינה דפדפן לפתוח כתובת URL, אם אפשר. כדי לספק את היכולת הזו באפליקציה, מנסים לבצע קריאה ל-startActivity()
באמצעות Intent שמגדיר את דגל הכוונה של FLAG_ACTIVITY_REQUIRE_NON_BROWSER
. אם המערכת תחזיר את הערך ActivityNotFoundException
, האפליקציה תוכל לפתוח את כתובת ה-URL בכרטיסייה מותאמת אישית.
אם הכוונה כוללת את הדגל הזה, קריאה ל-startActivity()
תגרום להשלכת ActivityNotFoundException
כשאחד מהתנאים הבאים מתקיים:
- השיחה תפעיל אפליקציית דפדפן ישירות.
- במהלך השיחה, תוצג למשתמש תיבת דו-שיח להסרת עמימות, שבה האפשרויות היחידות הן אפליקציות דפדפן.
קטע הקוד הבא מראה איך לעדכן את הלוגיקה כך שתשתמש בדגל הכוונה FLAG_ACTIVITY_REQUIRE_NON_BROWSER
:
Kotlin
try { val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply { // The URL should either launch directly in a non-browser app (if it's // the default) or in the disambiguation dialog. addCategory(CATEGORY_BROWSABLE) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER } startActivity(intent) } catch (e: ActivityNotFoundException) { // Only browser apps are available, or a browser is the default. // So you can open the URL directly in your app, for example in a // Custom Tab. openInCustomTabs(url) }
Java
try { Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); // The URL should either launch directly in a non-browser app (if it's the // default) or in the disambiguation dialog. intent.addCategory(CATEGORY_BROWSABLE); intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER); startActivity(intent); } catch (ActivityNotFoundException e) { // Only browser apps are available, or a browser is the default. // So you can open the URL directly in your app, for example in a // Custom Tab. openInCustomTabs(url); }
הימנעות מתיבת דו-שיח להסרת עמימות
אם אתם רוצים להימנע מהצגת תיבת הדו-שיח של הסרת הספק (disambiguation) שעשויה להופיע למשתמשים כשהם פותחים כתובת URL, ובמקום זאת אתם מעדיפים לטפל בכתובת ה-URL בעצמכם במצבים כאלה, תוכלו להשתמש בכוונה שמגדירה את דגל הכוונה FLAG_ACTIVITY_REQUIRE_DEFAULT
.
אם הכוונה כוללת את הדגל הזה, קריאה ל-startActivity()
תגרום להשלכת ActivityNotFoundException
במקרה שהקריאה הייתה מציגה למשתמש תיבת דו-שיח לצורך הסרת עמימות.
אם אובייקט Intent כולל גם את הדגל הזה וגם את דגל הכוונה FLAG_ACTIVITY_REQUIRE_NON_BROWSER
, קריאה ל-startActivity()
תגרום להקפצת ActivityNotFoundException
כשמתקיים אחד מהתנאים הבאים:
- השיחה הייתה מפעילה את אפליקציית הדפדפן ישירות.
- במצב כזה, תוצג למשתמש תיבת דו-שיח עם הבהרה.
קטע הקוד הבא מראה איך להשתמש בדגלים FLAG_ACTIVITY_REQUIRE_NON_BROWSER
ו-FLAG_ACTIVITY_REQUIRE_DEFAULT
ביחד:
Kotlin
val url = URL_TO_LOAD try { // For this intent to be invoked, the system must directly launch a // non-browser app. val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply { addCategory(CATEGORY_BROWSABLE) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER or FLAG_ACTIVITY_REQUIRE_DEFAULT } startActivity(intent) } catch (e: ActivityNotFoundException) { // This code executes in one of the following cases: // 1. Only browser apps can handle the intent. // 2. The user has set a browser app as the default app. // 3. The user hasn't set any app as the default for handling this URL. openInCustomTabs(url) }
Java
String url = URL_TO_LOAD; try { // For this intent to be invoked, the system must directly launch a // non-browser app. Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); intent.addCategory(CATEGORY_BROWSABLE); intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER | FLAG_ACTIVITY_REQUIRE_DEFAULT); startActivity(intent); } catch (ActivityNotFoundException e) { // This code executes in one of the following cases: // 1. Only browser apps can handle the intent. // 2. The user has set a browser app as the default app. // 3. The user hasn't set any app as the default for handling this URL. openInCustomTabs(url); }
פתיחת קובץ
אם האפליקציה מטפלת בקבצים או בקבצים מצורפים, למשל בודקת אם מכשיר מסוים יכול לפתוח קובץ מסוים, בדרך כלל הכי קל לנסות להפעיל פעילות שיכולה לטפל בקובץ. כדי לעשות זאת, צריך להשתמש ב-Intent שכולל את פעולת ה-Intent ACTION_VIEW
ואת ה-URI שמייצג את הקובץ הספציפי. אם אין אפליקציה זמינה במכשיר, האפליקציה יכולה לקלוט את ActivityNotFoundException
. בלוגיקה לטיפול בחריגות, אפשר להציג שגיאה או לנסות לטפל בקובץ בעצמכם.
אם האפליקציה שלכם צריכה לדעת מראש אם אפליקציה אחרת יכולה לפתוח קובץ נתון, צריך לכלול את הרכיב <intent>
בקטע הקוד הבא כחלק מהרכיב <queries>
במניפסט. אם אתם כבר יודעים מהו סוג הקובץ בזמן הידור, כדאי לכלול אותו.
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.VIEW" /> <!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". --> <data android:mimeType="application/pdf" /> </intent>
לאחר מכן תוכלו לבדוק אם אפליקציה מסוימת זמינה על ידי קריאה ל-resolveActivity()
עם הכוונה שלכם.
הענקת גישה ל-URI
הערה: חובה להצהיר על הרשאות גישה ל-URI כפי שמתואר בקטע הזה באפליקציות שמטרגטות את Android 11 (רמת API 30) ואילך, ומומלץ לעשות זאת בכל האפליקציות, ללא קשר לגרסה של ערכת ה-SDK שמוגדרת כיעד וללא קשר לכך שהאפליקציות מייצאות את ספקי התוכן שלהן.
כדי שאפליקציות שמטרגטות ל-Android 11 ואילך יוכלו לגשת ל-URI של התוכן, ה-intent של האפליקציה צריך להצהיר על הרשאות גישה ל-URI על ידי הגדרת אחד או שני הדגלים הבאים של ה-intent: FLAG_GRANT_READ_URI_PERMISSION
ו-FLAG_GRANT_WRITE_URI_PERMISSION
.
ב-Android מגרסה 11 ואילך, הרשאות הגישה ל-URI מאפשרות לאפליקציה שמקבלת את ה-Intent את היכולות הבאות:
- לקרוא מהנתונים ש-URI התוכן מייצג או לכתוב אליהם, בהתאם להרשאות ה-URI הנתונות.
- לקבלת מידע על האפליקציה שמכילה את ספק התוכן שתואם לסמכות ה-URI. יכול להיות שהאפליקציה שמכילה את ספק התוכן שונה מהאפליקציה ששולחת את הכוונה.
קטע הקוד הבא מראה איך להוסיף דגל של כוונה להרשאות URI כדי שאפליקציה אחרת שמטרגטת Android 11 ואילך תוכל להציג את הנתונים ב-URI של התוכן:
Kotlin
val shareIntent = Intent(Intent.ACTION_VIEW).apply { flags = Intent.FLAG_GRANT_READ_URI_PERMISSION data = CONTENT_URI_TO_SHARE_WITH_OTHER_APP }
Java
Intent shareIntent = new Intent(Intent.ACTION_VIEW); shareIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION); shareIntent.setData(CONTENT_URI_TO_SHARE_WITH_OTHER_APP);
חיבור לשירותים
אם האפליקציה צריכה לקיים אינטראקציה עם שירות שלא גלוי באופן אוטומטי, אפשר להצהיר על פעולת הכוונה המתאימה בתוך אלמנט <queries>
. בקטעים הבאים מפורטות דוגמאות לשירותים נפוצים.
חיבור למנוע המרת טקסט לדיבור
אם האפליקציה שלכם יוצרת אינטראקציה עם מנוע המרה של טקסט לדיבור (TTS), צריך לכלול את הרכיב <intent>
כחלק מהרכיב <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.TTS_SERVICE" /> </intent>
התחברות לשירות של זיהוי דיבור
אם האפליקציה שלכם יוצרת אינטראקציה עם שירות זיהוי דיבור, צריך לכלול את הרכיב <intent>
כחלק מהרכיב <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.speech.RecognitionService" /> </intent>
חיבור לשירותי דפדפני מדיה
אם האפליקציה היא אפליקציית דפדפן מדיה של לקוח, צריך לכלול את האלמנט <intent>
הבא כחלק מהאלמנט <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.media.browse.MediaBrowserService" /> </intent>
לספק פונקציונליות מותאמת אישית
אם האפליקציה שלכם צריכה לבצע פעולות שניתן להתאים אישית או להציג מידע שניתן להתאים אישית על סמך האינטראקציות שלה עם אפליקציות אחרות, תוכלו לייצג את ההתנהגות המותאמת אישית הזו באמצעות חתימות של מסנני כוונות כחלק מהרכיב <queries>
במניפסט. בקטעים הבאים תוכלו למצוא הנחיות מפורטות לכמה תרחישים נפוצים.
שליחת שאילתה לאפליקציות SMS
אם האפליקציה שלכם זקוקה למידע על קבוצת אפליקציות ה-SMS שמותקנות במכשיר, למשל כדי לבדוק איזו אפליקציה היא הכלי המוגדר כברירת מחדל לטיפול ב-SMS במכשיר, צריך לכלול את הרכיב <intent>
הבא כחלק מהרכיב <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.SENDTO"/> <data android:scheme="smsto" android:host="*" /> </intent>
יצירת גיליון שיתוף בהתאמה אישית
כשאפשר, כדאי להשתמש בחלונית שיתוף שמספקת המערכת. לחלופין, אפשר לכלול את הרכיב <intent>
הבא כחלק מהרכיב <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.SEND" /> <!-- Replace with the MIME type that your app works with, if needed. --> <data android:mimeType="image/jpeg" /> </intent>
בכל מקרה אחר, התהליך של בניית גיליון השיתוף בלוגיקה של האפליקציה, כמו הקריאה ל-queryIntentActivities()
, נשאר ללא שינוי בהשוואה לגרסאות של Android שקודמות ל-Android 11.
הצגת פעולות מותאמות אישית לבחירת טקסט
כשמשתמשים בוחרים טקסט באפליקציה, סרגל הכלים לבחירת טקסט מציג את הפעולות שאפשר לבצע על הטקסט שנבחר. אם בסרגל הכלים הזה מוצגות פעולות בהתאמה אישית מאפליקציות אחרות, צריך לכלול את האלמנט <intent>
כחלק מהאלמנט <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.PROCESS_TEXT" /> <data android:mimeType="text/plain" /> </intent>
הצגת שורות של נתונים מותאמים אישית של איש קשר
אפליקציות יכולות להוסיף שורות נתונים בהתאמה אישית לספק אנשי הקשר. כדי שאפליקציית 'אנשי קשר' תציג את הנתונים המותאמים אישית, היא צריכה להיות מסוגלת לבצע את הפעולות הבאות:
- קוראים את הקובץ
contacts.xml
מהאפליקציות האחרות. - טוענים סמל שתואם לסוג ה-MIME המותאם אישית.
אם האפליקציה היא אפליקציית אנשי קשר, צריך לכלול את רכיבי <intent>
הבאים כחלק מהרכיב <queries>
במניפסט:
<!-- Place inside the <queries> element. --> <!-- Lets the app read the contacts.xml file from other apps. --> <intent> <action android:name="android.accounts.AccountAuthenticator" /> </intent> <!-- Lets the app load an icon corresponding to the custom MIME type. --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="content" android:host="com.android.contacts" android:mimeType="vnd.android.cursor.item/*" /> </intent>