מילוי תרחישים לדוגמה נפוצים תוך חשיפה מוגבלת של חבילות

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

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

אם חלק מהאפליקציה שלכם תלוי בידיעה אם הקריאה ל-startActivity() יכולה להצליח, למשל הצגת ממשק משתמש, צריך להוסיף רכיב לרכיב <queries> במניפסט של האפליקציה. בדרך כלל זהו רכיב <intent>.

פתיחת כתובות URL

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

פתיחת כתובות URL בדפדפן או באפליקציה אחרת

כדי לפתוח כתובת URL, צריך להשתמש ב-Intent שמכיל את פעולת Intent מסוג ACTION_VIEW, כפי שמתואר במדריך לטעינת דפי אינטרנט כתובת URL. אחרי שמפעילים את startActivity() באמצעות הכוונה הזו, מתרחשת אחת מהאפשרויות הבאות:

  • כתובת ה-URL תיפתח באפליקציה של דפדפן אינטרנט.
  • כתובת האתר נפתחת באפליקציה שתומכת בכתובת האתר בתור קישור עומק .
  • תופיע תיבת דו-שיח להבחנה, שמאפשרת למשתמש לבחור את האפליקציה פותח את כתובת ה-URL.
  • מתרחשת ActivityNotFoundException כי לא מותקנת אפליקציה ב- המכשיר שיכול לפתוח את כתובת ה-URL. (זה חריג).

    מומלץ לאתר את הבעיה ActivityNotFoundException ולטפל בה באפליקציה אם היא מתרחשת.

כי השיטה 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() ומעבירים Intent באינטרנט כארגומנט, הרשימה שהוחזרה כוללת את אפליקציות הדפדפן הזמינות במקרים מסוימים. הרשימה לא כוללת אפליקציות דפדפן אם המשתמש הגדיר כברירת מחדל שכתובת ה-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() באמצעות כוונה שמגדירה FLAG_ACTIVITY_REQUIRE_NON_BROWSER סימון Intent. אם המערכת תחזיר את הערך ActivityNotFoundException, האפליקציה תוכל לפתוח את כתובת ה-URL בכרטיסייה מותאמת אישית.

אם הכוונה כוללת את הדגל הזה, קריאה ל-startActivity() תגרום להשלכת ActivityNotFoundException כשאחד מהתנאים הבאים מתקיים:

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

קטע הקוד הבא מראה איך לעדכן את הלוגיקה דגל Intent אחד (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.

אם הדגל הזה כולל את הסימון הזה של Intent, קריאה אל startActivity() גורמת להקפיץ את ActivityNotFoundException כשהשיחה הייתה מציגה תיבת דו-שיח של הבהרה למשתמש.

אם הכוונה כוללת גם את הדגל הזה וגם את דגל הכוונה 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 של התוכן, כוונת האפליקציה חייבת להצהיר על גישה ל-URI הרשאות על ידי הגדרה של אחד מהסימונים הבאים של Intent, או את שניהם: FLAG_GRANT_READ_URI_PERMISSION וגם FLAG_GRANT_WRITE_URI_PERMISSION.

ב-Android מגרסה 11 ואילך, הרשאות הגישה ל-URI מעניקות את היכולות הבאות לאפליקציה שמקבלת את הכוונה:

  • לקרוא מהנתונים ש-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);

קישור לשירותים

אם האפליקציה צריכה לקיים אינטראקציה עם שירות שאינו גלוי באופן אוטומטי, תוכלו להצהיר פעולת ה-Intent המתאימה בתוך רכיב <queries>. הקטעים הבאים מספקים דוגמאות באמצעות שירותים שניגשים אליהם לעיתים קרובות.

התחברות למנוע המרת טקסט לדיבור (TTS)

אם האפליקציה שלכם יוצרת אינטראקציה עם מנוע המרה של טקסט לדיבור (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>

הצגת שורות נתונים בהתאמה אישית לגבי איש קשר

אפליקציות יכולות להוסיף שורות נתונים בהתאמה אישית לספק אנשי הקשר. כדי שאפליקציית אנשי הקשר תוכל להציג את הנתונים המותאמים אישית האלה, היא צריכה להיות מסוגלת:

  1. לקרוא את הקובץ contacts.xml מאפליקציות אחרות.
  2. טוענים סמל שתואם לסוג ה-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>