百行代码集成Emoji并转成iOS、后台可识别字符

最近被提了一个BUG,在iOS提交了包含Emoji表情的文字,在Android中却识别不了,还可能导致后台接口出错(¬_¬)…于是,开始了我Emoji爬坑之路。

效果图:

集成Emoji表情

说到怎么集成Emoji表情,Github中一搜有一大堆,我这里用的是比较热门的emojicon,这个库提供的表情都比较全,但也会导致Apk包增加几兆(数千个表情-_-!),作者提供了EmojiconTextView、EmojiconEditText、EmojiconsFragment,其中EmojiconsFragment是写好的Emoji表情选择框(有些丑..得根据需求去修改),至于如何使用,可以去Github看文档。

将Emoji表情传给后台并解析后台返回的Emoji字符

在Android中调试看到的EditText.getText().toString的Emoji表情是后台无法识别的,我们需要将它转换成一些可见的字符串,并且这个字符串格式与iOS开发人员协定好,使得三个端都可识别。刚开始,我是将它通过EmojiUtils工具类转成Unicode十六进制字符串,拿到后台返回json数据时逐个字节判断是否包含Emoji表情,再将Emoji表情的Unicode字符串转成表情。

public class EmojiUtils {

    /**
     * 将Unicode字符转成中文
     * @param src
     * @return
     */
    public static String unicode2Emoji(String src) {
        if (TextUtils.isEmpty(src)) {
            return "";
        }

        StringBuffer retBuf = new StringBuffer();
        int maxLoop = src.length();
        for (int i = 0; i < maxLoop; i++) {
            if (src.charAt(i) == '\\') {
                if ((i < maxLoop - 5) && ((src.charAt(i + 1) == 'u') || (src.charAt(i + 1) == 'U'))) {
                    try {
                        retBuf.append((char) Integer.parseInt(src.substring(i + 2, i + 6), 16));
                        i += 5;
                    } catch (NumberFormatException localNumberFormatException) {
                        retBuf.append(src.charAt(i));
                    }
                } else {
                    retBuf.append(src.charAt(i));
                }
            } else {
                retBuf.append(src.charAt(i));
            }
        }
        return retBuf.toString();
    }

    /**
     * 将字符串中的Emoji表情转换成Unicode编码
     * @param src
     * @return
     */
    public static  String emoji2Unicode(String src) {
        StringBuffer unicode = new StringBuffer();

        for (int i = 0; i < src.length(); i++) {
            char c = src.charAt(i);
            int codepoint = src.codePointAt(i);
            if(isEmojiCharacter(codepoint)) {
                unicode.append("\\u").append(Integer.toHexString(c));
            } else {
                unicode.append(c);
            }
        }
        return unicode.toString();
    }

    /**
     * 判断是否包含Emoji符号
     * @param codePoint
     * @return
     */
    public static boolean isEmojiCharacter(int codePoint) {
        return (codePoint >= 0x2600 && codePoint <= 0x27BF) // 杂项符号与符号字体
                || codePoint == 0x303D
                || codePoint == 0x2049
                || codePoint == 0x203C
                || (codePoint >= 0x2000 && codePoint <= 0x200F)//
                || (codePoint >= 0x2028 && codePoint <= 0x202F)//
                || codePoint == 0x205F //
                || (codePoint >= 0x2065 && codePoint <= 0x206F)//
                /* 标点符号占用区域 */
                || (codePoint >= 0x2100 && codePoint <= 0x214F)// 字母符号
                || (codePoint >= 0x2300 && codePoint <= 0x23FF)// 各种技术符号
                || (codePoint >= 0x2B00 && codePoint <= 0x2BFF)// 箭头A
                || (codePoint >= 0x2900 && codePoint <= 0x297F)// 箭头B
                || (codePoint >= 0x3200 && codePoint <= 0x32FF)// 中文符号
                || (codePoint >= 0xD800 && codePoint <= 0xDFFF)// 高低位替代符保留区域
                || (codePoint >= 0xE000 && codePoint <= 0xF8FF)// 私有保留区域
                || (codePoint >= 0xFE00 && codePoint <= 0xFE0F)// 变异选择器
                || codePoint >= 0x10000; // Plane在第二平面以上的,char都不可以存,全部都转
    }
}

后来找到一个第三方库(https://github.com/vdurmont/emoji-java/),它可以将Emoji表情转换成各种格式字符串,包括我们想要的Unicode编码,最新Emoji表情Unicode对照表:http://apps.timwhitlock.info/emoji/tables/unicode

举个栗子

在app的build.gradle中加入:

//Emoji表情:https://github.com/rockerhieu/emojicon
compile 'io.github.rockerhieu:emojicon:+'

//Emoji表情转换成各类可见字符串:https://github.com/vdurmont/emoji-java/
compile 'com.vdurmont:emoji-java:+'

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/ll_main_bottom"
        android:overScrollMode="never">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"
                android:text="Emoji表情展示:"
                android:textColor="@color/colorAccent"/>

            <io.github.rockerhieu.emojicon.EmojiconTextView
                android:id="@+id/tv_main_emoji"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"
                android:text="Emoji表情转Unicode编码:"
                android:textColor="@color/colorAccent"/>

            <TextView
                android:id="@+id/tv_main_unicode"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"
                android:text="Emoji表情转Unicode(10进制)编码:"
                android:textColor="@color/colorAccent"/>

            <TextView
                android:id="@+id/tv_main_unicode_dec"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="Emoji表情转Unicode(16进制)编码:"
                android:textColor="@color/colorAccent"/>

            <TextView
                android:id="@+id/tv_main_unicode_hex"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"
                android:text="Emoji表情转iOS可识别的Aliase:"
                android:textColor="@color/colorAccent"/>

            <TextView
                android:id="@+id/tv_main_aliase"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"
                android:text="过滤Emoji表情:"
                android:textColor="@color/colorAccent"/>

            <TextView
                android:id="@+id/tv_main_emoji_filter"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/padding"/>
        </LinearLayout>
    </ScrollView>

    <LinearLayout
        android:id="@+id/ll_main_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <io.github.rockerhieu.emojicon.EmojiconEditText
                android:id="@+id/et_main_bottom"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:padding="5dp"/>

            <ImageView
                android:id="@+id/iv_main_emoji"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@mipmap/icon_happy_face"/>

            <Button
                android:id="@+id/btn_main_unicode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="编码转换"/>
        </LinearLayout>

        <FrameLayout
            android:id="@+id/fl_main_bottom_emoji"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:visibility="gone"/>
    </LinearLayout>
</RelativeLayout>

MainActivity

public class MainActivity extends AppCompatActivity implements EmojiconGridFragment.OnEmojiconClickedListener, EmojiconsFragment.OnEmojiconBackspaceClickedListener {

    @BindView(R.id.tv_main_emoji)
    EmojiconTextView tvEmoji;

    @BindView(R.id.tv_main_unicode)
    TextView tvUnicode;

    @BindView(R.id.tv_main_unicode_dec)
    TextView tvUnicodeDec;

    @BindView(R.id.tv_main_unicode_hex)
    TextView tvUnicodeHex;

    @BindView(R.id.tv_main_aliase)
    TextView tvAliase;

    @BindView(R.id.tv_main_emoji_filter)
    TextView tvEmojiFilter;

    @BindView(R.id.fl_main_bottom_emoji)
    FrameLayout flBottomEmoji;

    @BindView(R.id.et_main_bottom)
    EmojiconEditText etBottom;

    private Context mContext;
    private FragmentManager mFragmentManager;
    private EmojiconsFragment mEmojiconsFragment;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mContext = this;
        mFragmentManager = getSupportFragmentManager();
        if(mEmojiconsFragment == null) {
            mEmojiconsFragment = EmojiconsFragment.newInstance(false);
        }
    }

    /**
     * 显示表情选择框
     */
    private void showEmojiSelector() {
        flBottomEmoji.setVisibility(View.VISIBLE);
        if(mEmojiconsFragment.isAdded()) {
            mFragmentManager.beginTransaction().show(mEmojiconsFragment).commit();
        } else {
            mFragmentManager.beginTransaction().add(R.id.fl_main_bottom_emoji, mEmojiconsFragment).commit();
        }
    }

    /**
     * 隐藏表情选择框
     */
    private void hideEmojiSelector() {
        flBottomEmoji.setVisibility(View.GONE);
        if(mEmojiconsFragment.isAdded()) {
            mFragmentManager.beginTransaction().hide(mEmojiconsFragment).commit();
        }
    }

    @OnClick(R.id.et_main_bottom)
    public void onEditTextClick(View v) {
        //软键盘弹出时,隐藏表情选择框
        if(KeyBoardUtils.isKeyboardShown(mContext, etBottom)) {
            hideEmojiSelector();
        }
    }

    @OnClick(R.id.iv_main_emoji)
    public void emoji() {
        //显示或隐藏Emoji表情选择框
        KeyBoardUtils.closeKeybord(mContext, etBottom);

        if(!flBottomEmoji.isShown()) {
            showEmojiSelector();
        } else {
            hideEmojiSelector();
        }
    }

    @OnClick(R.id.btn_main_unicode)
    public void unicode() {
        //将Emoji表情转换成各种可见字符串
        KeyBoardUtils.closeKeybord(mContext, etBottom);

        String content = etBottom.getText().toString().trim();
        tvEmoji.setText(content);
        tvUnicode.setText(EmojiParser.parseToUnicode(content));
        tvUnicodeDec.setText(EmojiParser.parseToHtmlDecimal(content));
        tvUnicodeHex.setText(EmojiParser.parseToHtmlHexadecimal(content));
        tvAliase.setText(EmojiParser.parseToAliases(content));
        tvEmojiFilter.setText(EmojiParser.removeAllEmojis(content));
    }

    @Override
    public void onEmojiconBackspaceClicked(View v) {
        //删除EditText中的表情
        EmojiconsFragment.backspace(etBottom);
    }

    @Override
    public void onEmojiconClicked(Emojicon emojicon) {
        //选中表情,在EditText中显示
        EmojiconsFragment.input(etBottom, emojicon);
    }
}

最近项目挺忙,只能抽空弄个小Demo记录自己如何集成Emoji,不多说,又要去撸代码了~~
Github源码下载


参考链接:
- 最新Emoji表情Unicode对照表
- iOS、Android、Server对Emoji的支持

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值