IOS的Emoji表情因为编码问题,在Android手机上无法正常显示,如果当前的cc.Label节点使用的是系统字,在系统字库中找不到对应编码的字符,会导致崩溃。

为了解决这个问题,又要兼顾新老版本,要在3个地方做调整:

  1. Android虚拟键盘输入时,屏蔽Emoji;
  2. IOS虚拟键盘输入时,屏蔽Emoji;
  3. Lua端屏蔽Emoji;

一、Android端屏蔽Emoji

1、在Cocos2dxHelper.java类中添加过滤Emoji方法

private static boolean containsEmoji(String source) {
if (null == source || 0 == source.length()) {
return false;
}
int len = source.length();
for (int i = 0; i < len; i++) {
char c = source.charAt(i);
if (isEmojiCharacter(c)) {
return true;
}
}
return false;
} private static boolean isEmojiCharacter(char c) {
return !((c == 0x0) || (c == 0x9) || (c == 0xA)
|| (c == 0xD)
|| ((c >= 0x20) && (c <= 0xD7FF))
|| ((c >= 0xE000) && (c <= 0xFFFD))
|| ((c >= 0x10000) && (c <= 0x10FFFF)));
} private static String filterEmoji(String source) {
if (!containsEmoji(source)) {
return source;// don't contain, just return
}
StringBuilder buf = null;
int len = source.length();
for (int i = 0; i < len; i++) {
char c = source.charAt(i);
if (!isEmojiCharacter(c)) {
if (buf == null) {
buf = new StringBuilder(source.length());
}
buf.append(c);
}
}
if (buf == null) {
return null;
} else {
if (buf.length() == len) {
buf = null;
return source;
} else {
return buf.toString();
}
}
}

2、修改Cocos2dxHelper.java类的setEditTextDialogResult方法

把代码

final byte[] bytesUTF8 = pResult.getBytes("UTF8");

修改为

String text = filterEmoji(pResult);
if (null == text || 0 == text.length()) {
text = "";
}
final byte[] bytesUTF8 = text.getBytes("UTF8");

二、IOS屏蔽Emoji表情

IOS的Emoji表情的输入有两种方式:一种是Emoji表情页,另一种是输入法打字联想出来的。

1、屏蔽Emoji表情页中的表情输入

- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([textField isFirstResponder]) {
if([[[textField textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textField textInputMode] primaryLanguage]) {
return NO;
}
}
...
...
}

2、过滤输入法联想出来的Emoji:

1)检测并过滤Emoji表情

// 过滤所有表情。containEmoji为NO表示不含有表情,YES表示含有表情
- (BOOL)stringContainsEmoji:(UITextField *)textField
{
__block BOOL containEmoji = NO;
self.stringAfterFilterEmoji = @"";
NSString* string = textField.text;
[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
const unichar hs = [substring characterAtIndex:0];
BOOL is_emoji = NO;
// surrogate pair
if (0xd800 <= hs && hs <= 0xdbff) {
if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
is_emoji = YES;
}
}
} else if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
if (ls == 0x20e3) {
is_emoji = YES;
}
} else {
// non surrogate
if (0x2100 <= hs && hs <= 0x27ff) {
is_emoji = YES;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
is_emoji = YES;
} else if (0x2934 <= hs && hs <= 0x2935) {
is_emoji = YES;
} else if (0x3297 <= hs && hs <= 0x3299) {
is_emoji = YES;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
is_emoji = YES;
}
}
if (!is_emoji) {
self.stringAfterFilterEmoji = [self.stringAfterFilterEmoji stringByAppendingString:substring];
}
containEmoji = is_emoji ? is_emoji : containEmoji;
}];
return containEmoji;
}

2)应用过滤过的输入

- (BOOL)textFieldShouldEndEditing:(UITextField *)sender {
if ([self stringContainsEmoji:sender]) {
sender.text = self.stringAfterFilterEmoji;
}
...
...
}

三、Lua屏蔽Emoji

由于要兼顾老版本,不仅仅要在输入端对Emoji进行过滤,如果老版本使用Emoji,同样要添加过滤;但Lua的编码跟Java和OC有很大不同,Java可以通过char、OC通过unichar可以获取Unicode字符,但Lua不行,Lua是通过string的字节链接的形式来存储Unicode的字符;

通过总结发现,一个Emoji表情的第1个字节(string.byte(s, 1))等于240,第2个字节(string.byte(s,2))等于159的不能被Android识别,从而崩溃,因此可以过滤此种Emoji,从而解决崩溃问题。

function M:getByteCount( byte )
local ret = 0
if byte > 0 and byte <= 127 then
ret = 1
elseif byte >= 192 and byte < 223 then
ret = 2
elseif byte >= 224 and byte < 239 then
ret = 3
elseif byte >= 240 and byte <= 247 then
ret = 4
end
return ret
end function M:filterEmoji( source )
local len = string.len(source)
if len < 2 then return source end
local ret_str = ""
local i = 1
while i <= len do
local is_emoji = false
local byte_1 = string.byte(source, i)
if byte_1 == 240 then
local byte_2 = string.byte(source, i + 1)
if byte_2 == 159 then
is_emoji = true
end
end
local byte_count = self:getByteCount(byte_1)
byte_count = byte_count < 1 and 1 or byte_count
if not is_emoji then
ret_str = ret_str..string.sub(source, i, i + byte_count - 1)
end
i = i + byte_count
end
return ret_str
end

【Cocos2d-x】屏蔽Emoji并解决由于Emoji导致的崩溃问题的更多相关文章

  1. UITableViewController 滚动引起的cocos2d动画暂停问题的解决

    UITableViewController 滚动引起的cocos2d动画暂停问题的解决 之前在使用UITableViewController进行滚动时,cocos2d的动画会暂停,直至滚动完毕才会继续 ...

  2. Android中解决图像解码导致的OOM问题

    Android中解决图像解码导致的OOM问题 原文链接:http://blog.csdn.net/zjl5211314/article/details/7042017

  3. php--如何解决网站分页导致的SEO问题

    如何解决网站分页导致的SEO问题 分页(pagination)是一种自动分页机制,可以将移动Web窗体中的内容分割成一组组较小的页进行呈现,以适合于特定的设备,该机制还呈现可用于浏览到其他页的用户界面 ...

  4. 解决跨海高并发崩溃难题?so easy

    近年来随着互联网强势的发展浪潮,越来越多的企业选择跨境出海,扩展海外市场.而想要在一个陌生市场最快速地吸引到用户,一定不能缺少的就是丰富多样的各类活动.然而活动在带来大流量的同时,也带来了一些问题,比 ...

  5. MySQL解决插入emoji表情失败的问题

    普通的字符串或者表情都是占位3个字节,所以utf8足够用了,但是移动端的表情符号占位是4个字节,普通的utf8就不够用了,为了应对无线互联网的机遇和挑战.避免 emoji 表情符号带来的问题.涉及无线 ...

  6. laravel 解决保存Emoji 表情问题

    ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; ALTER TABLE table ...

  7. iOS 获取emoji表情和拦截emoji表情

      1 2 //将数字转为 #define EMOJI_CODE_TO_SYMBOL(x) ((((0x808080F0 | (x & 0x3F000) >> 4) | (x &a ...

  8. 自定制emoji替换系统的emoji键盘

    一.关于emoji表情 随着iOS系统版本的升级,对原生emoji表情的支持也越来越丰富.emoji表情是unicode码中为表情符号设计的一组编码,当然,还有独立于unicode的另一套编码SBUn ...

  9. 关于 error C2039: “create”: 不是“cocos2d::GLView”的成员的解决方法

    问题: 跑一个demo,因为是涉及3.x版本的引擎,不是很熟悉,在VS2013上运行,报错 error C2039: “create”: 不是“cocos2d::GLView”的成员 解决: 通过查阅 ...

随机推荐

  1. C语言之通讯录的模拟实现

    C语言之通讯录的模拟实现 在C语言学习结束之际,谨以此篇文章来对C语言的学习告一段落. 纲要: 通讯录的静态版本 通讯录的动态版本 通讯录的带文件版本 因为三种实现方法除了储存形式不同,其他都基本相同 ...

  2. CDN域名解析问题

    CDN域名解析问题 之前配置CDN域名解析,碰到一个配置带www的域名和不带www的域名,这里就有个解析的坑,已经将cdn域名都配置好的,但是一直访问不了,白屏现象 后面排除源站问题和cdn配置问题, ...

  3. Node.js/Vue.js使用jsSHA库进行SHA1/2/3加密

    1 概述 jsSHA是一个用JS+TS实现完整SHA系列加密算法的加密库,包括: SHA1 SHA-224/256/384/512 SHA3-224/256/384/512 SHAKE128/256 ...

  4. lvs 负载均衡 _DR模式 _Python脚本

    import paramiko vip='192.168.83.6' # 虚拟IP # direct_server_information ds_info={ 'ip':'192.168.83.5', ...

  5. Python学习从入门到放弃?我不允许!!!

    嗨,大家好 这里是汐仔 很多人都说学习python学习python,打开书本,三分钟,从入门到放弃. 这怎么可以!!!大家能选择python的原因可能是看它既简单,好入门,现在俨然是语言中的一匹黑马. ...

  6. .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程

    本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...

  7. scrapy爬虫框架调用百度地图api数据存入数据库

    scrapy安装配置不在本文 提及, 1.在开始爬取之前,必须创建一个新的Scrapy项目.进入自定义的项目目录中,运行下列命令 scrapy startproject mySpider 其中, my ...

  8. Java基础常用类深度解析(包含常见排序算法)

    目录 一.工具类 1.1.工具类的设计 1.1.1.公共静态方法 1.2.单例模式 二.包装类 2.1.基本类型的包装类 2.1.1.Integer 2.1.1.1.Integer >> ...

  9. 【MySQL】Mysql(InnoDB引擎) 索引的数据结构为什么选择B+Tree

    1.B+ Tree的层数较少 B类树的一个很鲜明的特点就是数的层数比较少,而每层的节点非常多,树的每个叶子节点到根节点的距离都是相同的: 2.   减少磁盘IO: 树的每一个节点都是一个数据也,这样每 ...

  10. hdu1428 spfa+记忆化搜索

    题意:      题意坑爹,很容易误认成是做短路的条数,题意是给你一个图,让你从起点走到终点,问你有多少种走法,但有一个限制,假如你想从a走到b,必须满足终点到b的最短距离小于终点到a的最短距离. 思 ...