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

Bjo*_*inn 5 java android emoticons

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

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

我发现这个代码适用于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
Run Code Online (Sandbox Code Playgroud)

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

根据维基百科,表情符号集位于0x1f600和0x1f64f之间,但我不知道如何检查char是否在该范围内.

我曾希望这样的东西可行,但事实并非如此

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

那么我该怎么做呢?

Mar*_*and 9

四年后...

这个时候,利用起来可能更有意义EmojiCompat。此代码假定您EmojiCompat在应用程序启动时进行了初始化。这里的基本思想是处理EmojiCompat您的CharSequenceEmojiSpan在任何表情符号出现的地方插入实例,然后检查结果。

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;
}
Run Code Online (Sandbox Code Playgroud)

如果您想收集给定 中出现的唯一表情符号的列表CharSequence,您可以执行类似的操作,迭代结果getSpans()并找到每个范围的开始和结束以捕获发现的表情符号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>();
}
Run Code Online (Sandbox Code Playgroud)

更新:这是 EmojiCompat 初始化的示例。可以从应用程序的 onCreate() 方法调用此静态方法,并将应用程序本身作为上下文参数传递。

@JvmStatic
fun initEmojiCompat(context: Context) {
    if (emojiCompatConfig != null) {
        // alternatively, EmojiCompat.reset() could be called here
        logger().w(LOGTAG, "EmojiCompat already initialized.")
        return
    }

    // "Noto Color Emoji Compat" doesn't have graphics for the following emojis:
    // U+1F5E3 "speaking head" (required)
    // U+1F441 "eye" (required)
    // U+1F575 "detective" (nice to have)
    val fontRequest = FontRequest(
        "com.google.android.gms.fonts",
        "com.google.android.gms",
        "Noto Color Emoji Compat",
        R.array.com_google_android_gms_fonts_certs
    )

    emojiCompatConfig = FontRequestEmojiCompatConfig(context, fontRequest)
        .setReplaceAll(false)
        .setEmojiSpanIndicatorEnabled(false)
        .registerInitCallback(initCallback)
        .also {
            EmojiCompat.init(it)
        }
}
Run Code Online (Sandbox Code Playgroud)


Bjo*_*inn 6

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

我不完全确定如何else if (substring.length > 1)从 iOS 代码进行处理,但我认为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;
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*sen 5

Telegram 是这样做的:

private static boolean isEmoji(String message){
    return message.matches("(?:[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83E\uDD00-\uD83E\uDDFF]|" +
        "[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|" +
        "[\u2600-\u26FF]\uFE0F?|[\u2700-\u27BF]\uFE0F?|\u24C2\uFE0F?|" +
        "[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|" +
        "[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|" +
        "[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|" +
        "[\u2934\u2935]\uFE0F?|[\u3030\u303D]\uFE0F?|[\u3297\u3299]\uFE0F?|" +
        "[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|" +
        "[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|" +
        "[\u00A9\u00AE]\uFE0F?|[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|" +
        "[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)+");
}

Run Code Online (Sandbox Code Playgroud)

这是21,026路