המשתמשים אוהבים תמונות, סרטונים ותוכן אחר בעל אופי אקספרסיבי, אבל לא תמיד קל להעביר את התוכן הזה באפליקציות. כדי להקל על אפליקציות מקבלים תוכן עשיר, גרסת Android 12 (רמת API 31) מציגה ממשק API מאוחד מאפשר לאפליקציה לקבל תוכן מכל מקור: לוח, מקלדת או גרירה.
אפשר לצרף ממשק,
OnReceiveContentListener
לרכיבי ממשק משתמש ולקבל קריאה חוזרת כשתוכן מוכנס דרך
על מנגנוני תשומת לב. הקריאה החוזרת (callback) הופכת למקום היחיד שבו הקוד שלך מטפל
לקבל את כל התוכן, החל מטקסט פשוט ומסוגנן ועד לתגי עיצוב, תמונות, סרטונים,
קובצי אודיו ואחרים.
לצורך תאימות לאחור עם גרסאות Android קודמות, ה-API הזה זמין ב-AndroidX, החל מ- Core 1.7 ו- Appcompat 1.4, שבו מומלץ להשתמש כאשר מטמיעים את הפונקציונליות הזו.
סקירה כללית
ב-APIs קיימים אחרים, כל מנגנון בממשק המשתמש - כמו לחיצה ארוכה על הלחצן או גרירה - יש ממשק API תואם משלו. כלומר, אתם צריכים לשלב כל API בנפרד, ולהוסיף קוד דומה לכל מנגנון מוסיפה תוכן:
ב-API OnReceiveContentListener
, מאחדים את נתיבי הקוד השונים האלה:
יצירת ממשק API אחד להטמעה, כדי שתוכלו להתמקד בלוגיקה הספציפית לאפליקציה
והפלטפורמה תטפל בכל השאר:
משמעות הגישה הזו גם היא שכשנוספים דרכים חדשות להוספת תוכן אין צורך לבצע שינויים נוספים בקוד כדי להפעיל את התמיכה. באפליקציה. ואם האפליקציה צריכה ליישם התאמה אישית מלאה מסוים, אפשר עדיין להשתמש בממשקי ה-API הקיימים, שממשיכים לפעול כמעט באותה הדרך.
הטמעה
ה-API הוא ממשק האזנה עם שיטה אחת,
OnReceiveContentListener
כדי לתמוך בגרסאות ישנות של פלטפורמת Android, מומלץ להשתמש
תואם
OnReceiveContentListener
בספריית AndroidX Core.
כדי להשתמש ב-API, מטמיעים את ה-listener על ידי ציון סוגי התוכן האפליקציה יכולה לטפל ב:
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 של תוכן. החזרת הנתונים שנותרו אל להעביר את הטיפול בנתונים האלה לפלטפורמה.
אחרי הטמעת ה-listener, מגדירים אותו ברכיבי ממשק המשתמש המתאימים ב- האפליקציה שלך:
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
התקבל על ידי ה-listen כדי לוודא שההרשאות לא
בוטלו מוקדם על ידי הפלטפורמה.
תצוגות מותאמות אישית
אם באפליקציה שלך נעשה שימוש במחלקה משנית מותאמת אישית של View
, צריך לוודא
לא ניתן לעקוף את OnReceiveContentListener
.
אם הכיתה View
מבטלת את
onCreateInputConnection
צריך להשתמש ב-Jetpack API
InputConnectionCompat.createWrapper
כדי להגדיר את InputConnection
.
אם הכיתה View
מבטלת את
onTextContextMenuItem
method, הענקת גישה ל-Super כאשר האפשרות בתפריט
R.id.paste
או
R.id.pasteAsPlainText
.
השוואה לממשק ה-API של תמונות במקלדת
אפשר לחשוב על API OnReceiveContentListener
בתור הגרסה הבאה של
הממשק API הקיים של תמונת המקלדת. הגרסה המאוחדת
ה-API תומך בפונקציונליות של ממשק ה-API של תמונת המקלדת
תכונות נוספות. התאימות של מכשירים ותכונות משתנה בהתאם
בין אם אתם משתמשים בספריית Jetpack או בממשקי ה-API המקוריים מ-Android SDK.
פעולה או תכונה | נתמך על ידי ממשק ה-API של תמונת המקלדת | תמיכה באמצעות API מאוחד |
---|---|---|
הוספה מהמקלדת | כן (רמת API 13 ומעלה) | כן (רמת API 13 ומעלה) |
הוספה באמצעות הדבקה ממגע & לחיצה ארוכה על הלחצן | לא | כן |
הוספה באמצעות גרירה ושחרור | לא | כן (רמת API 24 ומעלה) |
פעולה או תכונה | נתמך על ידי ממשק ה-API של תמונת המקלדת | תמיכה באמצעות API מאוחד |
---|---|---|
הוספה מהמקלדת | כן (רמת API 25 ומעלה) | כן (Android 12 ואילך) |
הוספה באמצעות הדבקה ממגע & לחיצה ארוכה על הלחצן | לא | |
הוספה באמצעות גרירה ושחרור | לא |