Android - Как отфильтровать эмодзи (смайлики) из строки?

Я работаю над приложением для Android и не хочу, чтобы люди использовали эмодзи на входе.

Как я могу удалить символы эмодзи из строки?

5 ответов

Решение

Emojis можно найти в следующих диапазонах ( источник):

  • U + 2190 до U + 21FF
  • U + 2600 до U + 26FF
  • U + 2700 до U + 27BF
  • U + 3000 до U+303F
  • От U+1F300 до U + 1F64F
  • U + 1F680 до U+1F6FF

Вы можете использовать эту строку в вашем скрипте, чтобы отфильтровать их все сразу:

text.replace("/[\u2190-\u21FF]|[\u2600-\u26FF]|[\u2700-\u27BF]|[\u3000-\u303F]|[\u1F300-\u1F64F]|[\u1F680-\u1F6FF]/g", "");

Последние данные смайликов можно найти здесь:

http://unicode.org/Public/emoji/

Существует папка с именем Emoji версии. Как разработчики приложений хорошей идеей является использование последней доступной версии.

Когда вы заглянете внутрь папки, вы увидите в ней текстовые файлы. Вы должны проверить emoji-data.txt. Он содержит все стандартные коды смайликов.

Для эмодзи существует множество небольших кодовых диапазонов. Лучшая поддержка будет проверять все это в вашем приложении.

Некоторые люди спрашивают, почему есть 5-значные коды, когда мы можем указать только 4 после \ u. Ну, это коды, сделанные из суррогатных пар. Обычно 2 символа используются для кодирования одного смайлика.

Например, у нас есть строка.

String s = ...;

UTF-16 представительство

byte[] utf16 = s.getBytes("UTF-16BE");

Итерация по UTF-16

for(int i = 0; i < utf16.length; i += 2) {

Получить один символ

char c = (char)((char)(utf16[i] & 0xff) << 8 | (char)(utf16[i + 1] & 0xff));

Теперь проверьте наличие суррогатных пар. Emoji расположены на первой плоскости, поэтому проверьте первую часть пары в диапазоне 0xd800..0xd83f.

if(c >= 0xd800 && c <= 0xd83f) {
    high = c;
    continue;
}

Для второй части суррогатной пары диапазон составляет 0xdc00..0xdfff. И теперь мы можем преобразовать пару в один 5-значный код.

else if(c >= 0xdc00 && c <= 0xdfff) {
    low = c;
    long unicode = (((long)high - 0xd800) * 0x400) + ((long)low - 0xdc00) + 0x10000;
}

Все остальные символы не являются парами, поэтому обрабатывайте их как есть.

else {
    long unicode = c;
}

Теперь используйте данные из emoji-data.txt, чтобы проверить, является ли это emoji. Если это так, то пропустите это. Если нет, то скопируйте байты в выходной байтовый массив.

Наконец, байтовый массив преобразуется в строку

String out = new String(outarray, Charset.forName("UTF-16BE"));

Тем, кто использует Kotlin, также может помочь Char.isSurrogate. Найдите и удалите из этого истинные индексы.

Вот что я использую для удаления смайликов. Примечание: это работает только на API 24 и вперед

public  String remove_Emojis_For_Devices_API_24_Onwards(String name)
   {
    // we will store all the non emoji characters in this array list
     ArrayList<Character> nonEmoji = new ArrayList<>();

    // this is where we will store the reasembled name
    String newName = "";

    //Character.UnicodeScript.of () was not added till API 24 so this is a 24 up solution
    if (Build.VERSION.SDK_INT > 23) {
        /* we are going to cycle through the word checking each character
         to find its unicode script to compare it against known alphabets*/
        for (int i = 0; i < name.length(); i++) {
            // currently emojis don't have a devoted unicode script so they return UNKNOWN
            if (!(Character.UnicodeScript.of(name.charAt(i)) + "").equals("UNKNOWN")) {
                nonEmoji.add(name.charAt(i));//its not an emoji so we add it
            }
        }
        // we then cycle through rebuilding the string
        for (int i = 0; i < nonEmoji.size(); i++) {
            newName += nonEmoji.get(i);
        }
    }
    return newName;
}

так что если мы передадим строку:

remove_Emojis_For_Devices_API_24_Onwards ("тестовый индикатор:ढ японский:な корейский:ㅂ");

возвращается: тест Инди:: Японский:な Корейский: ㅂ

Emoji размещение или количество не имеет значения

      private String removeEmojis(String input) {
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < input.length(); i++) {
        char c = input.charAt(i);
        if (c <= 127) {
            output.append(c);
        }
    }
    return output.toString();
}
Другие вопросы по тегам