کاربران عاشق تصاویر، ویدیوها و سایر محتوای رسا هستند، اما درج و جابجایی این محتوا در برنامهها همیشه آسان نیست. برای سادهتر کردن دریافت محتوای غنی برای برنامهها، اندروید ۱۲ (سطح API 31) یک API یکپارچه معرفی میکند که به برنامه شما اجازه میدهد محتوا را از هر منبعی بپذیرد: کلیپبورد، صفحهکلید یا کشیدن و رها کردن.
شما میتوانید یک رابط کاربری، مانند OnReceiveContentListener ، را به کامپوننتهای رابط کاربری متصل کنید و وقتی محتوا از طریق هر مکانیزمی وارد میشود، یک فراخوانی دریافت کنید. این فراخوانی به مکانی واحد برای کد شما تبدیل میشود تا دریافت همه محتوا، از متن ساده و استایلدار گرفته تا نشانهگذاری، تصاویر، ویدیوها، فایلهای صوتی و موارد دیگر را مدیریت کند.
برای سازگاری با نسخههای قبلی اندروید، این API در AndroidX نیز موجود است، از Core 1.7 و Appcompat 1.4 شروع میشود، که توصیه میکنیم هنگام پیادهسازی این قابلیت از آن استفاده کنید.
نمای کلی
با سایر APIهای موجود، هر مکانیزم رابط کاربری - مانند منوی لمسی و نگهداشتن یا کشیدن - API مربوط به خود را دارد. این بدان معناست که شما باید با هر API بهطور جداگانه ادغام شوید و کد مشابهی را برای هر مکانیزمی که محتوا را وارد میکند، اضافه کنید:
API OnReceiveContentListener با ایجاد یک API واحد برای پیادهسازی، این مسیرهای کد مختلف را تجمیع میکند، بنابراین میتوانید روی منطق خاص برنامه خود تمرکز کنید و اجازه دهید پلتفرم بقیه کارها را انجام دهد:
این رویکرد همچنین به این معنی است که وقتی روشهای جدیدی برای درج محتوا به پلتفرم اضافه میشوند، نیازی به ایجاد تغییرات اضافی در کد برای فعال کردن پشتیبانی در برنامه خود ندارید. و اگر برنامه شما نیاز به پیادهسازی سفارشیسازی کامل برای یک مورد استفاده خاص داشته باشد، همچنان میتوانید از APIهای موجود استفاده کنید که به همان روش کار میکنند.
پیادهسازی
این API یک رابط شنونده با یک متد واحد به نام OnReceiveContentListener است. برای پشتیبانی از نسخههای قدیمیتر پلتفرم اندروید، توصیه میکنیم از رابط OnReceiveContentListener منطبق در کتابخانه AndroidX Core استفاده کنید.
برای استفاده از API، شنونده (listener) را با مشخص کردن انواع محتوایی که برنامه شما میتواند مدیریت کند، پیادهسازی کنید:
کاتلین
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
جاوا
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
پس از مشخص کردن تمام انواع MIME محتوایی که برنامه شما پشتیبانی میکند، بقیه شنونده را پیادهسازی کنید:
کاتلین
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/*") } }
جاوا
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های محتوا دوباره استفاده کنید. دادههای باقیمانده را برگردانید تا مدیریت آن دادهها را به پلتفرم واگذار کنید.
پس از پیادهسازی شنونده، آن را روی عناصر رابط کاربری مناسب در برنامه خود تنظیم کنید:
کاتلین
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()) } }
جاوا
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 دریافت شده توسط شنونده (listener) داشته باشید تا اطمینان حاصل شود که مجوزها توسط پلتفرم به طور زودهنگام لغو نمیشوند.
نماهای سفارشی
اگر برنامه شما از یک زیرکلاس View سفارشی استفاده میکند، مراقب باشید که OnReceiveContentListener نادیده گرفته نشود.
اگر کلاس View شما متد onCreateInputConnection override میکند، از Jetpack API InputConnectionCompat.createWrapper برای پیکربندی InputConnection استفاده کنید.
اگر کلاس View شما متد onTextContextMenuItem override میکند، وقتی آیتم منو R.id.paste یا R.id.pasteAsPlainText است، آن را به super واگذار کنید.
مقایسه با API تصویر صفحه کلید
میتوانید API مربوط به OnReceiveContentListener را به عنوان نسخه بعدی API تصویر صفحه کلید موجود در نظر بگیرید. این API یکپارچه از عملکرد API تصویر صفحه کلید و همچنین برخی ویژگیهای اضافی پشتیبانی میکند. سازگاری دستگاه و ویژگیها بسته به اینکه از کتابخانه Jetpack یا APIهای بومی از Android SDK استفاده میکنید، متفاوت است.
| اقدام یا ویژگی | پشتیبانی شده توسط API تصویر صفحه کلید | پشتیبانی شده توسط API یکپارچه |
|---|---|---|
| از صفحه کلید وارد کنید | بله (سطح API 13 و بالاتر) | بله (سطح API 13 و بالاتر) |
| با استفاده از چسباندن از منوی لمس و نگه داشتن، درج کنید | خیر | بله |
| درج با استفاده از کشیدن و رها کردن | خیر | بله (سطح API 24 و بالاتر) |
| اقدام یا ویژگی | پشتیبانی شده توسط API تصویر صفحه کلید | پشتیبانی شده توسط API یکپارچه |
|---|---|---|
| از صفحه کلید وارد کنید | بله (سطح API 25 و بالاتر) | بله (اندروید ۱۲ و بالاتر) |
| با استفاده از چسباندن از منوی لمس و نگه داشتن، درج کنید | خیر | |
| با استفاده از کشیدن و رها کردن، درج کنید | خیر |