检测String中的字符是否是表情符号(使用Android)

时间:2014-01-27 22:24:10

标签: java android emoticons

就像标题所说的那样。我想知道给定的java String是否包含表情符号。

我无法使用Character.UnicodeBlock.of(char) == Character.UnicodeBlock.EMOTICONS,因为这需要API级别19。

I found this code for iOS但它并不适用,因为它看起来像java和objective-c以不同的方式处理代理对。

我看过的文件告诉我:

A char value, therefore, represents Basic Multilingual Plane (BMP) code points, including the surrogate code points, or code units of the UTF-16 encoding

我不太清楚这意味着什么。这仅仅意味着他们还将BMP点作为他们的第一个数字吗?

According to Wikipedia表情符号集位于0x1f600和0x1f64f之间,但我不知道如何检查char是否在该范围内。

我原本希望这样的东西能起作用,但它没有

if (0x1f600 <= a && a <= 0x1f64f)
{
    Print.d("Unicode", "groovy!");
}

那我该怎么做呢?

3 个答案:

答案 0 :(得分:3)

我实际上能够使用链接的iOS代码来创建以下功能。我没有意识到包含例如单个表情符号的字符串将具有2的长度。因此,您可以检查字符是否实际上是代理。

我不完全确定如何处理iOS代码中的else if (substring.length > 1),但我认为Character.isHighSurrogate(myChar)在该实例中执行相同的工作。

private boolean containsIllegalCharacters(String displayName)
{
    final int nameLength = displayName.length();

    for (int i = 0; i < nameLength; i++)
    {
        final char hs = displayName.charAt(i);

        if (0xd800 <= hs && hs <= 0xdbff)
        {
            final char ls = displayName.charAt(i + 1);
            final int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;

            if (0x1d000 <= uc && uc <= 0x1f77f)
            {
                return true;
            }
        }
        else if (Character.isHighSurrogate(hs))
        {
            final char ls = displayName.charAt(i + 1);

            if (ls == 0x20e3)
            {
                return true;
            }
        }
        else
        {
            // non surrogate
            if (0x2100 <= hs && hs <= 0x27ff)
            {
                return true;
            }
            else if (0x2B05 <= hs && hs <= 0x2b07)
            {
                return true;
            }
            else if (0x2934 <= hs && hs <= 0x2935)
            {
                return true;
            }
            else if (0x3297 <= hs && hs <= 0x3299)
            {
                return true;
            }
            else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50)
            {
                return true;
            }
        }
    }

    return false;
}

答案 1 :(得分:1)

四年后......

此时,利用EmojiCompat可能更有意义。此代码假设您在应用启动时初始化EmojiCompat。这里的基本想法是让EmojiCompat处理您的CharSequence,在任何表情符号出现的任何地方插入EmojiSpan的实例,然后检查结果。

public static boolean containsEmoji(CharSequence charSequence) {
    boolean result = false;
    CharSequence processed = EmojiCompat.get().process(charSequence, 0, charSequence.length() -1, Integer.MAX_VALUE, EmojiCompat.REPLACE_STRATEGY_ALL);
    if (processed instanceof Spannable) {
        Spannable spannable = (Spannable) processed;
        result = spannable.getSpans(0, spannable.length() - 1, EmojiSpan.class).length > 0;
    }
    return  result;
}

如果您想收集显示在给定CharSequence内的唯一表情符号列表,您可以执行以下操作:迭代getSpans()的结果并查找每个表的开头和结尾span捕获EmojiCompat发现的表情符号:

@NonNull
public static List<String> getUniqueEmoji(CharSequence charSequence) {
    Set<String> emojiList = new HashSet<>();
    CharSequence processed = EmojiCompat.get().process(charSequence, 0, charSequence.length() -1, Integer.MAX_VALUE, EmojiCompat.REPLACE_STRATEGY_ALL);
    if (processed instanceof Spannable) {
        Spannable spannable = (Spannable) processed;

        EmojiSpan[] emojiSpans = spannable.getSpans(0, spannable.length() - 1, EmojiSpan.class);
        for (EmojiSpan emojiSpan : emojiSpans) {
            int spanStart = spannable.getSpanStart(emojiSpan);
            int spanEnd = spannable.getSpanEnd(emojiSpan);
            CharSequence emojiCharSequence = spannable.subSequence(spanStart, spanEnd);
            emojiList.add(String.valueOf(emojiCharSequence));
        }
    }
    return emojiList.size() > 0 ? new ArrayList<>(emojiList) : new ArrayList<String>();
}

答案 2 :(得分:0)

试试这个......

if (Integer.parseInt("1f600", 16) <= (int)'☺' && (int)'☺' <= Integer.parseInt("1f64f", 16)) {
    Print.d("Unicode", "groovy!");
}

这可能有效,因为十六进制值和char值都被转换为整数。