Upgrade to Pro — share decks privately, control downloads, hide ads and more …

No More Tofu - Mastering Emoji on Android (Chicago Roboto)

No More Tofu - Mastering Emoji on Android (Chicago Roboto)


Miguel Beltran

April 13, 2018


  1. @Miqubel No More □ (tofu)    Mastering Emoji on Android

  2. Why Emoji matters? What problems do Android developers face? What

    solutions do we have? Is EmojiCompat the greatest thing ever?
  3. Emoji: A Brief Story Source: https://stories.moma.org/the-original-emoji-set-has-been-added-to-the-museum-of-modern-arts-collection-c6060e141f61

  4. Emoji & Android Source: https://www.androidcentral.com/history-emoji-android

  5. How to be up to date: DIY

  6. None
  7. None
  8. None
  9. Emotions Source: People interpret the same emoji in completely different

    ways https://www.theverge.com/2016/4/11/11406944/emoji-meaning-difference-ios-android
  10. How Emoji Works

  11. Extra-short-intro to Unicode Hello U+0048 U+0065 U+006C U+006C U+006F Unicode:

    Single character set that contains ALL characters of the Universe Each character maps to a Codepoint A Codepoint may be represented in memory differently! Codepoint UTF-8 UTF-16 H U+0048 48 0048 U+1F602 F0 9F 98 82 D83D DE02
  12. How Emoji works Emoji: Graphic representation of one or more

    Unicode chars (Codepoints) "Face With Tears of Joy” U+1F602 val emoji = "\uD83D\uDE02"
  13. How Emoji works “Woman Technologist: Medium-Dark Skin Tone” val emoji

    = “\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBB" U+1F469 U+1F3FE U+200D U+1F4BB
  14. How long is an Emoji? Challenge: How many “Woman Technologist:

    Medium-Dark Skin Tone” Emojis can you fit on a Tweet? A: 280 B: 140 C: 40 Solution: 40 280 / 7 = 40
  15. How long is an Emoji? —> Improvement emoji.length = 7

    emoji.codePointCount(0, emoji.length) = 4 val emoji = “\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBB"
  16. How long is an Emoji? —> Improvement val it =

    BreakIterator.getCharacterInstance() it.setText(emoji) var count = 0 while (it.next() != BreakIterator.DONE) { count++ } count = 3 on API 23 count = 1 on API 25
  17. Challenges so far Missing Emoji (tofu) Different Emoji per platform

    Length of strings with Emoji
  18. Let’s look at three solutions Custom solution: Images and Spans

    Custom solution: Font file Using EmojiCompat
  19. Images and Spans Strategy: 1. Find an Emoji on a

    String 2. Replace with an ImageSpan 3. Repeat for the whole String
  20. Finding Emoji on Strings Get a nice dictionary: EmojiOne “emoji.json”:

    1.38 MB! Fast JSON parsing: com.jsoniter —> but you won’t need to Efficient pattern matching —> Regular Expression
  21. None
  22. Emoji assets Download: emojione/emojione-assets • Free: PNG 32px, 64px, 128px

    • Paid: SVG and larger PNG Example: SLICE OF PIZZA (U+1F355) —> 1f355.png
  23. Matching and displaying val PATTERN = “\\ud83c\\udf55".toRegex() val matches =

    PATTERN.findAll(text) for (match in matches) { spannableString.setSpan( ImageSpan(context, R.drawable.emoji_1f355), match.range.start, match.range.endInclusive + 1, SpannableString.SPAN_INCLUSIVE_INCLUSIVE ) } Solution: DynamicDrawableSpan (and resize the drawable)
  24. Images and Spans Pros: Freedom Cons: Lots of manual work

    needed APK size (4000 PNGs…)
  25. Custom font file Strategy: 1. Include font file with Emoji

    2. Set font file containing Emoji to TextView 3. Set text to TextView
  26. Custom font file: Setup 1. Download Android font 2. Place

    in assets/fonts Download: https://www.emojione.com/download
  27. Custom font file: Setup val typeface = Typeface.createFromAsset(assets, “fonts/emojione.ttf”) textView.typeface

    = typeface textView.text = string
  28. Custom font file: Results

  29. Custom font file: Hold on… textView.text = "Numbers: 1 2

    3 4" Solution: Parse Emoji and create TypefaceSpans
  30. Custom Font: Better but… Pros: Easy to setup Cons: Manual

    work needed
  31. EmojiCompat Strategy: — Process Strings with EmojiCompat or — Use

  32. EmojiCompat: Setup (bundled) implementation “com.android.support:support-emoji:x.y.z” implementation “com.android.support:support-emoji-bundled:x.y.z” Adds: 7.4 MB

  33. EmojiCompat: Setup (downloadable) val fontRequest = FontRequest( "com.google.android.gms.fonts", "com.google.android.gms", "Noto

    Color Emoji Compat", R.array.com_google_android_gms_fonts_certs) val config = FontRequestEmojiCompatConfig(this, fontRequest) EmojiCompat.init(config) Init takes 150 ms! But happens asynchronously
  34. EmojiCompat: Setup (downloadable) Downloadable fonts get updated automatically!

  35. EmojiCompat: Setup (downloadable) Source: https://github.com/googlei18n/noto-emoji

  36. EmojiCompat: Setup (downloadable) Downloadable fonts get updated automatically! Find it

    in data/data/com.google.android.gms/files/fonts/opentype Noto_Color_Emoji_Compat-400-100_0-0_0.ttf Version 2.003;GOOG;noto-emoji:20171030:a5efe6ca61db
  37. EmojiCompat: Using it textView.text = EmojiCompat.get().process(string)

  38. EmojiCompat: Using it

  39. EmojiCompat: Replace All val config = FontRequestEmojiCompatConfig(…) config.setReplaceAll(true) EmojiCompat.init(config)

  40. EmojiCompat: Handling init delay EmojiCompat.get().registerInitCallback(object : EmojiCompat.InitCallback() { override fun

    onInitialized() { textView.text = EmojiCompat.get().process(string) } override fun onFailed(throwable: Throwable?) { // handle error? textView.text = string } } )
  41. EmojiCompat: Using the Views <android.support.text.emoji.widget.EmojiTextView/> <android.support.text.emoji.widget.EmojiEditText/> <android.support.text.emoji.widget.EmojiButton/>

  42. EmojiCompat: Easy! Wishlist Customize it Emoji Keyboard Emoji tools

  43. Thank you! Miquel Beltran - @Miqubel