משתמשים אוהבים תמונות, סרטונים ותוכן נוסף שמאפשר להם להביע את עצמם, אבל לא תמיד קל להוסיף תוכן כזה לאפליקציות ולהעביר אותו. כדי להקל על האפליקציות לקבל תוכן עשיר, ב-Android 12 (רמת API 31) מוצג ממשק API מאוחד שמאפשר לאפליקציה לקבל תוכן מכל מקור: הלוח, המקלדת או גרירה.
אפשר לצרף ממשק, כמו OnReceiveContentListener
, לרכיבי ממשק המשתמש ולקבל קריאה חוזרת (callback) כשתוכן מוכנס דרך מנגנון כלשהו. פונקציית ה-callback הופכת למקום היחיד שבו הקוד שלכם יכול לטפל בקבלת כל התוכן, החל מטקסט פשוט ועד לטקסט עם עיצוב, רכיבי Markup, תמונות, סרטונים, קובצי אודיו ועוד.
כדי לשמור על תאימות לאחור לגרסאות קודמות של Android, ממשק ה-API הזה זמין גם ב-AndroidX, החל מ-Core 1.7 ו-Appcompat 1.4. מומלץ להשתמש בהם כשמטמיעים את הפונקציונליות הזו.
סקירה כללית
בממשקי API קיימים אחרים, לכל מנגנון בממשק המשתמש – כמו תפריט לחיצה ארוכה או גרירה – יש ממשק API תואם משלו. כלומר, צריך לשלב עם כל API בנפרד, ולהוסיף קוד דומה לכל מנגנון להוספת תוכן:
ממשק ה-API של OnReceiveContentListener
מביא לידי ביטוי את נתיבי הקוד השונים האלה על ידי יצירת API יחיד להטמעה, כך שתוכלו להתמקד בלוגיקה הספציפית לאפליקציה שלכם ולתת לפלטפורמה לטפל בשאר הדברים:
הגישה הזו גם מאפשרת להוסיף לפלטפורמה דרכים חדשות להוספת תוכן בלי לבצע שינויים נוספים בקוד כדי להפעיל תמיכה באפליקציה. אם אתם צריכים להטמיע באפליקציה התאמה אישית מלאה לתרחיש לדוגמה מסוים, עדיין תוכלו להשתמש בממשקי ה-API הקיימים, שימשיכו לפעול באותו אופן.
הטמעה
ה-API הוא ממשק של מאזין עם method יחיד, OnReceiveContentListener
.
כדי לתמוך בגרסאות ישנות יותר של פלטפורמת Android, מומלץ להשתמש בממשק התואם OnReceiveContentListener
בספריית AndroidX Core.
כדי להשתמש ב-API, מטמיעים את המאזין ומציינים את סוגי התוכן שהאפליקציה יכולה לטפל בהם:
Kotlin
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
אחרי שמציינים את כל סוגי ה-MIME של התוכן שהאפליקציה תומכת בהם, מטמיעים את שאר הקוד של הבורר:
Kotlin
class MyReceiver : OnReceiveContentListener { override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat { val split = contentInfo.partition { item: ClipData.Item -> item.uri != null } val uriContent = split.first val remaining = split.second if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining } companion object { val MIME_TYPES = arrayOf("image/*", "video/*") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; @Override public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) { Pairsplit = contentInfo.partition( item -> item.getUri() != null); ContentInfo uriContent = split.first; ContentInfo remaining = split.second; if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining; } }
אם האפליקציה שלכם כבר תומכת בשיתוף באמצעות כוונות, תוכלו לעשות שימוש חוזר בלוגיקה הספציפית לאפליקציה לטיפול ב-URI של תוכן. מחזירים את כל הנתונים הנותרים כדי להעביר את הטיפול בהם לפלטפורמה.
אחרי שמטמיעים את המאזין, מגדירים אותו ברכיבי ממשק המשתמש המתאימים באפליקציה:
Kotlin
class MyActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... val myInput = findViewById(R.id.my_input) ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver()) } }
Java
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { // ... AppCompatEditText myInput = findViewById(R.id.my_input); ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver()); } }
הרשאות URI
המערכת מעניקה ומבטלת באופן אוטומטי הרשאות קריאה לכל מזהי URI של תוכן בתוכן הייעודי (payload) שמוענק ל-OnReceiveContentListener
.
בדרך כלל, האפליקציה מעבדת מזהי URI של תוכן בשירות או בפעילות. לעיבוד ממושך, השתמשו ב-WorkManager. כשמפעילים את התכונה הזו, צריך להעביר את התוכן באמצעות Intent.setClipData
ולהגדיר את הדגל FLAG_GRANT_READ_URI_PERMISSION
כדי להרחיב את ההרשאות לשירות או לפעילות היעד.
לחלופין, אפשר להשתמש בשרשור רקע בהקשר הנוכחי כדי לעבד את התוכן. במקרה כזה, צריך לשמור על הפניה לאובייקט payload
שהאזין קיבל כדי לוודא שהפלטפורמה לא תבטל את ההרשאות לפני הזמן.
תצוגות מותאמות אישית
אם באפליקציה שלכם נעשה שימוש בתת-סוג View
בהתאמה אישית, חשוב לוודא שלא מתבצעת עקיפה של OnReceiveContentListener
.
אם בכיתה View
מוגדר שינוי מברירת המחדל של השיטה onCreateInputConnection
, צריך להשתמש ב-Jetpack API InputConnectionCompat.createWrapper
כדי להגדיר את InputConnection
.
אם בכיתה View
מתבצעת החלפה של השיטה onTextContextMenuItem
, מעבירים את הטיפול ל-super כשפריט התפריט הוא R.id.paste
או R.id.pasteAsPlainText
.
השוואה ל-Keyboard Image API
אפשר להתייחס ל-API OnReceiveContentListener
כגרסה הבאה של ממשק ה-API הקיים לתמונות של מקלדת. ממשק ה-API המאוחד תומך בפונקציונליות של ממשק ה-API של התמונה של המקלדת, וגם בתכונות נוספות. תאימות המכשירים והתכונות משתנה בהתאם לשימוש בספריית Jetpack או בממשקי ה-API המקוריים מ-Android SDK.
פעולה או תכונה | נתמך על ידי ממשק API של תמונה של מקלדת | נתמכים על ידי API מאוחד |
---|---|---|
הוספה מהמקלדת | כן (רמת API 13 ואילך) | כן (רמת API 13 ואילך) |
הוספה באמצעות הדבקה מהתפריט של הלחיצה הארוכה | לא | כן |
הוספה באמצעות גרירה ושחרור | לא | כן (רמת API 24 ואילך) |
פעולה או תכונה | נתמך על ידי ממשק API של תמונה של מקלדת | נתמכים על ידי API מאוחד |
---|---|---|
הוספה מהמקלדת | כן (רמת API 25 ואילך) | כן (Android מגרסה 12 ואילך) |
הוספה באמצעות הדבקה מהתפריט של הלחיצה הארוכה | לא | |
הוספה באמצעות גרירה ושחרור | לא |