Help us understand the problem. What is going on with this article?

Firebaseのサーバーレスアプリ開発について(Android編)

Firebaseサーバーレスアプリのニーズ

2~3年前からサーバーレスのアプリ開発(Android/iOS)が増えています。
特にFirebaseを使っているスタートアップをよく見かけます。

アプリの競争が激しい中、今はいいアプリを作るだけで売れる時代は終わっているかも知りません。
特に資金力の弱いスタトアップだと限られた資金で短期間に成果をあげることは難しいでしょう
資金調達の為にもより早くアプリを見せないといけないです。
そういったニーズの答えがFirebaseのサービスだと思います。

Firebaseサーバーレスのメリット&デメリット

メリット&デメリットはあくまで私の個人意見です。
以下の内容以外にもいっぱいあると思います。

メリット

  • サーバー開発期間がゼロ
  • サーバー管理が不要で開発に集中できる
  • 無料枠でも結構使える
  • Firestoreだとほぼリアルタイムで更新するのでチャット機能も簡単に実現できる

デメリット

その他

Firebaseサーバーレスの実装サンプル

本投稿ではサーバーレスの実装がどれだけ簡単にできるかをコードを中心に伝えたいと思います。
導入方法については次回に紹介します。

1.Firebase Authentication

会員登録とログイン関係の全ての機能を提供しています。
サーポートする認証方式は以下の画像を参考にしてください。
FirebaseでサーポートしてないLINEなどの認証は別の方法で実装ができます。
それについては次回に紹介します。

サーポートする認証方式は色々ありますが、
本投稿では「メール/パスワード」の認証方式だけをkotlinで書いて見ました。
- 会員登録、プロフィール変更、パスワード変更、ログイン、ログアウト、退会

a.会員登録
会員登録
    fun signup() {
        val auth = FirebaseAuth.getInstance()
        val email = "test@bizreach.co.jp"
        val password = "12345678"
        auth.createUserWithEmailAndPassword(email, password)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
会員登録後のAuthentication管理画面

b.プロフィール変更
プロフィール変更
    fun changeProfile() {
        val auth = FirebaseAuth.getInstance()
        val user = auth.currentUser ?: return

        val name = "山田"
        val profileUrl = "https://example.com/jane-q-user/profile.jpg"
        val profile = UserProfileChangeRequest.Builder()
            .setDisplayName(name)
            .setPhotoUri(Uri.parse(profileUrl))
            .build()
        user.updateProfile(profile)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
c.パスワード変更
パスワード変更
    fun changePassword() {
        val auth = FirebaseAuth.getInstance()
        val user = auth.currentUser ?: return
        val newPassword = "abcdefgh"
        user.updatePassword(newPassword)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
d.ログイン
ログイン
    fun login() {
        val auth = FirebaseAuth.getInstance()
        val email = "test@bizreach.co.jp"
        val password = "abcdefgh"
        auth.signInWithEmailAndPassword(email, password)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
e.ログアウト
ログアウト
    fun logout() {
        FirebaseAuth.getInstance().signOut()
    }
f.退会
退会
    fun withdrawal() {
        val auth = FirebaseAuth.getInstance()
        val user = auth.currentUser ?: return
        user.delete()
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
退会後のAuthentication管理画面

2.Cloud Firestore

NoSQLデータベースで、データの保存・変更・削除などの機能が簡単に使えます。
サンプルコードではToDo一覧、ToDo詳細機能をベースにデータを構成して実装して見ました。

a.ToDo登録
ToDo登録
    data class Todo(val title: String, val done: Boolean = false, val createdAt: Timestamp = Timestamp(Date()))

    fun addTodo() {
        val db = FirebaseFirestore.getInstance()
        val col = db.collection("todo_list")

        col.add(Todo("todo1"))
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }

        col.add(Todo("todo2"))
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
ToDo登録後のFirestore管理画面

b.ToDo編集
ToDo編集
    fun changeToDone() {
        val db = FirebaseFirestore.getInstance()
        val doc = db.collection("todo_list")
            .document("Hi2mlwN3lguMmfu76ZqX")

        doc.update("done", true)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
ToDo編集後のFirestore管理画面

c.ToDoの一覧取得
ToDoの一覧取得
    fun getTodoList() {
        val db = FirebaseFirestore.getInstance()
        db.collection("todo_list")
            .get()
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result ->
                /*成功*/
                result?.forEach {
                    val title = it["title"] as String
                    val done = it["done"] as Boolean
                    val createdAt = it["createdAt"] as Timestamp
                    val todo = Todo(title, done, createdAt)
                    Log.d("TAG", "todo_list: documentId=${it.id} todo=$todo")
                }
            }
    }
---- logcat
//todo_list: documentId=1aPGHKce0Fn4Osu65ioW todo=Todo(title=todo2, done=false, createdAt=Timestamp(seconds=1573460794, nanoseconds=820000000))
//todo_list: documentId=Hi2mlwN3lguMmfu76ZqX todo=Todo(title=todo1, done=true, createdAt=Timestamp(seconds=1573460794, nanoseconds=801000000))

d.ToDo削除
ToDo削除
    fun removeTodo() {
        val db = FirebaseFirestore.getInstance()
        val doc = db.collection("todo_list")
            .document("Hi2mlwN3lguMmfu76ZqX")

        doc.delete()
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
ToDo削除後のFirestore管理画面

3.Cloud Storage

ファイルの保存、変更、削除、URL参照ができます。
例えば会員のプロフィール写真などを保存して画面に表示する際に使います。
※内部的にはAWSのS3を使っています。

a.プロフィール画像のアップロード
プロフィール画像のアップロード
    fun uploadProfile() {
        val storage = FirebaseStorage.getInstance()
        val profileRef = storage.reference.child("images/profile.jpg")

        val bitmap = BitmapFactory.decodeResource(resources, R.drawable.profile)
        val baos = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
        val data = baos.toByteArray()

        profileRef.putBytes(data)
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
プロフィール画像のアップロード後のStorage管理画面

b.プロフィール画像URLの取得
プロフィール画像URLの取得
    fun getProfileUrl() {
        val storage = FirebaseStorage.getInstance()
        val profileRef = storage.reference.child("images/profile.jpg")
        profileRef.downloadUrl
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result ->
                /*成功*/
                Log.d("TAG", "profileUrl = $result")
            }
    }
----logcat
profileUrl = https://firebasestorage.googleapis.com/v0/b/fir-serverlessdemo.appspot.com/o/images%2Fprofile.jpg?alt=media&token=8bbb1678-76a7-470f-8773-9f3d8d8363f4
d.プロフィール画像の削除
プロフィール画像の削除
    fun deleteProfile() {
        val storage = FirebaseStorage.getInstance()
        val profileRef = storage.reference.child("images/profile.jpg")
        profileRef.delete()
            .addOnFailureListener { exception -> /* 失敗 */ }
            .addOnSuccessListener { result -> /*成功*/ }
    }
プロフィール画像の削除後のStorage管理画面

まとめ

Firebaseを使えば認証管理、DB管理、ファイル管理がどれだけ簡単にできるか理解頂けたと思います。

伝統的なネイティブアプリの開発方法がだんだん変わっています。
昔の開発では3人(インフラエンジニア/サーバーサイドエンジニア/フロントエンジニア)でやってたのが
今はだった一人でできる時代になりました。
Firebaseを使えば質の高いアプリ(Android/iOS/Web)をたった一人で開発することができます。

以前は物理サーバーを立ててから開発することが普通でしたが、
現在ではクラウドサービス(AWS、AZUL、GCP...)を使うのが当たり前のようになっています。
それと同じ様にネイティブアプリの開発でもサーバーレスのアプリ開発が広がり、
当たり前のような時代になるかも知りません。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした