Firebase Storageの画像をGlideで表示する

Firebaseを使ったAndroidアプリの開発をしています。
Cloud Storage for Firebaseにアップした画像をアプリに表示したかったのですが、色々ハマったのでメモに残します。

例として、"image"というフォルダに格納した画像"sample.jpg"を表示します。


# 開発環境
- Android Studio 3.3.2
- Kotlin 1.3.21
- firebase-storage 16.1.0
- Glide 4.9.0


## 手順
- Storageに画像をアップロードする
- セキュリティールールを変更する
- Androidアプリで画像を取得する(実装)

## 実装


### Storageに画像をアップロードする

Firebaseプロジェクトの Storageを開き、右上のアイコンをクリックしてフォルダを追加。
フォルダ移動して、「ファイルをアップロード」ボタンから、画像をアップロードします。

![スクリーンショット 2019-03-19 1.12.15.png](https://qiita-image-store.s3.amazonaws.com/0/303516/6ce44030-053d-5e04-6c4f-8c6fd3eeb181.png)


### セキュリティールールを変更する
フォルダ"image"配下の全てのファイルを、認証不要で読み込みのみ許可します。
今回はサンプルアプリなので、認証不要にしましたが、実運用ではAuthenticationで認証する方が良いです。

```
service firebase.storage {
  match /b/{bucket}/o {
    match /image/{allPaths=**} {
      // allow read, write: if request.auth != null;
      allow read;
    }
  }
}
```


### Androidアプリで画像を取得する(実装)

```gradle:project/build.gradle
buildscript {
    ext.kotlin_version = '1.3.21'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.2.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
```

Firebaseが用意しているfirebase-ui-storageを使います。

``` gradle:app/build.gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'

apply plugin: 'com.google.gms.google-services'

android {
    dataBinding {
        enabled true
    }
}
dependencies {
    // kotlin
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

    // firebase strage and glide
    implementation 'com.google.firebase:firebase-storage:16.1.0'
    implementation 'com.firebaseui:firebase-ui-storage:4.1.0'
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    kapt 'com.github.bumptech.glide:compiler:4.9.0'
}
```
AppGlideModuleを継承したクラスを作成します。
@GlideModuleアノテーションをつけないと認識されないので注意。

``` Kotlin:MyAppGlideModule.kt
@GlideModule
class MyAppGlideModule: AppGlideModule() {

    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        // Register FirebaseImageLoader to handle StorageReference
        registry.append(StorageReference::class.java,
                InputStream::class.java,
                FirebaseImageLoader.Factory())
    }
}
```

StorageReferenceインスタンスを直接Glideに渡して画像表示することが可能です。

``` Kotlin:MainActivity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val storageRef = FirebaseStorage.getInstance().reference
        val imageRef = storageRef.child("sample.jpg")
        GlideApp.with(this)
                .load(imageRef)
                .into(imageView)
    }
```

以上。