קבלת תוכן עשיר

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

המשתמשים אוהבים תמונות, סרטונים ותוכן אחר בעל אופי אקספרסיבי, אבל לא תמיד קל להעביר את התוכן הזה באפליקציות. כדי להקל על אפליקציות מקבלים תוכן עשיר, גרסת Android 12 (רמת API 31) מציגה ממשק API מאוחד מאפשר לאפליקציה לקבל תוכן מכל מקור: לוח, מקלדת או גרירה.

אפשר לצרף ממשק, OnReceiveContentListener לרכיבי ממשק משתמש ולקבל קריאה חוזרת כשתוכן מוכנס דרך על מנגנוני תשומת לב. הקריאה החוזרת (callback) הופכת למקום היחיד שבו הקוד שלך מטפל לקבל את כל התוכן, החל מטקסט פשוט ומסוגנן ועד לתגי עיצוב, תמונות, סרטונים, קובצי אודיו ואחרים.

לצורך תאימות לאחור עם גרסאות Android קודמות, ה-API הזה זמין ב-AndroidX, החל מ- Core 1.7 ו- Appcompat 1.4, שבו מומלץ להשתמש כאשר מטמיעים את הפונקציונליות הזו.

סקירה כללית

ב-APIs קיימים אחרים, כל מנגנון בממשק המשתמש - כמו לחיצה ארוכה על הלחצן או גרירה - יש ממשק API תואם משלו. כלומר, אתם צריכים לשלב כל API בנפרד, ולהוסיף קוד דומה לכל מנגנון מוסיפה תוכן:

תמונה שבה מוצגות הפעולות השונות וה-API היחסי להטמעה
איור 2. בעבר, אפליקציות הטמיעו ממשק API שונה לכל ממשק משתמש מנגנון להוספת תוכן.

ב-API OnReceiveContentListener, מאחדים את נתיבי הקוד השונים האלה: יצירת ממשק API אחד להטמעה, כדי שתוכלו להתמקד בלוגיקה הספציפית לאפליקציה והפלטפורמה תטפל בכל השאר:

תמונה שמציגה את ממשק ה-API המאוחד פשוט
איור 3. ממשק API מאוחד מאפשר לך ליישם ממשק 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) {
         Pair<ContentInfoCompat, ContentInfoCompat> split = 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.

טבלה 1. תכונות ורמות API שנתמכות עבור תרמיל ריחוף.
פעולה או תכונה נתמך על ידי ממשק ה-API של תמונת המקלדת תמיכה באמצעות API מאוחד
הוספה מהמקלדת כן (רמת API 13 ומעלה) כן (רמת API 13 ומעלה)
הוספה באמצעות הדבקה ממגע & לחיצה ארוכה על הלחצן לא כן
הוספה באמצעות גרירה ושחרור לא כן (רמת API 24 ומעלה)
טבלה 2. תכונות נתמכות ורמות API נתמכות עבור מודעות מותאמות מממשקי API.
פעולה או תכונה נתמך על ידי ממשק ה-API של תמונת המקלדת תמיכה באמצעות API מאוחד
הוספה מהמקלדת כן (רמת API 25 ומעלה) כן (Android 12 ואילך)
הוספה באמצעות הדבקה ממגע & לחיצה ארוכה על הלחצן לא
הוספה באמצעות גרירה ושחרור לא