Kullanıcılar genellikle emoji, çıkartma ve diğer zengin içerik türlerini kullanarak iletişim kurmak isterler. Android'in önceki sürümlerinde, giriş yöntemi düzenleyicileri veya IME'ler olarak da bilinen sanal klavyeler uygulamalara yalnızca Unicode emojileri gönderebiliyordu. Zengin içerikler için uygulamalar, diğer uygulamalarda kullanılamayan, uygulamaya özel API'ler oluşturdu veya basit paylaşım işlemi ya da pano aracılığıyla resim gönderme gibi geçici çözümler kullandı.
Android 7.1'den (API düzeyi 25) başlayarak Android SDK'da, IME'lerin resimleri ve diğer zengin içeriği doğrudan uygulamadaki bir metin düzenleyiciye göndermesi için evrensel bir yol sunan Commit Content API bulunur. API, 25.0.0 düzeltmesinden itibaren v13 Destek Kitaplığı'nda da mevcuttur. Uygulamayı basitleştiren yardımcı yöntemler içerdiğinden Destek Kitaplığı'nı kullanmanızı öneririz.
Bu API'yi kullanarak herhangi bir klavyeden zengin içeriği kabul eden mesajlaşma uygulamaları ve herhangi bir uygulamaya zengin içerik gönderebilen klavyeler oluşturabilirsiniz. Google Klavye ve Google'dan Mesajlar gibi uygulamalar, Android 7.1'de Commit Content API'yi destekler. Şekil 1'de gösterildiği gibi.
Bu dokümanda, Commit Content API'nin hem IME'lerde hem de uygulamalarda nasıl uygulanacağı gösterilmektedir.
Nasıl çalışır?
Klavyeden resim ekleme için IME'den ve uygulamadan katılım gerekir. Aşağıdaki sırada, resim ekleme sürecindeki her adım açıklanmaktadır:
Kullanıcı bir
EditText
simgesine dokunduğunda düzenleyici,EditorInfo.contentMimeTypes
'te kabul ettiği MIME içerik türlerinin listesini gönderir.IME, desteklenen türlerin listesini okur ve düzenleyicinin kabul edebileceği içeriği klavyede görüntüler.
Kullanıcı bir resim seçtiğinde, IME
commitContent()
numarasını arar ve düzenleyiciye birInputContentInfo
gönderir.commitContent()
çağrısı,commitText()
çağrısına benzer ancak zengin içerik içindir.InputContentInfo
, bir içerik sağlayıcıdaki içeriği tanımlayan bir URI içerir.
Bu süreç Şekil 2'de gösterilmektedir:
Uygulamalara resim desteği ekleme
Uygulamaların, IME'lerden zengin içerikleri kabul etmek için hangi içerik türlerini kabul ettiğini IME'lere bildirmesi ve içerik alındığında yürütülecek bir geri çağırma yöntemini belirtmesi gerekir.
Aşağıdaki örnekte, PNG resimleri kabul eden bir EditText
öğesinin nasıl oluşturulacağı gösterilmektedir:
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; } };
Aşağıda daha ayrıntılı bir açıklama bulabilirsiniz:
Bu örnekte Destek Kitaplığı kullanıldığı için
android.view.inputmethod
yerine bazıandroid.support.v13.view.inputmethod
referansları bulunmaktadır.Bu örnek bir
EditText
oluşturur veInputConnection
öğesini değiştirmek içinonCreateInputConnection(EditorInfo)
yöntemini geçersiz kılar.InputConnection
, IME ile girişini alan uygulama arasındaki iletişim kanalıdır.super.onCreateInputConnection()
çağrısı, metin gönderme ve alma gibi yerleşik davranışı korur ve sizeInputConnection
için bir referans sunar.setContentMimeTypes()
,EditorInfo
öğesine desteklenen MIME türlerinin listesini ekler.setContentMimeTypes()
tarihinden öncesuper.onCreateInputConnection()
numaralı telefonu arayın.IME her içeriği kaydettiğinde
callback
yürütülür.onCommitContent()
yöntemi, içerik URI'si içerenInputContentInfoCompat
referansına sahiptir.- Uygulamanız API düzeyi 25 veya sonraki bir sürümde çalışıyorsa ve
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
işareti IME tarafından ayarlanmışsa izinleri isteyin ve yayınlayın. Aksi takdirde, IME tarafından verildiğinden veya içerik sağlayıcının erişimi kısıtlamadığından içerik URI'sına zaten erişebilirsiniz. Daha fazla bilgi için IME'lere resim desteği ekleme başlıklı makaleye bakın.
- Uygulamanız API düzeyi 25 veya sonraki bir sürümde çalışıyorsa ve
createWrapper()
;InputConnection
, değiştirilenEditorInfo
ve geri çağırmayı yeni birInputConnection
öğesine sarmalar ve bunu döndürür.
Önerilen uygulamalar şunlardır:
Zengin içeriği desteklemeyen düzenleyiciler
setContentMimeTypes()
çağrısı yapmaz veEditorInfo.contentMimeTypes
değerlerininull
değerine ayarlı olarak bırakır.InputContentInfo
politikasında belirtilen MIME türü, kabul ettikleri türlerin hiçbiriyle eşleşmiyorsa düzenleyiciler içeriği yoksayar.Zengin içerik, metin imlecinin konumunu etkilemez ve etkilenmez. Düzenleyiciler, içerikle çalışırken imleç konumunu yoksayabilir.
Düzenleyicinin
OnCommitContentListener.onCommitContent()
yönteminde, içeriği yüklemeden önce biletrue
öğesini eşzamansız olarak döndürebilirsiniz.Taahhütte bulunmadan önce IME'de düzenlenebilen metnin aksine zengin içerik hemen aktarılır. Kullanıcıların içeriği düzenlemesine veya silmesine izin vermek istiyorsanız mantığı kendiniz uygulayın.
Uygulamanızı test etmek için cihazınızda veya emülatörünüzde zengin içerik gönderebilen bir klavye bulunduğundan emin olun. Google Klavye'yi Android 7.1 veya sonraki sürümlerde kullanabilirsiniz.
IME'lere resim desteği ekleme
Uygulamalara zengin içerik göndermek isteyen IME'ler, aşağıdaki örnekte gösterildiği gibi Commit Content API'yi uygulamalıdır:
onStartInput()
veyaonStartInputView()
değerlerini geçersiz kılın ve hedef düzenleyiciden desteklenen içerik türlerinin listesini okuyun. Aşağıdaki kod snippet'i, hedef düzenleyicinin GIF resimleri kabul edip etmediğini nasıl kontrol edeceğinizi gösterir.
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. } }
- Kullanıcı bir resim seçtiğinde içeriği uygulamaya kaydedin. Düzenleyicinin odağını kaybetmesine neden olabileceğinden metin oluşturulurken
commitContent()
çağrısı yapmaktan kaçının. Aşağıdaki kod snippet'inde bir GIF resminin nasıl kaydedileceği gösterilmektedir.
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); }
Bir IME yazarı olarak, içerik URI'si isteklerine yanıt vermek için büyük olasılıkla kendi içerik sağlayıcınızı uygulamanız gerekir. Bunun istisnası, IME'nizin MediaStore
gibi mevcut içerik sağlayıcıların içeriklerini desteklemesidir. İçerik sağlayıcıları oluşturma hakkında bilgi için içerik sağlayıcı ve dosya sağlayıcı dokümanlarına bakın.
Kendi içerik sağlayıcınızı oluşturuyorsanız android:exported
öğesini false
değerine ayarlayarak dışa aktarmamanızı öneririz. Bunun yerine, android:grantUriPermission
öğesini true
değerine ayarlayarak sağlayıcıda izin vermeyi etkinleştirin. Ardından, IME'niz içerik kaydedildiğinde içerik URI'sine erişim izni verebilir. Bunu iki şekilde yapabilirsiniz:
Android 7.1 (API düzeyi 25) ve sonraki sürümlerde
commitContent()
çağrısı yapılırken işaret parametresiniINPUT_CONTENT_GRANT_READ_URI_PERMISSION
olarak ayarlayın. Ardından, uygulamanın aldığıInputContentInfo
nesnesirequestPermission()
vereleasePermission()
çağrıları yaparak geçici okuma izinleri isteyebilir ve yayınlayabilir.Android 7.0 (API düzeyi 24) ve önceki sürümlerde
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
göz ardı edildiği için içeriğe manuel olarak izin verin. Bunu yapmanın bir yolugrantUriPermission()
kullanmaktır ancak kendi gereksinimlerinizi karşılayan kendi mekanizmanızı da uygulayabilirsiniz.
IME'nizi test etmek için cihazınızda veya emülatörünüzde zengin içerik alabilen bir uygulamanın bulunduğundan emin olun. Google Messenger uygulamasını Android 7.1 veya sonraki sürümlerde kullanabilirsiniz.