初心者のためのAndroid Firebase

初心者のためのAndroid Firebase

Firebase

I. Firebaseとは

Google FirebaseはGoogleのバックエンドアプリケーションで開発者がiOSやandroid、Web appsの開発を行うことができるサービスです。Firebaseはトラッキングやその分析、クラッシュレポートまたその修正、マーケティングの調査、アプリケーションの検証のツールとして提供されています。Firebaseはたくさんのサービスがあります。今回はin-app messaging、cloud messages、そしてreal-time databasesについてご紹介したいと思います。

II. アプリにFirebaseを追加する

AndroidアプリケーションにFirebaseを入れる前に、AndroidアプリケーションをFirebaseに接続するためそのプロジェクトを構築する必要があります。Firebaseコンソールにログインをします。 https://console.firebase.google.com/?hl=en

Step 1: Firebaseにログインした後、”Create a project“をクリックします。

Step 2: ここからは新しくFirebaseプロジェクトを作成するための手順です。Android iconをクリックします。 

Step 3:Android Manifestのpackage nameと同じものを”Android package name“に入力してください。

 

Step 4:  google-services.json”をダウンロードしてください。そしてプロジェクトに追加してください。

  • Viewを切り替えるために”Project”をクリックしてください。そうするとプロジェクトのrootディレクトリが表示されます。”google-services.json“ファイルを”Project/~/app”フォルダにおきます。



Step 5: Firebase SDKを設定します。(画像参照)

1. build.gradle” (Project):

2. build.gradle” (app):

Step 6: 起動させFirebaseのアプリの確認を待ちます。成功のメッセージが表示されると“Continue to console”をクリックします。

III. In-App Message

1. 紹介

Firebase In-App Messagingは 狙ったユーザに対しアプリの主要な機能を動かすためテキストメッセージを送りユーザにアプリを起動させるように促すことができます。例えば、サブスクライバーやビデオ観賞、レベルの達成またはアイテムの購入を誘導するためユーザにin-app messageを送ります。
カードやバナー、モーダル、画像のようにカスタマイズすることができ、そしてトリガーをセットできます。そのため、一番効果があるタイミングで正確にそれを表示することができます。

2. 始め方

Step 1build.gradle” (app)に“implementation ‘com.google.firebase:firebase-inappmessaging-display:19.0.3’を追加します。そして”Sync Now“をクリックします。

Step 2: Firebase instance ID (Firebaseのin-app messageのテストに使用するID)を取得します。

private fun createInstanceId() {
    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "getInstanceId failed", task.exception)
            return@addOnCompleteListener
        }

        //create new instance id Token
        val msg = task.result?.id
        Log.d(TAG, "token: $msg")
    }
}

Step 3:アプリを起動させ”Logcat” ツールを開きます。ID tokenをそこで確認することができます。

Step 4: ID tokenをコピーし, Firebase コンソール -> “In-App Messaging“を開き, “Create your first campaign”をクリックします。

Step 5: “Message title” (例: Hello I’m FireBase)”Body” (optional), “Images” (ex: https://cdn.pixabay.com/photo/2015/10/12/14/54/coffee-983955_960_720.jpg)を入力します。

Button text“を追加します。

Step 6: “Test on Device”をクリックし, “Add an instance ID” フィールドにID tokenをペーストします。

Firebase In-App Messagingはクリックするとすぐに”Test“を送信します。それを見るためにはアプリをバックエンドへ移動し、テスト端末でアプリを再起動します。

結果:

Step 7: テストが成功した後、続けるために”Next”をクリックします。

メッセージを公開するために”Review“をクリックしてください。

Publish“をクリックすると、アプリにメッセージが送信されます。

結果:

IV. Cloud Message

1. 紹介

Firebase Cloud Messaging (FCM)は費用なしで確実にメッセージを届けるクロスプラットフォームメッセージソリューションです。FCMを使用し、メールや同期可能な他のデータでクライアントアプリケーションに知らせることができます。ユーザの再訪問やアプリの使用を継続させるプッシュ通知を送ることができます。
インスタントメッセージを使用するケースとして、メッセージはクライアントアプリに4KBまでのpayloadで送ることができる。

2. 始め方

Step 1: “implementation ‘com.google.firebase:firebase-messaging:20.1.0’ “を”build.gradle” (app)に追加する。そして”Sync Now“をクリックします。

Step 2 : AndroidManifestファイルにfilterを追加します。

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

MyFirebaseMessagingServiceはFirebaseMessagingServiceの拡張です。これはバックグラウンドでアプリにPush通知を受け取る以外にメッセージを扱うとき必要になります。フォアグランドでPush通知を受け取るためにはPayloadで受け取り、upstream messagesを送るなど、このサービスを使わなければならない。

line 23にエラーが表示されています。これはMyFirebaseMessagingServiceファイルがないために発生しているので、それを作ります。

.java.MyFirebaseMessagingServiceから<package>.MyFirebaseMessagingServiceにpackage nameを変更します。

Step 3 (optional): デフォルトアイコンと色を設定します。特にPush通知で変更したくなければこのステップをスキップして良いです。

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

Step 4 (Optional): Android 8.0 (API level 26)またはそれ以上から、notification channelsはsupported またはrecommendedになっています。FCMは基本設定としてdefault notification channelの使用を提供しています。
もし新たにchannelを作りたい、デフォルトのchannelにしたい場合はdefault_notification_channel_idに自分のデフォルトchannelとしてpush通知channelオブジェクトを利用してください。
FCMはnotification channelが明示的にセットされない限りこの値を使用します。もっと詳しく知りたければ、Manage notification channels
を参照してください。

  • res/values/strings.xmlを開き、この行を追加してください。
<string name="default_notification_channel_id">1</string>

  • AndroidManifestファイルを開き、このコードを追加してください。
<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id" />

 Step 5: 現在のregistration tokenを取得するためMainActivityを開き、この機能を追加します。

private fun createInstanceId() {
    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "getInstanceId failed", task.exception)
            return@addOnCompleteListener
        }

        //get id Token
        // Get new Instance ID token
        val token = task.result?.token

        // Log and toast
        Log.d(TAG, "token: $token")
        Toast.makeText(baseContext, "token: $token", Toast.LENGTH_SHORT).show()
    }
}

  • アプリを動作させ、Firebase instance IDを取得します。

Step 6: MyFirebaseMessagingServiceクラスに下記のコードを追加します。

class MyFirebaseMessagingService : FirebaseMessagingService() {
    companion object {
        private val TAG = this::class.java.simpleName
    }

    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")
        super.onNewToken(token)
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        Log.d(TAG, "From: ${remoteMessage.from}")

        remoteMessage.data.isNotEmpty().let {
        }

        remoteMessage.notification?.let {
            Log.d(TAG, "Message Notification Body: ${it.body}")
            it.body?.let { body ->
                sendNotification(body)
            }
        }
    }

    private fun sendNotification(messageBody: String) {
        val intent = Intent(this, CloudMessageActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)

        val channelId = getString(R.string.default_notification_channel_id)
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val notificationBuilder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_notifications)
            .setContentTitle("Mess Title")
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)

        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId, "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        notificationManager.notify(1, notificationBuilder.build())
    }
}

Step 7: Cloud Messagingのテスト

Notification Title, textimage (optional)を入力します。 ex: https://cdn.pixabay.com/photo/2017/07/07/02/05/symbol-2480161_960_720.png and send test message.

  • Logcat (step 5)からtokenを取得し追加します。

  • 結果:

Step 7: 作成とメッセージ送信

テストが成功した後で、続けるために”Next“を追加します。

  • メッセージを送信するため”Publish“を送信します。

結果:

V. Realtime Database

1. 紹介

Firebase Realtime Databaseはクラウドホスティングデータベースです。データはJson形式で保存され、クライアントに毎回リアルタイムに同期されます。iOS, Android JavaScript SDKを使ったあなたのクライアントのクロスプラットフォームアプリはrealtime database instanceに同期され、自動で最新のデータにアップデートされます。

2. Get start

Step 1“build.gradle”に“implementation ‘com.google.firebase:firebase-database:19.2.1’ ” (app)を追加します。そして”Sync Now“をクリックします。

Step 2: テストのためにrealtime databaseのrules設定します。

realtime databaseのrulesについてはこちらを確認してください。

Step 3: UserModelクラスを作成します。

data class UserModel(
    var id: String = "",
    var name: String = "",
    var age: Int = 0,
    var email: String = ""
) {
    override fun toString(): String {
        return "UserModel(id='$id', name='$name', age=$age, email='$email')"
    }
}

Step 4: 3つの項目(name, age and email)があるLayoutを作成し、User dataを含めるために1つのrecycler viewを追加します。
これが作成したlayoutです。

Step 5:
データベースを記述します。
最初にdatabaseReferenceを初期化します。

private fun initDatabase() {
    databaseReference = FirebaseDatabase.getInstance().reference
}

次に、入力した値を取得し、データベースに追加します。

private fun insertUser() {
    if (edt_name.text.isNullOrEmpty() || edt_age.text.isNullOrEmpty() || edt_email.text.isNullOrEmpty()) {
        Toast.makeText(this, "Some field are missing.", Toast.LENGTH_SHORT).show()
        return
    }

    //get key
    val key = databaseReference.child("User").push().key

    //get user data from edit text
    val user = UserModel(
        name = edt_name.text.toString(),
        age = edt_age.text.toString().toInt(),
        email = edt_email.text.toString()
    )

    key?.let {
        user.id = key

        // Write a data to the database
        databaseReference.child("User").child(key).setValue(user).addOnSuccessListener {
            clearText()
            //get user data from database
            getUser()
            //scroll to new item
            recycler_user.scrollToPosition(recyclerAdapter.userList.size - 1)
        }
            .addOnFailureListener {
                Toast.makeText(this, "Upload Error", Toast.LENGTH_SHORT).show()
            }
    }
}

Insertボタンのイベントのコードを追加します。

btn_insert.setOnClickListener {
    insertUser()
}

アプリの”Insert“ボタンをクリックした後で、データはすぐにFirebaseに送られます。

データの読み込み:

databaseReference.child("User").addValueEventListener(object : ValueEventListener {
    override fun onCancelled(dataError: DatabaseError) {
        Toast.makeText(this@DataBaseActivity, "Upload Error", Toast.LENGTH_SHORT).show()
    }

    override fun onDataChange(dataSnapshot: DataSnapshot) {
        
        //get user list from database
        val list = dataSnapshot.children.mapNotNull {
            it.getValue(UserModel::class.java)
        }
        list.forEach {
            Log.i("Users", it.toString())
        }
        //add to recycler view
        if (list.isNotEmpty()) {
            recyclerAdapter.userList.clear()
            recyclerAdapter.userList.addAll(list)
            recyclerAdapter.notifyDataSetChanged()
        }
    }
})

データの更新:

private fun updateUser() {
    user?.let {
        //create new user object
        val user = UserModel(
            it.id,
            edt_name.text.toString(),
            edt_age.text.toString().toInt(),
            edt_email.text.toString()
        )
        //update user
        databaseReference.child("User/${it.id}").setValue(user)
    }
}

データの削除:

private fun deleteUser() {
    // get user id
    val query =
        databaseReference.child("User").orderByChild("id").equalTo(user?.id)

    query.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            for (user in dataSnapshot.children) {
                //remove user
                user.ref.removeValue().addOnSuccessListener {
                    clearText()
                }
            }
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.e(
                TAG,
                "onCancelled",
                databaseError.toException()
            )
        }
    })
    getUser()
}

VI. 参考文献

https://firebase.google.com/docs/guides

https://github.com/firebase/quickstart-android/blob/995be41782f84b3c54e41d7d7e5d3a5048fe329e/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/kotlin/MyFirebaseMessagingService.kt#L65-L77

https://proandroiddev.com/firebase-android-playground-realtime-database-560d4e18404a

https://www.learnhowtoprogram.com/android/data-persistence/firebase-reading-data-and-event-listeners