Firebase Realtime DatabaseをAndroidアプリからKotlinで使ってみる

## Firebaeの設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/7132/251e7fd5-d1fb-c9b5-56de-b9a39cf5e381.png)

### Firebaseのプロジェクトを作成
https://console.firebase.google.com/ にアクセスし、新規プロジェクトを作成します。
既存のものを使う場合は、そちらを使用してください。

### FirebaseにAndroidアプリを登録する
アプリのパッケージ名を入力し、アプリを登録します。
複数アプリがある場合はアプリ毎に登録が必要です。
<img width="1542" alt="スクリーンショット 2017-07-26 6.46.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/7132/874030bb-92e2-ed57-bc4f-3cdb4265d079.png">

### google-services.jsonを配置する
アプリ登録後に作成された設定ファイルをダウンロードし、`app`配下にファイルを保存します。

`./app/google-services.json`
<img width="472" alt="スクリーンショット 2017-07-26 7.04.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/7132/eeae792d-c93f-f8d6-86c6-58422232801e.png">

### Gradleにclasspathを追加

プロジェクトレベルの`build.gradle`に
`classpath 'com.google.gms:google-services:3.1.0'`をdependenciesの中に追記します。

```bash:./build.gradle
buildscript {
    ext.kotlin_version = '1.1.3-2'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha8'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:3.1.0'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
```

### Gradleにpluginを追加

アプリレベルの`build.gradle`に
`apply plugin: 'com.google.gms.google-services'`を最後に追記します。

```bash:./app/build.gradle
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "tokyo.ibot.thor"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.0'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.0'
}

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


ここまでで、Firebaseを使う準備は完了です。


## Realtime Databaseの設定

### ルールを変更
Realtime Databaseの`ルール`タブに移動し中身を変更します。

<img width="1560" alt="スクリーンショット 2017-07-26 7.20.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/7132/0ff79a2e-53fe-5d77-2a20-2eff7f32c0d2.png">

```json
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
```

これで誰にでも読み書きができるようになります。
もちろん、セキュリティ上は良くないので実際に使用する場合には認証を入れる必要があります。


### Gradleにdependencyを追加

アプリレベルの`build.gradle`に
`compile 'com.google.firebase:firebase-database:11.0.2' `を追記します。

```bash:./app/build.gradle
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "tokyo.ibot.thor"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.0'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.0'
    compile 'com.google.firebase:firebase-database:11.0.2'
}

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

Realtime Databaseを使う準備も完了


## Realtime Databaseに読み書きしてみる

### データの更新
適当に`MainActivity`の`onCreate`にRealtime Databaseへ書き込みするコードを追記してみます。

```kotlin:MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.google.firebase.database.FirebaseDatabase

class MainActivity : AppCompatActivity() {

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

        val key = "color"
        val value = "red"

        val database = FirebaseDatabase.getInstance()
        val ref = database.getReference(key)
        ref.setValue(value)
    }
}
```

これを実行すると、Webのコンソール上に反映されました。
![Group.png](https://qiita-image-store.s3.amazonaws.com/0/7132/8bff5ed8-6ea6-80bb-d0f3-2fd14568c81b.png)

`value`の値を変更し、再実行するとコンソールもリアルタイムに変更されているのがわかります。
<img width="163" alt="スクリーンショット 2017-07-26 7.45.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/7132/841b11a1-3a63-e44d-be12-021b484b9c7b.png">


### データの読み込み
読み込みでは変更をリアルタイムに通知されるため、`addValueEventListener`にコードを書いていきます。
`textView`の値がリアルタイムに変更されるように実装しました。

```kotlin:MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        val key = "color"
        val value = "blue"

        val database = FirebaseDatabase.getInstance()
        val ref = database.getReference(key)
        ref.setValue(value)


        ref.addValueEventListener(object: ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                val value = dataSnapshot.value
                textView.text = value.toString()
            }

            override fun onCancelled(error: DatabaseError) {
                Log.w("onCancelled", "error:", error.toException())
            }
        })
    }
}
```

コンソール上で値を変更すると、アプリに通知され`textView`に反映されます。


## おわり
実際に作ったAndroidアプリをスマホとAndroid Thingsにそれぞれインストールし、Firebase経由で繋げてみました。
Android Thingsでも問題なく使えて、実装も無理がなく便利でした。

<blockquote class="twitter-video" data-lang="ja"><p lang="und" dir="ltr"><a href="https://twitter.com/hashtag/androidthings?src=hash">#androidthings</a> <a href="https://twitter.com/hashtag/firebase?src=hash">#firebase</a> <a href="https://t.co/0yrCDFF2gr">pic.twitter.com/0yrCDFF2gr</a></p>&mdash; なりたけいすけ (@narikei1030) <a href="https://twitter.com/narikei1030/status/889976159894618112">2017年7月25日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>