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

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

הימנעות מתיבת דו-שיח עם הבהרה

אם רוצים להימנע מהצגת תיבת דו-שיח של הבהרה, שמוצגת למשתמשים הם פותחים כתובת אתר, ובמקום זאת מעדיפים לטפל בכתובת האתר בעצמכם יכולים להשתמש בכוונה שמגדירה FLAG_ACTIVITY_REQUIRE_DEFAULT סימון Intent.

אם הדגל הזה כולל את הסימון הזה של 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);

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

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