غالبًا ما يرغب المستخدمون في التواصل باستخدام الرموز التعبيرية والملصقات والأنواع الأخرى من المحتوى الغني. في إصدارات Android السابقة، كان بإمكان لوحات المفاتيح اللينة، المعروفة أيضًا باسم أدوات تحرير أسلوب الإدخال، أو أدوات IME، إرسال رموز Unicode التعبيرية فقط إلى التطبيقات. بالنسبة إلى المحتوى الغني، أنشأت التطبيقات واجهات برمجة تطبيقات خاصة بالتطبيقات لا يمكن استخدامها في تطبيقات أخرى أو استخدمت حلولاً بديلة، مثل إرسال الصور من خلال إجراء مشاركة بسيط أو الحافظة.
بدءًا من الإصدار 7.1 من نظام التشغيل Android (المستوى 25 من واجهة برمجة التطبيقات)، تتضمّن حزمة تطوير البرامج (SDK) لنظام التشغيل Android واجهة برمجة التطبيقات Commit Content API التي توفّر طريقة شاملة يمكن من خلالها لمستخدمي أسلوب الإدخال (IME) إرسال الصور والمحتوى الوافي الآخر مباشرةً إلى محرِّر نصوص في أحد التطبيقات. تتوفّر واجهة برمجة التطبيقات أيضًا في الإصدار 13 من مكتبة الدعم اعتبارًا من الإصدار 25.0.0. ننصح باستخدام مكتبة الدعم لأنها تحتوي على طرق مساعِدة تبسّط عملية التنفيذ.
باستخدام واجهة برمجة التطبيقات هذه، يمكنك إنشاء تطبيقات مراسلة تقبل المحتوى الوافي من أي لوحة مفاتيح، بالإضافة إلى لوحات مفاتيح يمكنها إرسال محتوى وافٍ إلى أي تطبيق. تتوافق لوحة مفاتيح Google وتطبيقات مثل الرسائل من Google مع Commit Content API في الإصدار 7.1 من نظام التشغيل Android، كما هو موضّح في الشكل 1.
يعرض هذا المستند كيفية تنفيذ Commit Content API في كل من أدوات IME والتطبيقات.
طريقة العمل
يتطلب إدراج صورة لوحة المفاتيح مشاركة من أداة IME والتطبيق. ويصف التسلسل التالي كل خطوة في عملية إدراج الصور:
عندما ينقر المستخدم على
EditText
، يرسل المحرِّر قائمة بأنواع محتوى MIME التي يقبلها فيEditorInfo.contentMimeTypes
.تقرأ أداة IME قائمة الأنواع المتوافقة وتعرض المحتوى في لوحة المفاتيح الإلكترونية التي يمكن للمحرر قبولها.
عندما يختار المستخدم صورة، تستدعي أداة IME
commitContent()
وترسلInputContentInfo
إلى المحرر. تشبه استدعاءcommitContent()
طلبcommitText()
، ولكنّه يتضمن محتوًى وافيًا. يحتويInputContentInfo
على عنوان URI يحدّد المحتوى في موفّر المحتوى.
يوضح الشكل 2 هذه العملية:
إتاحة الصور في التطبيقات
لقبول المحتوى المنسَّق من أدوات IME، يجب أن يُطلع التطبيق أدوات IME على أنواع المحتوى التي يقبلها، وأن يحدد طريقة لرد الاتصال يتم تنفيذها عند تلقي المحتوى.
يوضّح المثال التالي كيفية إنشاء سمة EditText
تقبل صور PNG:
Kotlin
var editText: EditText = object : EditText(this) { override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection { var ic = super.onCreateInputConnection(outAttrs) EditorInfoCompat.setContentMimeTypes(outAttrs, arrayOf("image/png")) val mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this) if (mimeTypes != null) { EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes) ic = InputConnectionCompat.createWrapper(this, ic, outAttrs) } return ic } }
Java
EditText editText = new EditText(this) { @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { InputConnection ic = super.onCreateInputConnection(outAttrs); EditorInfoCompat.setContentMimeTypes(outAttrs, new String[]{"image/png"}); String[] mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this); if (mimeTypes != null) { EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes); ic = InputConnectionCompat.createWrapper(this, ic, outAttrs); } return ic; } };
فيما يلي المزيد من التوضيح:
يستخدم هذا المثال مكتبة Support Library، لذا هناك بعض الإشارات إلى العنصر
android.support.v13.view.inputmethod
بدلاً منandroid.view.inputmethod
.ينشئ هذا المثال
EditText
ويلغي طريقةonCreateInputConnection(EditorInfo)
لتعديلInputConnection
. وInputConnection
هي قناة الاتصال بين أداة IME والتطبيق الذي يستقبل مدخلاته.تحافظ المكالمة
super.onCreateInputConnection()
على السلوك المضمّن، أي إرسال الرسائل النصية واستلامها، وإعطائك إشارة إلىInputConnection
.يضيف
setContentMimeTypes()
قائمة بأنواع MIME المتوافقة إلىEditorInfo
. يُرجى الاتصال بـsuper.onCreateInputConnection()
قبلsetContentMimeTypes()
.يتم تنفيذ
callback
عندما تنفذ أداة IME المحتوى. تتضمّن الطريقةonCommitContent()
مرجعًا إلىInputContentInfoCompat
، الذي يحتوي على معرّف موارد منتظم (URI) للمحتوى.- يمكنك طلب الأذونات وإصدارها إذا كان تطبيقك يعمل على المستوى 25 من واجهة برمجة التطبيقات
أو مستوى أعلى، وتم ضبط العلامة
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
من خلال أداة IME. بخلاف ذلك، يمكنك الوصول إلى معرّف الموارد المنتظم (URI) للمحتوى لأنّه تم منحه من خلال أداة IME أو لأنّ مزود المحتوى لا يحظر الوصول. ولمزيد من المعلومات، يُرجى الاطّلاع على إضافة دعم الصور إلى أدوات IME.
- يمكنك طلب الأذونات وإصدارها إذا كان تطبيقك يعمل على المستوى 25 من واجهة برمجة التطبيقات
أو مستوى أعلى، وتم ضبط العلامة
createWrapper()
يتضمنInputConnection
وقيمةEditorInfo
المعدَّلة ومعاودة الاتصال فيInputConnection
جديد وتعرضها.
في ما يلي الممارسات المقترَحة:
إنّ المحرِّرين الذين لا يوفّرون المحتوى الوافي لا يتصلون بالرمز
setContentMimeTypes()
، ويتركونEditorInfo.contentMimeTypes
مضبوطة علىnull
.يتجاهل المحرِّرون المحتوى إذا كان نوع MIME المحدّد في
InputContentInfo
لا يتطابق مع أي من الأنواع التي يقبلونها.لا يؤثر المحتوى الغني بموضع مؤشر النص ولا يتأثر به. يمكن للمحررين تجاهل موضع المؤشر عند التعامل مع المحتوى.
في طريقة
OnCommitContentListener.onCommitContent()
في المحرِّر، يمكنك عرضtrue
بشكل غير متزامن، حتى قبل تحميل المحتوى.على عكس النص الذي يمكن تعديله في أداة IME قبل استخدامه، يتم الالتزام بالمحتوى الوافي على الفور. إذا كنت ترغب في السماح للمستخدمين بتعديل المحتوى أو حذفه، فنفِّذ المنطق بنفسك.
لاختبار تطبيقك، تأكد من احتواء الجهاز أو المحاكي على لوحة مفاتيح يمكنها إرسال محتوى وافٍ. يمكنك استخدام لوحة مفاتيح Google في الإصدار Android 7.1 أو الإصدارات الأحدث.
إضافة دعم الصور إلى أدوات IME
على أدوات IME التي تريد إرسال محتوى وافٍ إلى التطبيقات تنفيذ Commit Content API، كما هو موضّح في المثال التالي:
- إلغاء
onStartInput()
أوonStartInputView()
وقراءة قائمة أنواع المحتوى المتوافقة من المحرر المستهدف. يعرض مقتطف الرمز التالي كيفية التحقق مما إذا كان المحرر المستهدف يقبل صور GIF أم لا.
Kotlin
override fun onStartInputView(editorInfo: EditorInfo, restarting: Boolean) { val mimeTypes: Array<String> = EditorInfoCompat.getContentMimeTypes(editorInfo) val gifSupported: Boolean = mimeTypes.any { ClipDescription.compareMimeTypes(it, "image/gif") } if (gifSupported) { // The target editor supports GIFs. Enable the corresponding content. } else { // The target editor doesn't support GIFs. Disable the corresponding // content. } }
Java
@Override public void onStartInputView(EditorInfo info, boolean restarting) { String[] mimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo); boolean gifSupported = false; for (String mimeType : mimeTypes) { if (ClipDescription.compareMimeTypes(mimeType, "image/gif")) { gifSupported = true; } } if (gifSupported) { // The target editor supports GIFs. Enable the corresponding content. } else { // The target editor doesn't support GIFs. Disable the corresponding // content. } }
- تفعيل المحتوى في التطبيق عندما يختار المستخدم صورة تجنَّب طلب الرمز
commitContent()
عندما يتم إنشاء أي نص، لأنّ ذلك قد يؤدي إلى فقدان التركيز على المحرِّر. يوضح مقتطف التعليمة البرمجية التالي كيفية التقاط صورة GIF.
Kotlin
// Commits a GIF image. // @param contentUri = Content URI of the GIF image to be sent. // @param imageDescription = Description of the GIF image to be sent. fun commitGifImage(contentUri: Uri, imageDescription: String) { val inputContentInfo = InputContentInfoCompat( contentUri, ClipDescription(imageDescription, arrayOf("image/gif")), null ) val inputConnection = currentInputConnection val editorInfo = currentInputEditorInfo var flags = 0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { flags = flags or InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION } InputConnectionCompat.commitContent(inputConnection, editorInfo, inputContentInfo, flags, null) }
Java
// Commits a GIF image. // @param contentUri = Content URI of the GIF image to be sent. // @param imageDescription = Description of the GIF image to be sent. public static void commitGifImage(Uri contentUri, String imageDescription) { InputContentInfoCompat inputContentInfo = new InputContentInfoCompat( contentUri, new ClipDescription(imageDescription, new String[]{"image/gif"}), null ); InputConnection inputConnection = getCurrentInputConnection(); EditorInfo editorInfo = getCurrentInputEditorInfo(); Int flags = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { flags |= InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION; } InputConnectionCompat.commitContent( inputConnection, editorInfo, inputContentInfo, flags, null); }
بصفتك مؤلف أداة IME، ستحتاج على الأرجح إلى تنفيذ موفر المحتوى التابع لك للرد على طلبات معرّف الموارد المنتظم (URI) للمحتوى. يُستثنى من ذلك إذا كان محرر أسلوب الإدخال (IME) لديك يتيح استخدام المحتوى من
مزودي المحتوى الحاليين مثل
MediaStore
. للحصول على معلومات عن إنشاء موفّري المحتوى، يُرجى الاطّلاع على مستندات موفّر المحتوى وموفِّر الملفات.
في حال إنشاء موفّر محتوى خاص بك، ننصحك بعدم تصديره
من خلال ضبط
android:exported
على
false
. بدلاً من ذلك، عليك تفعيل ميزة منح الأذونات في مقدّم الخدمة من خلال ضبط android:grantUriPermission
على true
. وبعد ذلك، يمكن لأداة IME منح أذونات الوصول إلى معرّف الموارد المنتظم للمحتوى (URI) للمحتوى الذي يتم الالتزام به. ثمة طريقتان لتنفيذ هذا الإجراء:
في نظام التشغيل Android 7.1 (المستوى 25 لواجهة برمجة التطبيقات) والإصدارات الأحدث، اضبط معلَمة العلامة على
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
عند طلب البيانات منcommitContent()
. بعد ذلك، يمكن لكائنInputContentInfo
الذي يتلقّاه التطبيق طلب أذونات قراءة مؤقتة وإصدارها من خلال استدعاءrequestPermission()
وreleasePermission()
.في نظام التشغيل Android 7.0 (مستوى واجهة برمجة التطبيقات 24) والإصدارات الأقدم، يتم تجاهل
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
، لذا عليك منح الإذن يدويًا بالمحتوى. يمكنك إجراء ذلك باستخدامgrantUriPermission()
، ولكن يمكنك تنفيذ آلية خاصة بك تلبّي متطلباتك.
لاختبار أداة IME، تأكد من أن جهازك أو المحاكي به تطبيق يمكنه تلقي محتوى وافٍ. يمكنك استخدام تطبيق مراسلة Google في الإصدار Android 7.1 أو الإصدارات الأحدث.