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

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

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

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

קטע הקוד הבא מדגים איך להוסיף דגל Intent להרשאות של 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>

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

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

  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>