add custom image as Emoji in android
Asked Answered
C

1

6

how to add custom image as emoji in android InputMethodService. i have tried using

ImageGetter imageGetter = new ImageGetter() {
                public Drawable getDrawable(String source) {    
                    StringTokenizer st = new StringTokenizer(str, ".");
                    Drawable d = new BitmapDrawable(getResources(),emoticons[Integer.parseInt(st.nextToken()) - 1]);
                    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
                    return d;
                }
            };

            Spanned cs = Html.fromHtml("<img src ='"+ str +"'/>", imageGetter, null);


        getCurrentInputConnection().commitText(cs,1);

but only getting enter image description here a obj text image. is there any way to add custom emoji to message(whatsapp /twitter) in android

Edit :

in my application if i type hello using my custom keyboard i have to insert a custom hello picture in edit field for every app installed in phone.

can it achieved ?

Edit : 2

i have checked it using convert mage to base64 also but nothing happen with Tag

ImageGetter imageGetter = new ImageGetter() {
                @Override
                public Drawable getDrawable(String source) {    
                    byte [] encodeByte=Base64.decode("iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",Base64.DEFAULT);
                    Bitmap bitmap=BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);      
                    Drawable d = new BitmapDrawable(bitmap);

                    Log.e("Chk", "Height : "+d.getIntrinsicHeight());
                    Log.e("Chk", "Width : " + d.getIntrinsicWidth());                       

                    return d;
                }
            };

            Spanned cs = Html.fromHtml("<img src='data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='/>", imageGetter,null);

            Log.e("Chk", "12 : " + 12);


        getCurrentInputConnection().setComposingText(cs,1);

Edit : 3

I am using this InputMethodService class in my custom keyboard application.

package com.example.android.softkeyboard;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Html;
import android.text.Html.ImageGetter;
import android.text.Spanned;
import android.text.method.MetaKeyKeyListener;
import android.util.Base64;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;

public class SoftKeyboard extends InputMethodService implements
        KeyboardView.OnKeyboardActionListener {
    static final boolean DEBUG = false;

    static final boolean PROCESS_HARD_KEYS = true;

    private KeyboardView mInputView;
    private CandidateView mCandidateView;
    private CompletionInfo[] mCompletions;

    private StringBuilder mComposing = new StringBuilder();
    private boolean mPredictionOn;
    private boolean mCompletionOn;
    private int mLastDisplayWidth;
    private boolean mCapsLock;
    private long mLastShiftTime;
    private long mMetaState;

    private Keyboard mSymbolsKeyboard;
    private Keyboard mSymbolsShiftedKeyboard;
    private Keyboard mQwertyKeyboard;

    private String mWordSeparators;

    StringBuilder strBldrFrEmoji;

    private void makeKeyboards() {
        if (mQwertyKeyboard != null) {
            // Configuration changes can happen after the keyboard gets
            // recreated,
            // so we need to be able to re-build the keyboards if the available
            // space has changed.
            int displayWidth = getMaxWidth();
            if (displayWidth == mLastDisplayWidth)
                return;
            mLastDisplayWidth = displayWidth;
        }
        mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
        mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
        mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        makeKeyboards();
        mWordSeparators = getResources().getString(R.string.word_separators);
    }

    @Override
    public View onCreateInputView() {
        // We call makeKeyboards() here to regenerate them if needed due to
        // a configuration change.
        makeKeyboards();
        mInputView = (KeyboardView) getLayoutInflater().inflate(R.layout.input,
                null);
        mInputView.setOnKeyboardActionListener(this);
        mInputView.setKeyboard(mQwertyKeyboard);
        return mInputView;
    }

    @Override
    public View onCreateCandidatesView() {
        mCandidateView = new CandidateView(this);
        mCandidateView.setService(this);
        return mCandidateView;
    }

    @Override
    public void onStartInputView(EditorInfo attribute, boolean restarting) {
        super.onStartInputView(attribute, restarting);

        // Reset our state. We want to do this even if restarting, because
        // the underlying state of the text editor could have changed in any
        // way.
        mComposing.setLength(0);
        updateCandidates();

        if (!restarting) {
            // Clear shift states.
            mMetaState = 0;
        }

        mPredictionOn = false;
        mCompletionOn = false;
        mCompletions = null;
        Keyboard keyboard;

        // We are now going to initialize our state based on the type of
        // text being edited.
        switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
        case EditorInfo.TYPE_CLASS_NUMBER:
        case EditorInfo.TYPE_CLASS_DATETIME:
            // Numbers and dates default to the symbols keyboard, with
            // no extra features.
            keyboard = mSymbolsKeyboard;
            break;

        case EditorInfo.TYPE_CLASS_PHONE:
            // Phones will also default to the symbols keyboard, though
            // often you will want to have a dedicated phone keyboard.
            keyboard = mSymbolsKeyboard;
            break;

        case EditorInfo.TYPE_CLASS_TEXT:

            // This is general text editing. We will default to the
            // normal alphabetic keyboard, and assume that we should
            // be doing predictive text (showing candidates as the
            // user types).
            keyboard = mQwertyKeyboard;
            mPredictionOn = true;

            // We now look for a few special variations of text that will
            // modify our behavior.
            int variation = attribute.inputType
                    & EditorInfo.TYPE_MASK_VARIATION;
            if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) {
                // Do not display predictions / what the user is typing
                // when they are entering a password.
                mPredictionOn = false;
            }

            if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                    || variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
                // Our predictions are not useful for e-mail addresses
                // or URIs.
                mPredictionOn = false;
            }

            if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
                // If this is an auto-complete text view, then our predictions
                // will not be shown and instead we will allow the editor
                // to supply their own. We only show the editor's
                // candidates when in fullscreen mode, otherwise relying
                // own it displaying its own UI.
                mPredictionOn = false;
                mCompletionOn = isFullscreenMode();
            }

            // We also want to look at the current state of the editor
            // to decide whether our alphabetic keyboard should start out
            // shifted.
            updateShiftKeyState(attribute);
            break;

        default:
            // For all unknown input types, default to the alphabetic
            // keyboard with no special features.
            keyboard = mQwertyKeyboard;

        }

        // Apply the selected keyboard to the input view.
        if (mInputView != null) {
            mInputView.setKeyboard(keyboard);
            mInputView.closing();
        }
    }

    @Override
    public void onFinishInput() {
        super.onFinishInput();

        // Clear current composing text and candidates.
        mComposing.setLength(0);
        updateCandidates();

        // We only hide the candidates window when finishing input on
        // a particular editor, to avoid popping the underlying application
        // up and down if the user is entering text into the bottom of
        // its window.
        setCandidatesViewShown(false);

        if (mInputView != null) {
            mInputView.closing();
        }
    }

    @Override
    public void onUpdateSelection(int oldSelStart, int oldSelEnd,
            int newSelStart, int newSelEnd, int candidatesStart,
            int candidatesEnd) {

        // If the current selection in the text view changes, we should
        // clear whatever candidate text we have.
        if (mComposing.length() > 0
                && (newSelStart != candidatesEnd || newSelEnd != candidatesEnd)) {
            mComposing.setLength(0);
            updateCandidates();
            InputConnection ic = getCurrentInputConnection();
            if (ic != null) {
                ic.finishComposingText();

            }
        }
    }

    @Override
    public void onDisplayCompletions(CompletionInfo[] completions) {
        if (mCompletionOn) {
            mCompletions = completions;
            if (completions == null) {
                setSuggestions(null, false, false);
                return;
            }

            List<String> stringList = new ArrayList<String>();
            for (int i = 0; i < (completions != null ? completions.length : 0); i++) {
                CompletionInfo ci = completions[i];
                if (ci != null)
                    stringList.add(ci.getText().toString());
            }
            setSuggestions(stringList, true, true);
        }
    }

    private boolean translateKeyDown(int keyCode, KeyEvent event) {

        mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState, keyCode,
                event);
        int c = event.getUnicodeChar(MetaKeyKeyListener
                .getMetaState(mMetaState));
        mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
        InputConnection ic = getCurrentInputConnection();
        if (c == 0 || ic == null) {
            return false;
        }

        boolean dead = false;

        if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
            dead = true;
            c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
        }

        if (mComposing.length() > 0) {
            char accent = mComposing.charAt(mComposing.length() - 1);
            int composed = KeyEvent.getDeadChar(accent, c);

            if (composed != 0) {
                c = composed;
                mComposing.setLength(mComposing.length() - 1);
            }
        }

        onKey(c, null);

        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        switch (keyCode) {

        case KeyEvent.KEYCODE_BACK:
            // The InputMethodService already takes care of the back
            // key for us, to dismiss the input method if it is shown.
            // However, our keyboard could be showing a pop-up window
            // that back should dismiss, so we first allow it to do that.
            if (event.getRepeatCount() == 0 && mInputView != null) {
                if (mInputView.handleBack()) {
                    return true;
                }
            }
            break;

        case KeyEvent.KEYCODE_DEL:
            // Special handling of the delete key: if we currently are
            // composing text for the user, we want to modify that instead
            // of let the application to the delete itself.
            if (mComposing.length() > 0) {
                onKey(Keyboard.KEYCODE_DELETE, null);
                return true;
            }
            break;

        default:
            // For all other keys, if we want to do transformations on
            // text being entered with a hard keyboard, we need to process
            // it and do the appropriate action.
            if (PROCESS_HARD_KEYS) {
                if (keyCode == KeyEvent.KEYCODE_SPACE
                        && (event.getMetaState() & KeyEvent.META_ALT_ON) != 0) {
                    // A silly example: in our input method, Alt+Space
                    // is a shortcut for 'android' in lower case.
                    InputConnection ic = getCurrentInputConnection();
                    if (ic != null) {
                        // First, tell the editor that it is no longer in the
                        // shift state, since we are consuming this.
                        ic.clearMetaKeyStates(KeyEvent.META_ALT_ON);
                        keyDownUp(KeyEvent.KEYCODE_A);
                        keyDownUp(KeyEvent.KEYCODE_N);
                        keyDownUp(KeyEvent.KEYCODE_D);
                        keyDownUp(KeyEvent.KEYCODE_R);
                        keyDownUp(KeyEvent.KEYCODE_O);
                        keyDownUp(KeyEvent.KEYCODE_I);
                        keyDownUp(KeyEvent.KEYCODE_D);
                        // And we consume this event.
                        return true;
                    }
                }
                if (mPredictionOn && translateKeyDown(keyCode, event)) {
                    return true;
                }
            }
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {

        // If we want to do transformations on text being entered with a hard
        // keyboard, we need to process the up events to update the meta key
        // state we are tracking.
        if (PROCESS_HARD_KEYS) {
            if (mPredictionOn) {
                mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
                        keyCode, event);
            }
        }

        return super.onKeyUp(keyCode, event);
    }

    private void commitTyped(InputConnection inputConnection) {

        if (mComposing.length() > 0) {
            inputConnection.commitText(mComposing, mComposing.length());
            mComposing.setLength(0);
            updateCandidates();
        }
    }

    private void updateShiftKeyState(EditorInfo attr) {
        if (attr != null && mInputView != null
                && mQwertyKeyboard == mInputView.getKeyboard()) {
            int caps = getCurrentInputConnection().getCursorCapsMode(
                    attr.inputType);
            mInputView.setShifted(mCapsLock || caps != 0);
        }
    }

    private boolean isAlphabet(int code) {

        if (Character.isLetter(code)) {
            return true;
        } else {
            return false;
        }
    }

    private void keyDownUp(int keyEventCode) {

        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
        getCurrentInputConnection().sendKeyEvent(
                new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
    }

    private void sendKey(int keyCode) {
        ;
        switch (keyCode) {
        case '\n':
            keyDownUp(KeyEvent.KEYCODE_ENTER);
            break;
        default:
            if (keyCode >= '0' && keyCode <= '9') {
                keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
            } else {
                getCurrentInputConnection().commitText(
                        String.valueOf((char) keyCode), 1);
            }
            break;
        }
    }

    public void onKey(int primaryCode, int[] keyCodes) {

        if (primaryCode == 32 || primaryCode == -5 || primaryCode == 10) {
            if (strBldrFrEmoji != null) {
                strBldrFrEmoji = null;
            }
        }

        if (isWordSeparator(primaryCode)) {

            if (mComposing.length() > 0) {
                commitTyped(getCurrentInputConnection());
            }
            sendKey(primaryCode);
            updateShiftKeyState(getCurrentInputEditorInfo());
        } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
            handleBackspace();
        } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
            handleShift();
        } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
            handleClose();
            return;
        } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
            // Show a menu or somethin'
        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
                && mInputView != null) {
            Keyboard current = mInputView.getKeyboard();
            if (current == mSymbolsKeyboard
                    || current == mSymbolsShiftedKeyboard) {
                current = mQwertyKeyboard;
            } else {
                current = mSymbolsKeyboard;
            }
            mInputView.setKeyboard(current);
            if (current == mSymbolsKeyboard) {
                current.setShifted(false);
            }
        } else {
            handleCharacter(primaryCode, keyCodes);
        }
    }

    private void updateCandidates() {

        if (!mCompletionOn) {
            if (mComposing.length() > 0) {
                ArrayList<String> list = new ArrayList<String>();
                list.add(mComposing.toString());
                setSuggestions(list, true, true);
            } else {
                setSuggestions(null, false, false);
            }
        }
    }

    public void setSuggestions(List<String> suggestions, boolean completions,
            boolean typedWordValid) {

        if (mCandidateView != null) {
            mCandidateView.setSuggestions(suggestions, completions,
                    typedWordValid);
            if (suggestions != null && suggestions.size() > 0) {
                setCandidatesViewShown(true);
            } else if (isFullscreenMode()) {
                setCandidatesViewShown(true);
            }
        }
    }

    private void handleBackspace() {
        final int length = mComposing.length();
        if (length > 1) {
            mComposing.delete(length - 1, length);
            getCurrentInputConnection().setComposingText(mComposing,
                    mComposing.length());
            updateCandidates();
        } else if (length > 0) {
            mComposing.setLength(0);
            getCurrentInputConnection().commitText("", 0);
            updateCandidates();
        } else {
            keyDownUp(KeyEvent.KEYCODE_DEL);
        }
        updateShiftKeyState(getCurrentInputEditorInfo());
    }

    private void handleShift() {
        if (mInputView == null) {
            return;
        }

        Keyboard currentKeyboard = mInputView.getKeyboard();
        if (mQwertyKeyboard == currentKeyboard) {
            // Alphabet keyboard
            checkToggleCapsLock();
            mInputView.setShifted(mCapsLock || !mInputView.isShifted());
        } else if (currentKeyboard == mSymbolsKeyboard) {
            mSymbolsKeyboard.setShifted(true);
            mInputView.setKeyboard(mSymbolsShiftedKeyboard);
            mSymbolsShiftedKeyboard.setShifted(true);
        } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
            mSymbolsShiftedKeyboard.setShifted(false);
            mInputView.setKeyboard(mSymbolsKeyboard);
            mSymbolsKeyboard.setShifted(false);
        }
    }

    private void handleCharacter(int primaryCode, int[] keyCodes) {

        if (strBldrFrEmoji == null) {
            strBldrFrEmoji = new StringBuilder();

        }
        strBldrFrEmoji.append(String.valueOf((char) primaryCode));

        checkEnteredText(strBldrFrEmoji.toString());

        if (isInputViewShown()) {
            if (mInputView.isShifted()) {
                primaryCode = Character.toUpperCase(primaryCode);
            }
        }
        if (isAlphabet(primaryCode) && mPredictionOn) {
            mComposing.append((char) primaryCode);
            getCurrentInputConnection().setComposingText(mComposing,
                    mComposing.length());
            updateShiftKeyState(getCurrentInputEditorInfo());
            updateCandidates();
        } else {
            getCurrentInputConnection().commitText(
                    String.valueOf((char) primaryCode), 1);
        }
    }

    void checkEnteredText(String str1) {

        if (str1.length() > 0) {
            if (str1.equalsIgnoreCase("hello")) {


                /**
                ImageGetter imageGetter = new ImageGetter() {
            public Drawable getDrawable(String source) {    
                Drawable d = new BitmapDrawable(getResources(),BitmapFactory.decodeResource(getResources(),
                        R.drawable.ic_smiley));
                d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
                return d;
            }
        };

        Spanned cs = Html.fromHtml("<a href='http://www.google.com'><img src ='"+ str1 +"'/><a>", imageGetter, null);
                */
                ImageGetter imageGetter = new ImageGetter() {
                    @Override
                    public Drawable getDrawable(String source) {
                        byte[] encodeByte = Base64
                                .decode("iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
                                        Base64.DEFAULT);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(
                                encodeByte, 0, encodeByte.length);
                        Drawable d = new BitmapDrawable(bitmap);

                        return d;
                    }
                };

                Spanned cs = Html
                        .fromHtml(
                                "<img src='data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='/>",
                                imageGetter, null);

                getCurrentInputConnection().setComposingText(cs, 1);

            }
        }

    }

    private void handleClose() {

        commitTyped(getCurrentInputConnection());
        // dismissSoftInput(0);
        mInputView.closing();
    }

    private void checkToggleCapsLock() {
        long now = System.currentTimeMillis();
        if (mLastShiftTime + 800 > now) {
            mCapsLock = !mCapsLock;
            mLastShiftTime = 0;
        } else {
            mLastShiftTime = now;
        }
    }

    private String getWordSeparators() {
        return mWordSeparators;
    }

    public boolean isWordSeparator(int code) {

        String separators = getWordSeparators();
        return separators.contains(String.valueOf((char) code));
    }

    public void pickDefaultCandidate() {
        pickSuggestionManually(0);
    }

    public void pickSuggestionManually(int index) {
        if (mCompletionOn && mCompletions != null && index >= 0
                && index < mCompletions.length) {
            CompletionInfo ci = mCompletions[index];
            getCurrentInputConnection().commitCompletion(ci);
            if (mCandidateView != null) {
                mCandidateView.clear();
            }
            updateShiftKeyState(getCurrentInputEditorInfo());
        } else if (mComposing.length() > 0) {
            // If we were generating candidate suggestions for the current
            // text, we would commit one of them here. But for this sample,
            // we will just commit the current text.
            commitTyped(getCurrentInputConnection());
        }
    }

    public void swipeRight() {
        if (mCompletionOn) {
            pickDefaultCandidate();
        }
    }

    public void swipeLeft() {
        handleBackspace();
    }

    public void swipeDown() {
        handleClose();
    }

    public void swipeUp() {
    }

    public void onPress(int primaryCode) {
    }

    public void onRelease(int primaryCode) {
    }

    @Override
    public void onText(CharSequence text) {

    }
}
Carry answered 11/8, 2014 at 9:57 Comment(31)
i have also checked stackoverflow.com/q/24100615/3472378 but no answer.Carry
Reference example : github.com/chiragjain/Emoticons-KeyboardKaliope
@RIT hey, thanks for replay, but could you please see edited question. and i have already checked above link.Carry
what would you like to get instead of OBJ image?Bort
@Bort i want to show image from drawable folder.Carry
where do you call getCurrentInputConnection().setComposingText(cs,1); from?Bort
@Bort i have added my InputMethodService class in question.Carry
ok so create assets folder, add a file "obj1.png" inside assets folder and try to run pastebin.com/9WPJHpHJ, it will give you an idea how to get Spanned imageBort
@Bort this is a keyboard app(Smaple soft keyboard). it enables only when user select it from language and input menu in settings of a device. i dont have edittext/ui in my app.Carry
@Bort actually we are going to create an keyboard when user type using this keyboard for some specific words it will add image instead. for example if user types "hello" it will remove hello and add a image icon in edit field. i have trying from about 3 days but still get no solution any help ?Carry
EditText is not imortanant here, it just shows a Spanned text just to make sure that ImageSpan works ok, what you need is to pass ssb to your commitText methodBort
so important stuff is inside try clause except setText of courseBort
@Bort i have tried it as SpannableStringBuilder ssb = new SpannableStringBuilder("x"); Object what = new ImageSpan(BitmapFactory.decodeStream(getAssets().open("1.png"))); ssb.setSpan(what, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned cs = ssb; getCurrentInputConnection().setComposingText(cs, 1); but it is not rendering image just showing x :(Carry
that's why i posted the code with EditText to make sure you setup everything, did you try to put it in Activity.onCreate and run it? if so do you see the obj1.png image?Bort
@Bort when i add an activity to my app and select this input method as keyboard it is working fine, but when i use this keyboard to enter text in other application like whatsapp, twitter it is not working. also if i copy text from my app to other it is also not copying just paste a blank space.Carry
try to TextUtils.dumpSpans of pasted buffer, it will log the spans in Spanned objectBort
@Bort i used TextUtils.dumpSpans it is printing. 08-12 14:09:14.006: D/CHECK(14297): span x: 41079428 android.text.style.ImageSpan (0-1) fl=#33Carry
so ImageSpan is inside pasted buffer, try to get it via Spanned.getSpans and try to see its Drawable (ImageSpan.getDrawable method)Bort
@Bort i am getting the object of drawable using ImageSpan.getDrawable, and also getting it's height, width. could i ask how it helps to show image.Carry
if Drawable were null or dimensions were zeros the answer would be obvious, now that its valid Drawable the answer is: i don't know why its blank, you would post all the code for me to test it but i think you cannot do thatBort
@Bort Here is the link of project which i want to modify. android.googlesource.com/platform/development/+/master/samples/… i only modify SoftKeyboard class which is posted in question and added a icon image in asset folder with name "1.png". and Thanks in Advance, it would be very useful for me if you help.Carry
@Bort and this is download link for project android.googlesource.com/platform/development/+archive/master/…Carry
instead of ImageSpan try to use any ParcelableSpan (for ex Background/ForegroundColorSpan) and see if they work, if so I'm afraid you can use only ParcelableSpans across different processes, though you could make custom ImageSpan that implements Parcelable iface, i didn't test itBort
did you try Background/ForegroundColorSpan? did they work?Bort
@Bort i have checked color was working. i will post code after 15 hours from now because my IDE is now closed by my employer. thanks.Carry
so i think that only Spans implementing ParcelableSpan can be used in such cases... but you could try as i said to create a custom ImageSpan that implements Parcelable but i don't think it will help...Bort
@Bort i have used 1. wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); (not working) 2. String ss = text.replace("Android", "<font color=\"#ff0000\">Android</font>"); //And then edtresult.setText(Html.fromHtml(ss); (working while typing only)Carry
wordtoSpan.setSpan will work too, you need correct start and end params, and please dont use crappy Html.fromHtml stuffBort
INVISIBLe did you manage to solve the problem ? Im a bit in the same situation.Upstretched
@Upstretched i have not found any solution..Carry
any solution for the above discussionRaving
M
1

You're trying to send an image to twitter/whatsapp, not an emoji. There is a difference.

Emoji literally means "picture to character" and are dependent on the phone's character set that the receiver is using. Even if you replaced the images associated with your own phone's emojis, the person you are sending the emoji to would only be able to see their own keysets of emojis. This is not what you want.

Images have nothing to do with phone keysets and will appear roughly the same no matter which phones they are sent to. You need to pipe your image to an intent associated with the application the user is currently focused on.

  1. Look at Android's application stack.
  2. Find the Application on top.
  3. Pipe the bitmap via intent.putExtra(Intent.EXTRA_STREAM, BitmapUriLocation) into the application;

This is how the app referenced here : https://play.google.com/store/apps/details?id=com.plantpurple.emojidom most likely did things.

Macedo answered 30/1, 2015 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.