这个是我做Android以来碰到的最烦的东西,该死的emoji表情,恨之入骨。。无奈这个问题分配给我了。我也只能硬着头皮做。

0.吐个槽先

首先,你要明白什么是emoji表情,不知道的google,不需要支持emoji的可以绕道了。

emoji有很多不同的版本,我tm最讨厌的就是不同版本的了。Unified DoCoMo KDDI Softbank Google

因为ios5升级了,emoji编码从softbank变成unified了。所以只能Android这边改了。伤心。

我要做的工作就是把消息中含有的unified的emoji编码过滤出来,然后映射出对应的表情资源显示出来。

1.准备工作。

google下emoji表情的历史,google code上有个源码,不过是java的,那么你要把它改成java的。。(记得当初解析gif表情时也是把java改成android,可怜的我为咩总是干这活。。)

这里有个link,上面有所有的编码对应转换。Emoji for PHP

然后google code里有所有对应的编码转换的xml。叫emoji4unicode.xml. 这里是link: emoji4unicode

如果没兴趣我等下会直接贴代码的,但是最好你先自己弄明白解析的原理是什么,emoji表情一直在增加,以后要兼容你就得自己想办法了。

2.举个例子

black sun with rays unified : U+2600 softbank: U+E04A

如果以前你解析过softbank,应该很熟悉了。好歹它还有个大致得顺序,解析得时候只要判断是否在这个unicode范围内就可以了。so easy

可是unified完全是无顺序得,所以必须得自己建好映射。

因为原始的emoji.xml很大,把所有的描述信息都放里面了,我不需要,所以我写了个java把xml解析了一遍,然后重新生成了一个我需要的xml。贴个图出来大家看下。

you see , 这个原始的xml实在太大了,有162K,而且还是xml解析。。你想想多耗内存和时间。所以必须把它再转换一遍。

so 这个过程做好了,就可以进行下一步真正的解析了。。

3 解析过程。

因为emoji是有表情分组的,所以你要优先考虑解析出来的也是分好组的。

HashMap<String, ArrayList<String>> emoMap = new HashMap<String, ArrayList<String>>();

我是这么来分组的。

解析xml,然后把2600这样的字符串转换成unicode。这个很关键,映射对应不上肯定也解析不出来。要注意的一点是有的emoji是两个unicode组成的  U+1F1F0 U+1F1F7  这样。。所以么。又多了一个环节。

HashMap<List<Integer>, String> convertMap = new HashMap<List<Integer>, String>();

再定义一个map来存unicode和string字符的映射。

  1. if (xmlpull.getName().equals("e")) {
  2. fromAttr = xmlpull.nextText();
  3. emos.add(fromAttr);
  4. List<Integer> fromCodePoints = new ArrayList<Integer>();
  5. if (fromAttr.length() > ) {
  6. String[] froms = fromAttr.split("\\_");
  7. for (String part : froms) {
  8. fromCodePoints.add(Integer.parseInt(part, ));
  9. }
  10. } else {
  11. fromCodePoints.add(Integer.parseInt(fromAttr, ));
  12. }
  13. convertMap.put(fromCodePoints, fromAttr);
  14. }

这样就把整个解析都写到内存里了。这个就做成单例咯,在程序一进来,application里初始化。

4,解析过程

这里我是把emoji表情解析出来,再改成[e]2600[/e]的形式。然后再用正则再解析一遍(为什么这样做。。因为消息里面不可能只有emoji表情的啊亲。。。你还要解析另外的表情。)

下面是过滤emoji表情的方法:

  1. public String parseEmoji(String input) {
  2. if (input == null || input.length() <= ) {
  3. return "";
  4. }
  5. StringBuilder result = new StringBuilder();
  6. int[] codePoints = toCodePointArray(input);
  7. List<Integer> key = null;
  8. for (int i = ; i < codePoints.length; i++) {
  9. key = new ArrayList<Integer>()
  10. if (i + < codePoints.length) {
  11. key.add(codePoints[i]);
  12. key.add(codePoints[i + ]);
  13. if (convertMap.containsKey(key)) {
  14. String value = convertMap.get(key);
  15. if (value != null) {
  16. result.append("[e]" + value + "[/e]");
  17. }
  18. i++;
  19. continue;
  20. }
  21. }
  22. key.clear();
  23. key.add(codePoints[i]);
  24. if (convertMap.containsKey(key)) {
  25. String value = convertMap.get(key);
  26. if (value != null) {
  27. result.append("[e]" + value + "[/e]");
  28. }
  29. continue;
  30. }
  31. result.append(Character.toChars(codePoints[i]));
  32. }
  33. return result.toString();
  34. }

看到这里,你可能觉得懵了。当时我也是卡了两三天,不停的网上找资料,反编译别人的代码。最后才找的解决方案的,代码其实没有很多,最重要的是要怎么去思考。

4.渲染成图片。

  1. public static SpannableStringBuilder convetToHtml(String content, Context mContext) {
  2. String regex = "\\[e\\](.*?)\\[/e\\]";
  3. Pattern pattern = Pattern.compile(regex);
  4. String emo = "";
  5. Resources resources = mContext.getResources();
  6. String unicode = EmojiParser.getInstance(mContext).parseEmoji(content);
  7. Matcher matcher = pattern.matcher(unicode);
  8. SpannableStringBuilder sBuilder = new SpannableStringBuilder(unicode);
  9. Drawable drawable = null;
  10. ImageSpan span = null;
  11. while (matcher.find()) {
  12. emo = matcher.group();
  13. try {
  14. int id = resources.getIdentifier(
  15. "emoji_" + emo.substring(emo.indexOf("]") + , emo.lastIndexOf("[")),
  16. "drawable", "package");
  17. if (id != ) {
  18. drawable = resources.getDrawable(id);
  19. drawable.setBounds(, , , );
  20. span = new ImageSpan(drawable);
  21. sBuilder.setSpan(span, matcher.start(), matcher.end(),
  22. Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  23. }
  24. } catch (Exception e) {
  25. break;
  26. }
  27. }
  28. return sBuilder;
  29. }

好了,成功解析出来了。但是!!你得先把图片弄到手啊,亲。而且还要我这个格式得。

贴个图

额,话说这个我也是写了个java,把之前得softbank得命名转换成unified的命名,当初我还准备一个一个手动改来着,还好我同事一语点醒梦中人额。。不然我估计就吐血身亡了。程序写多了就是这样,思维固定了。。。

5.发emoji消息。

既然能显示了,你还得发啊,亲。

直接贴代码把,一个还原过程

  1. public static String convertToMsg(CharSequence cs, Context mContext) {
  2. SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
  3. ImageSpan[] spans = ssb.getSpans(, cs.length(), ImageSpan.class);
  4. for (int i = ; i < spans.length; i++) {
  5. ImageSpan span = spans[i];
  6. String c = span.getSource();
  7. int a = ssb.getSpanStart(span);
  8. int b = ssb.getSpanEnd(span);
  9. if (c.contains("emoji")) {
  10. ssb.replace(a, b, convertUnicode(c));
  11. }
  12. }
  13. ssb.clearSpans();
  14. return ssb.toString();
  15. }
  16. private static String convertUnicode(String emo) {
  17. emo = emo.substring(emo.indexOf("_") + );
  18. if (emo.length() < ) {
  19. return new String(Character.toChars(Integer.parseInt(emo, )));
  20. }
  21. String[] emos = emo.split("_");
  22. char[] char0 = Character.toChars(Integer.parseInt(emos[], ));
  23. char[] char1 = Character.toChars(Integer.parseInt(emos[], ));
  24. char[] emoji = new char[char0.length + char1.length];
  25. for (int i = ; i < char0.length; i++) {
  26. emoji[i] = char0[i];
  27. }
  28. for (int i = char0.length; i < emoji.length; i++) {
  29. emoji[i] = char1[i - char0.length];
  30. }
  31. return new String(emoji);
  32. }

由于时间跨度比较长了。年初得时候写得,基本都记不清了。所以尽量不要来问我额,亲们,我只提供解决方案。

代码我也会上传一份,有需要得可以拿去耍。

Unified Emoji表情for Android的更多相关文章

  1. Emoji表情图标在iOS与PHP之间通信及MySQL存储

    在某个 iOS 项目中,需要一个服务器来保存一些用户数据,例如用户信息.评论等,我们的服务器端使用了 PHP+MySQL 的搭配.在测试过程中我们发现,用户在 iOS 端里输入了 Emoji 表情提交 ...

  2. 数据库支持emoji表情

    从MySQL5.5.3开始,MySQL 支持一种utf8mb4的字符集,这个字符集能够支持4字节的UTF8编码的字符.utf8mb4字符集能够完美地兼容utf8字符串.在数据存储方面,当一个普通中文字 ...

  3. mysql兼容emoji表情存取

    emoji介绍 Emoji (絵文字,词义来自日语えもじ,e-moji,moji在日语中的含义是字符)是一套起源于日本的12x12像素表情符号,由栗田穣崇(Shigetaka Kurit)创作,最早在 ...

  4. Js 过滤emoji表情...持续补充中..

    原文来自: https://www.cnblogs.com/tsjTSJ/p/7065544.html 最全最详细的用JS过滤Emoji表情的输入   在前端页面开发过程中,总会碰到不允许输入框输入e ...

  5. 最全最详细的用JS过滤Emoji表情的输入

    在前端页面开发过程中,总会碰到不允许输入框输入emoji表情的需求,我的思路是通过编码用正则匹配表情,然后将其替换为空字符创.但是问题也是显而易见的,完整的编码集是什么呢?查阅了官方文档,发现上面并没 ...

  6. 用JS过滤Emoji表情的输入

    本文为原创,转载请注明出处: cnzt       文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6773854.html 在前端页面开发过程中,总会碰到不允许 ...

  7. Android 实现emoji表情的demo

    Android 实现emoji表情的例子,网上看到的,记录一下. 请看下图 : 项目下载地址:http://download.csdn.net/detail/abc13939746593/741397 ...

  8. 使用php-emoji类让网页显示emoji表情

    需要的材料: php-emoji类库的下载地址:https://github.com/iamcal/php-emoji 代码示例:(该代码来自官网) <?php include('emoji.p ...

  9. mysql utf8mb4与emoji表情

    一 什么是Emoji emoji就是表情符号:词义来自日语(えもじ,e-moji,moji在日语中的含义是字符) 表情符号现已普遍应用于手机短信和网络聊天软件. emoji表情符号,在外国的手机短信里 ...

随机推荐

  1. selenium-python iframe用法

    易迅的登录方法,因为页面有很多iframe的内置框架,需要先逐级定位到登录元素所在的iframe才行 使用方法switch_to_frame('id-name') from selenium impo ...

  2. 【笔记】WPF之模板控件应用

    最近在捣鼓WPF的动画,想自定义一个控件模型来实现动画. 目标功能是这样:在WPF项目文件中创建一个自定义用户控件模型,该模型最外层是一个Grid,Grid布局为3行1列,第一列是一个图片按钮,第二列 ...

  3. [转]DataGridView绑定泛型List的种种

    1.DataGridView数据绑定对比(DataTable与泛型List):当DataGridView的DataSource是DataTable的时候,DataTable的数据改变时,DataGri ...

  4. iOS的SandBox的结构研究

    在模拟器中运行iOS程序,都会为该程序创建一个沙盒(SandBox).首先声明,我用的系统是Max OS X 10.7.3,编译器是Xcode 4.3.2.想要找到沙盒目录,先运行Finder,然后在 ...

  5. windows2003通过iis配置ftp服务器

    以前习惯于用filezilla作为windows的ftp服务器,但是现在新版本的filezilla已经不支持windows2003了,所以趁机试一下iis配置ftp服务器. 前面都是很常规的配置 参考 ...

  6. 从InputStream到String_写成函数

    String result = readFromInputStream(inputStream);//调用处 //将输入流InputStream变为String public String readF ...

  7. app进入后台申请10分钟活跃时间-b

    IOS允许长时间在后台运行的情况有7种: audio VoIP GPS 下载新闻 和其它附属硬件进行通讯时 使用蓝牙进行通讯时 使用蓝牙共享数据时 除以上情况,程序退出时可能设置短暂运行10分钟 让程 ...

  8. 最火的.NET开源项目(转)

    综合类 微软企业库 微软官方出品,是为了协助开发商解决企业级应用开发过程中所面临的一系列共性的问题, 如安全(Security).日志(Logging).数据访问(Data Access).配置管理( ...

  9. [转载+原创]Emgu CV on C# (四) —— Emgu CV on 全局固定阈值二值化

    重点介绍了全局二值化原理及数学实现,并利用emgucv方法编程实现. 一.理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数)  1.概述 图像二值化是图像处理中的一项基本技术,也 ...

  10. C#之多态

    多态是面向对象编程中三大机制之一,其原理建立在"从父类继承而来的子类可以转换为其父类"这个规则之上,换句话说,能用父类的地方,就能用该类的子类.当从父类派生了很多子类时,由于每个子 ...