ইমেজ কীবোর্ড সাপোর্ট

ব্যবহারকারীরা প্রায়ই ইমোজি, স্টিকার ও অন্যান্য ধরনের রিচ কন্টেন্ট ব্যবহার করে যোগাযোগ করতে চান। Android-এর আগের ভার্সনে, সফ্ট কীবোর্ড—যা ইনপুট পদ্ধতি এডিটর বা IME নামেও পরিচিত—অ্যাপে শুধু ইউনিকোড ইমোজি পাঠাতে পারত। রিচ কন্টেন্টের জন্য, অ্যাপ-নির্দিষ্ট API-এর মাধ্যমে তৈরি করা অ্যাপ অন্যান্য অ্যাপে ব্যবহার করা যায় না অথবা সহজ শেয়ার অ্যাকশন বা ক্লিপবোর্ডের মাধ্যমে ছবি পাঠানোর মতো ওয়ার্কঅ্যারাউন্ড ব্যবহার করা যায় না।

ছবি সার্চ করার সুবিধা আছে এমন কীবোর্ড দেখানো ছবি
ছবি ১. ইমেজ কীবোর্ড সংক্রান্ত সহায়তার উদাহরণ।

Android 7.1 (API লেভেল ২৫) থেকে শুরু করে, Android SDK-তে Commit Content API অন্তর্ভুক্ত থাকে, যা IME-এর জন্য অ্যাপের টেক্সট এডিটরে সরাসরি ছবি ও অন্যান্য রিচ কন্টেন্ট পাঠানোর একটি সর্বজনীন উপায় প্রদান করে। API-টি ২৫.০.০ রিভিশন অনুযায়ী v13 সাপোর্ট লাইব্রেরিতেও উপলভ্য। আমরা সহায়তা লাইব্রেরি ব্যবহার করার সাজেশন দিই কারণ এতে সহায়ক পদ্ধতি রয়েছে যা প্রয়োগ করা সহজ করে তোলে।

এই API-এর সাহায্যে, আপনি এমন মেসেজিং অ্যাপ তৈরি করতে পারবেন যা যেকোনও কীবোর্ড থেকে রিচ কন্টেন্ট গ্রহণ করে এবং যেকোনও অ্যাপে রিচ কন্টেন্ট পাঠাতে পারে। Google কীবোর্ড এবং Messages by Google-এর মতো অ্যাপ Android 7.1-এ Commit Content API-কে সাপোর্ট করে, যেমনটি চিত্র ১-এ দেখানো হয়েছে।

এই ডকুমেন্ট থেকে জানা যায় যে কীভাবে IME এবং অ্যাপ, দুটিতেই Commit Content API প্রয়োগ করতে হয়।

এটি কীভাবে কাজ করে

কীবোর্ডে ছবি যোগ করার জন্য IME এবং অ্যাপের অংশগ্রহণ প্রয়োজন। নিম্নলিখিত ক্রম ছবি যোগ করার প্রসেসের প্রতিটি ধাপ বর্ণনা করে:

  1. ব্যবহারকারী EditText-এ ট্যাপ করলে, এডিটর MIME কন্টেন্টের প্রকারের একটি তালিকা পাঠায় যা এটি EditorInfo.contentMimeTypes-এ গ্রহণ করে।

  2. IME কাজ করে এমন ধরনের তালিকা পড়ে এবং সফ্ট কীবোর্ডে কন্টেন্ট দেখায় যা এডিটর গ্রহণ করতে পারে।

  3. ব্যবহারকারী কোনও ছবি বেছে নিলে, IME commitContent() কল করে এবং এডিটরে InputContentInfo পাঠায়। commitContent() কলটি commitText() কলের মতো, তবে এটি রিচ কন্টেন্টের জন্য। InputContentInfo-এ একটি URI আছে যা কন্টেন্ট প্রোভাইডার-এ কন্টেন্ট শনাক্ত করে।

এই প্রসেসটি ছবি ২-এ দেখানো হয়েছে:

অ্যাপ্লিকেশন থেকে IME এবং আবার অ্যাপ্লিকেশনে ফিরে আসার সিকোয়েন্স দেখানো একটি ছবি
ছবি ২. অ্যাপ্লিকেশন থেকে IME হয়ে অ্যাপ্লিকেশন ফ্লো।

অ্যাপে ছবি সংক্রান্ত সহায়তা যোগ করা

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
    }
}

জাভা

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;
    }
};

নিচে আরও ব্যাখ্যা দেওয়া হল:

  • এই উদাহরণে সহায়তা লাইব্রেরি ব্যবহার করা হয়েছে, তাই android.view.inputmethod-এর পরিবর্তে android.support.v13.view.inputmethod-এর কিছু রেফারেন্স আছে।

  • এই উদাহরণটি একটি EditText তৈরি করে এবং InputConnection পরিবর্তন করার জন্য এর onCreateInputConnection(EditorInfo) পদ্ধতি ওভাররাইড করে। InputConnection হল IME এবং যে অ্যাপে ইনপুট পাঠানো হচ্ছে, তার মধ্যে যোগাযোগের চ্যানেল।

  • কল super.onCreateInputConnection() বিল্ট-ইন আচরণ—টেক্সট পাঠানো ও গ্রহণ করা—সংরক্ষণ করে এবং আপনাকে InputConnection-এর রেফারেন্স দেয়।

  • setContentMimeTypes() EditorInfo-এ কাজ করে এমন MIME-এর প্রকারের তালিকা যোগ করে। setContentMimeTypes()-এর আগে super.onCreateInputConnection()-কে কল করুন।

  • IME কন্টেন্ট কমিট করলেই callback এক্সিকিউট করা হয়। onCommitContent() পদ্ধতিতে InputContentInfoCompat-এর রেফারেন্স আছে, যাতে কন্টেন্ট URI রয়েছে।

    • আপনার অ্যাপ API লেভেল ২৫ বা তার থেকে বেশি ভার্সনে চললে এবং IME-এর মাধ্যমে INPUT_CONTENT_GRANT_READ_URI_PERMISSION ফ্ল্যাগ সেট করা থাকলে, অনুমতি দেওয়ার অনুরোধ করুন এবং রিলিজ করুন। অন্যথায়, আপনার কাছে আগে থেকেই কন্টেন্ট URI-এর অ্যাক্সেস আছে কারণ এটি IME-এর মাধ্যমে মঞ্জুর করা হয়েছে অথবা কন্টেন্ট প্রোভাইডার অ্যাক্সেস সীমিত করেনি। আরও তথ্যের জন্য, IME-তে ইমেজ সাপোর্ট যোগ করুন দেখুন।
  • createWrapper() InputConnection, পরিবর্তিত EditorInfo এবং কলব্যাককে নতুন InputConnection-এ র‍্যাপ করে এবং এটি ফিরিয়ে দেয়।

নিম্নলিখিতগুলি হল সাজেস্ট করা পদ্ধতি:

  • যেসব এডিটর রিচ কন্টেন্ট সাপোর্ট করে না, তারা setContentMimeTypes() কল করে না এবং তাদের EditorInfo.contentMimeTypes null-এ সেট করা থাকে।

  • InputContentInfo-এ উল্লেখ করা MIME-এর ধরন এডিটরদের গ্রহণ করা কোনও ধরনের সাথে না মিললে, তারা কন্টেন্টটি উপেক্ষা করেন।

  • রিচ কন্টেন্ট টেক্সট কার্সারের পজিশনকে প্রভাবিত করে না এবং এর দ্বারা প্রভাবিত হয় না। কন্টেন্ট নিয়ে কাজ করার সময় এডিটররা কার্সারের পজিশন উপেক্ষা করতে পারবেন।

  • এডিটরের OnCommitContentListener.onCommitContent() পদ্ধতিতে, আপনি অ্যাসিঙ্ক্রোনাসভাবে true রিটার্ন করতে পারবেন, এমনকি কন্টেন্ট লোড করার আগেও।

  • টেক্সটের মতো নয়, যা কমিট করার আগে IME-তে এডিট করা যায়, রিচ কন্টেন্ট অবিলম্বে কমিট করা হয়। আপনি যদি ব্যবহারকারীদের কন্টেন্ট এডিট বা মুছে ফেলার অনুমতি দিতে চান, তাহলে লজিকটি নিজেই প্রয়োগ করুন।

আপনার অ্যাপ পরীক্ষা করতে, আপনার ডিভাইস বা এমুলেটরে এমন একটি কীবোর্ড আছে কিনা তা নিশ্চিত করুন যা রিচ কন্টেন্ট পাঠাতে পারে। Android 7.1 বা তার পরবর্তী যেকোনও ভার্সনে Google Keyboard ব্যবহার করতে পারবেন।

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.
    }
}

জাভা

@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)
}

জাভা

// 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 (API লেভেল 25) এবং তার পরবর্তী যেকোনও ভার্সনে, commitContent() কল করার সময়, ফ্ল্যাগ প্যারামিটার INPUT_CONTENT_GRANT_READ_URI_PERMISSION-এ সেট করুন। তারপর, অ্যাপ যে InputContentInfo অবজেক্ট পায়, সেটি requestPermission() এবং releasePermission() কল করে সাময়িক রিড পার্মিশনের অনুরোধ করতে ও তা রিলিজ করতে পারে।

  • Android 7.0 (API লেভেল ২৪) এবং তার আগের ভার্সনে, INPUT_CONTENT_GRANT_READ_URI_PERMISSION উপেক্ষা করা হয়, তাই কন্টেন্টের জন্য ম্যানুয়ালি অনুমতি দিন। এটি করার একটি উপায় হল grantUriPermission(), তবে আপনি নিজের প্রয়োজন অনুযায়ী নিজস্ব মেকানিজম প্রয়োগ করতে পারেন।

আপনার IME পরীক্ষা করতে, আপনার ডিভাইস বা এমুলেটরে এমন একটি অ্যাপ আছে কিনা তা নিশ্চিত করুন যা রিচ কন্টেন্ট গ্রহণ করতে পারে। আপনি Android 7.1 বা তার পরবর্তী যেকোনও ভার্সনে Google Messenger অ্যাপ ব্যবহার করতে পারবেন।