Like the title says. I want to find out if a given java String contains an emoticon.
I can\'t use Character.UnicodeBlock.of(char) == Character.UnicodeBlock.EMO
Try this...
if (Integer.parseInt("1f600", 16) <= (int)'☺' && (int)'☺' <= Integer.parseInt("1f64f", 16)) {
Print.d("Unicode", "groovy!");
}
This might work because the hexidecimal value and the char value are both being converted to ints.
I was in fact able to use the linked iOS code to create the following function. I didn't realize that a String that contains, for example, a single emoticon will have a length of 2. So you can check if a character is in fact a surrogate.
I'm not entirely sure how to handle else if (substring.length > 1)
from the iOS code but I think Character.isHighSurrogate(myChar)
does the same job in that instance.
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;
}
Four years later...
At this time, it might make more sense to take advantage of EmojiCompat
. This code presumes you initialized EmojiCompat
when your app was starting up. The basic idea here is to have EmojiCompat
process your CharSequence
, inserting instances of EmojiSpan
wherever any emoji appear, and then examine the results.
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;
}
If you want to collect a list of the unique emoji that appear within a given CharSequence
, you could do something like this, iterating over the results of getSpans()
and finding the start and end of each span to capture the emoji discovered by 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>();
}