Preventing Unwanted Content from Google Keyboard

Android 7.1 added the ability for IMEs to send images (and more) to EditTexts.

Supporting rich content requires you to explicitly opt-in by overriding EditText.onCreateInputConnection(). It's a bit of a hassle, and not everyone wants to accept rich content, so unsurprisingly many apps don't support it.

Normally if you try to insert rich content into an app lacking support, then nothing happens. But the Google Keyboard (aka Gboard), which comes standard on many devices, has some alternative behavior around this case. If your app has an intent filter that accepts android.intent.action.SEND, then Gboard automatically fires an Intent (with the rich content) towards it!

I think this is a bad choice for fallback behavior because it is confusing and unnecessary. It can happen on any EditText in your app, meaning you could one moment be searching for data, and then the next moment be pulled into an entirely different part of the app! And moreover, it's unlikely that users actually want to enter rich content (like a sticker or gif) into any given EditText - it only makes sense in limited contexts.

I tried adding a sticker to a variety of apps that accept images to see what would happen. I started from each apps' "search" functionality, since I assume no one actually wants to accept stickers in searches. The results range from confusing to broken:

  • Drive prompts you to save the sticker to Drive.
  • Keep prompts you to save a new card with the sticker (even if you were already editing a note!)
  • Google Maps prompts you to post the sticker as a photo for a place.
  • Google Photos sets you up to upload the sticker to your photo collection.
  • Slack prompts you to share the sticker to a channel.
  • Amazon Kindle shoots you to another part of the app and then pops up an error dialog.
  • Trello prompts you to create a new card with the sticker attached.

The above isn't meant to shame any apps - rather I want to demonstrate that no one is expecting this weird behavior that Gboard is throwing at them.

There does not seem to be an easy way to prevent Gboard from firing the Intent. Here are a few workarounds, all bad:

  • Stop accepting the SEND intent. This won't be an option for most apps since presumably they do want to accept this intent every once in a while!
  • Use an inputType that does not allow for stickers (like number). Also not an option most of the time, since you often want people to enter text!
  • Swallow the rich content commits so that Gboard doesn't think the content went unhandled.

Here's a sketch of how you would swallow the content commits:

class MyEditText(context: Context?, attrs: AttributeSet?) : EditText(context, attrs) {
  override fun onCreateInputConnection(editorInfo: EditorInfo): InputConnection {
    val ic = super.onCreateInputConnection(editorInfo)
    EditorInfoCompat.setContentMimeTypes(editorInfo, arrayOf("image/*"))
    val callback = InputConnectionCompat.OnCommitContentListener { _, _, _ -> true }
    return InputConnectionCompat.createWrapper(ic, editorInfo, callback)
  }
}

It's not a great workaround because you have to subclass every EditText in your app, lest someone still be able to access this behavior. Secretly I'm hoping someone working on Gboard notices this post and fixes this bizarre problem.