Anthony Wentzel

Sending images from an Android keyboard, before Android let you

In 2015 we built a custom emoji keyboard for Android. Keyboards could only type text, so we used share intents, a ContentProvider and the clipboard.

From 2015 · 2 min read · Published August 27, 2026

In mid-2015 our team built an Android emoji keyboard for a TV network: branded stickers and GIFs from the network's shows, organized by show, available from any app's text field. Android's keyboard input system wasn't built for it.

The Android keyboard constraint

A custom Android keyboard is an InputMethodService. It talks to the app you're typing in through an InputConnection, and in 2015 that connection could do one thing: commit text. There was no supported way for a keyboard to insert an image into a chat app. That API (commitContent) didn't arrive until Android 7.1, more than a year later.

So a keyboard full of images had to get them into other apps some other way.

What we did instead

When a user tapped a sticker, the keyboard wrote the image to a file and handed it off with a share intent, typed by MIME type so GIFs stayed animated:

FXKeyboard.java (simplified)
if (object instanceof Bitmap) {
    File file = saveToShareableFile((Bitmap) object);
    boolean shared = Utils.getSendEmailIntent(this, "", "", "image/png", file); 
    if (!shared) {
        // fall back to something the target app can accept
    }
}

Around that core, most of the work was making the handoff reliable:

  • A custom ContentProvider, so images could be handed to other apps as content:// URIs rather than raw file paths those apps might not be allowed to open.
  • A clipboard path, so the image could be pasted in apps that didn't handle the share intent well.
  • Device-specific fixes. One release note in the history reads "adding new emojis and fix for MotoX." Android fragmentation was not theoretical.
  • Analytics events on each sticker, because a marketing app that can't report usage doesn't get a second season.

What I learned

The workaround shipped to Google Play, and new show packs kept getting added through the summer. But I came away with a clear rule about platform constraints: when the platform doesn't support what you're doing, every workaround is a feature you now maintain forever, on every OS version and device.

The right time to build a sticker keyboard on Android turned out to be after commitContent existed. We built it before, because the product needed to exist then. That's often the real trade: not "right way versus wrong way," but "ship now with a workaround you'll own, or wait for the platform."


Related: Fastlane for iOS: half my commits were build numbers · Wrapping a native SDK in a React Native native module