App ShortcutsはいいからまずはImage Keyboardをサポートしたほうがいい

煽り気味のタイトルですみません :bow:

# App Shortcutsとは？
ホームに特定の機能をショートカットとして置くことができます。
https://developer.android.com/guide/topics/ui/shortcuts.html

Android 7.1から使えるようになった機能です

# Image Keyboard Supportとは？
キーボードから画像を入力することができます。
https://developer.android.com/guide/topics/text/image-keyboard.html

Android 7.1から使えるようになった機能……__ではないです！__

> The API is also available in v13 Support Library as of revision 25.0.0.

サポートライブラリを使えばAndroid 3.2から使えます！

## 画像が入力できるキーボードなんて使っている人いるの？
実はNexusなどに標準で入っているキーボードがGboardという名前になったとき、GIFアニメが入力できるようになりました。
https://play.google.com/store/apps/details?id=com.google.android.inputmethod.latin
http://jp.techcrunch.com/2016/12/18/20161216google-brings-its-upgraded-keyboard-app-gboard-to-android/

かなり分かりにくいですが、以下のような手順で入力できます。

![device-2017-01-02-203222.gif](https://qiita-image-store.s3.amazonaws.com/0/92361/47b77fb0-817b-f80e-540e-cfa9ced27c09.gif)

# どうやって対応する？
従来のintentによる画像選択が実装されているようなアプリでは、かなり簡単に実装することができます。

## サポートライブラリ
まずは、サポートライブラリの導入。

```groovy:build.gradle
dependencies {
    // ...
    compile 'com.android.support:support-v13:25.1.0'
}
```

あんまり使わない（？）v13のサポートライブラリです。25以降を入れる必要があります。

## ImageKeyboardSupportEditTextの作成
[ドキュメント](https://developer.android.com/guide/topics/text/image-keyboard.html#adding_image_support_to_apps)では`EditText`を`new`していますが、専用のクラスを作ってしまった方が、xmlにも書けて楽でしょう。

RxJavaとラムダ式を使うと以下のような感じでしょうか？

```java:ImageKeyboardSupportEditText.java
class ImageKeyboardSupportEditText extends EditText {
    private BehaviorSubject<Uri> uri = BehaviorSubject.create();
    
    // コンストラクタは省略

    @Override
    public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
        final InputConnection ic = super.onCreateInputConnection(editorInfo);
        EditorInfoCompat.setContentMimeTypes(editorInfo, new String[]{"image/gif"});
        return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> {
            if (BuildCompat.isAtLeastNMR1() && (flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
                try {
                    inputContentInfo.requestPermission();
                } catch (Exception e) {
                    return false;
                }
            }
            uri.onNext(inputContentInfo.getContentUri());
            inputContentInfo.releasePermission();
            return true;
        });
    }

    public Observable<Uri> getUri() {
        return uri.asObservable();
    }
}
```

ほとんどドキュメントの通りですが、GboardはGIFだけっぽいので、`image/gif`にしています。

後は`findViewById`するなどして、コールバックを設定します。

```java:MainActivity.java
ImageKeyboardSupportEditText imageKeyboardSupportEditText = (ImageKeyboardSupportEditText) findViewById(R.id.image_keyboard_support_edit_text);
imageKeyboardSupportEditText.getUri().subscribe(uri -> {
    // 画像のuriを受けた後の処理
});
```

## URIから画像に
通常なら、以下のような感じになると思いますが、

```java
imageKeyboardSupportEditText.getUri().subscribe(uri -> {
    InputStream inputStream = getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, null);
    // bitmapを使う
});
```
Glideを使えばGIFアニメーションも簡単にできてしまいます。

```java
final GlideDrawableImageViewTarget target = new GlideDrawableImageViewTarget(imageView);
imageKeyboardSupportEditText.getUri().subscribe(uri -> {
    Glide.with(this).load(uri).into(target);
});
```

すでに`ACTION_GET_CONTENT`や`ACTION_IMAGE_CAPTURE`によって画像を取得し、サーバに送信する処理などを実装しているのであれば、以下のような感じでもできると思います。

```java
imageKeyboardSupportEditText.getUri().subscribe(uri -> {
    onActivityResult(REQUEST_CODE, RESULT_OK, new Intent().setData(uri));
});
```

# まとめ
最初は「文字列内に画像が入るの？」と思いましたが、通常の画像選択と同じuriなので、意外と簡単に導入できました。
LINEスタンプの代わりになるようなものとして発展していけば面白いなと思います。
ただ、画像の著作権がどのようになっているのかはちょっと気になりました :sweat_smile:
気が向いたらIMEの方も作ってみたいと思います :muscle:

何か間違いがあれば教えていただけると幸いです :bow: