Firebase と Jetpack Compose を使用して Android アプリを構築する

1. はじめに

最終更新日: 2022-11-16

Firebase と Jetpack Compose を使用して Android アプリを構築する

このコードラボでは、 Make It Soという Android アプリを構築します。このアプリの UI は、ネイティブ UI を構築するための Android の最新ツールキットであるJetpack Compose を使用して完全に構築されています。これは直感的であり、.xml ファイルを作成してアクティビティ、フラグメント、またはビューにバインドするよりも必要なコードが少なくなります。

Firebase と Jetpack Compose がどのように連携して機能するかを理解するための最初のステップは、最新の Android アーキテクチャを理解することです。優れたアーキテクチャでは、コンポーネントがどのように編成され、相互に通信するかが非常に明確になるため、システムが理解しやすく、開発しやすく、保守しやすくなります。 Android の世界では、推奨されるアーキテクチャはModel - View - ViewModelと呼ばれます。モデルは、アプリケーション内のデータにアクセスするレイヤーを表します。ビューはUI レイヤーであり、ビジネス ロジックについては何も認識する必要はありません。 ViewModelはビジネス ロジックが適用される場所であり、 ViewModel がモデル層を呼び出す必要がある場合があります。

この記事を読んで、Jetpack Compose で構築された Android アプリにModel - View - ViewModel がどのように適用されるかを理解することを強くお勧めします。これにより、コードベースが理解しやすくなり、次のステップを完了しやすくなります。

何を構築するか

Make It So は、ユーザーがタスクを追加および編集したり、フラグ、優先順位、期日を追加したり、タスクを完了としてマークしたりできるシンプルな To-Do リスト アプリケーションです。以下の画像は、このアプリケーションの 2 つのメイン ページ (タスク作成ページと作成されたタスクのリストを含むメイン ページ) を示しています。

「タスクの追加」画面にしますホーム画面を作る

このアプリに欠けているいくつかの機能を追加します。

  • メールアドレスとパスワードでユーザーを認証する
  • Firestore コレクションにリスナーを追加し、UI が変更に反応できるようにする
  • カスタム トレースを追加して、アプリ内の特定のコードのパフォーマンスを監視します
  • Remote Config を使用して機能切り替えを作成し、段階的ロールアウトを使用して起動します

学べること

  • 最新の Android アプリケーションで Firebase Authentication、Performance Monitoring、Remote Config、Cloud Firestore を使用する方法
  • Firebase API を MVVM アーキテクチャに適合させる方法
  • Firebase API で行われた変更を Compose UI に反映する方法

必要なもの

2. サンプルアプリを入手して Firebase をセットアップする

サンプルアプリのコードを取得する

コマンドラインから GitHub リポジトリのクローンを作成します。

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Firebaseをセットアップする

まず最初に行う必要があるのは、以下に示すように、 Firebase コンソールに移動し、[+ プロジェクトの追加] ボタンをクリックして Firebase プロジェクトを作成することです。

Firebaseコンソール

画面の手順に従ってプロジェクトの作成を完了します。

各 Firebase プロジェクト内で、Android、iOS、Web、Flutter、Unity 用のさまざまなアプリを作成できます。ここに示すように、Android オプションを選択します。

Firebase プロジェクトの概要

次に、次の手順に従います。

  1. パッケージ名としてcom.example.makeitsoと入力し、必要に応じてニックネームを入力します。このコードラボでは、デバッグ署名証明書を追加する必要はありません。
  2. [次へ]をクリックしてアプリを登録し、Firebase 構成ファイルにアクセスします。
  3. 「Download google-services.json」をクリックして構成ファイルをダウンロードし、 make-it-so-android/appディレクトリに保存します。
  4. 「次へ」をクリックします。 Firebase SDK はサンプル プロジェクトのbuild.gradleファイルにすでに含まれているため、 [次へ]をクリックして次のステップに進みます。
  5. 「コンソールに進む」をクリックして終了します。

Make it Soアプリを適切に動作させるには、コードに移動する前にコンソールで 2 つのことを行う必要があります。それは、認証プロバイダーを有効にすることと、Firestore データベースを作成することです。まず、ユーザーがアプリにログインできるように認証を有効にしましょう。

  1. 「ビルド」メニューから「認証」を選択し、 「開始」をクリックします。
  2. [サインイン方法]カードから[電子メール/パスワード]を選択し、有効にします。
  3. 次に、 [新しいプロバイダーの追加]をクリックし、 [匿名]を選択して有効にします。

次にFirestoreを設定します。 Firestore を使用して、サインインしているユーザーのタスクを保存します。各ユーザーは、データベースのコレクション内で独自のドキュメントを取得します。

  1. [構築]メニューから[Firestore]を選択し、 [データベースの作成]をクリックします。
  2. [運用モードで開始] を有効のままにして、 [次へ]をクリックします。
  3. プロンプトが表示されたら、Cloud Firestore データを保存する場所を選択します。本番アプリを開発するときは、これを大多数のユーザーに近いリージョンに配置し、Functions などの他の Firebase サービスと共通にする必要があります。このコードラボでは、デフォルトのリージョンをそのまま使用することも、最も近いリージョンを選択することもできます。
  4. [有効にする]をクリックして、Firestore データベースをプロビジョニングします。

Firestore データベースに堅牢なセキュリティ ルールを構築してみましょう。 Firestore ダッシュボードを開き、 [ルール]タブに移動します。次に、セキュリティ ルールを次のように更新します。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

これらのルールは基本的に、アプリのサインインしているユーザーはすべて、任意のコレクション内で自分用のドキュメントを作成できることを規定しています。その後、ドキュメントを作成すると、そのドキュメントを作成したユーザーのみがそのドキュメントを表示、更新、削除できるようになります。

アプリケーションを実行する

これでアプリケーションを実行する準備が整いました。 Android Studio でmake-it-so-android/startフォルダーを開き、アプリを実行します (Android エミュレーターまたは実際の Android デバイスを使用して実行できます)。

3. Firebase認証

どの機能を追加しますか?

Make It Soサンプル アプリの現在の状態では、ユーザーは最初にサインインしなくてもアプリの使用を開始できます。これを実現するために匿名認証を使用します。ただし、匿名アカウントを使用すると、ユーザーは他のデバイス上のデータにアクセスしたり、将来のセッションにアクセスしたりすることはできません。匿名認証はウォーム オンボーディングには便利ですが、ユーザーが別のサインイン形式に変換するオプションを常に提供する必要があります。これを念頭に置いて、このコードラボでは、 Make It Soアプリに電子メールとパスワードの認証を追加します。

コードを書く時間です!

ユーザーがメールアドレスとパスワードを入力してアカウントを作成したらすぐに、Firebase Authentication API にメール認証情報を要求し、新しい認証情報を匿名アカウントにリンクする必要があります。 Android Studio でAccountServiceImpl.ktファイルを開き、 linkAccount関数を次のように更新します。

モデル/サービス/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

次に、 SignUpViewModel.ktを開き、 onSignUpClick関数のlaunchCatchingブロック内でサービスlinkAccount関数を呼び出します。

スクリーン/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

まず認証を試み、呼び出しが成功すると、次の画面 ( SettingsScreen ) に進みます。これらの呼び出しをlaunchCatchingブロック内で実行しているとき、最初の行でエラーが発生すると、例外がキャッチされて処理され、2 行目にはまったく到達しません。

ユーザーはすでに認証されているため、 SettingsScreenを再度開いたらすぐに、 「サインイン」と「アカウントの作成」のオプションが消えていることを確認する必要があります。これを行うには、 SettingsViewModelで現在のユーザーのステータス ( AccountService.ktで入手可能) をリッスンさせ、アカウントが匿名かどうかを確認します。これを行うには、 SettingsViewModel.ktuiState次のように更新します。

画面/設定/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

最後に行う必要があるのは、 SettingsScreen.ktuiState更新して、 SettingsViewModelによって発行された状態を収集することです。

画面/設定/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

これで、ユーザーが変わるたびに、 SettingsScreenが再構成され、ユーザーの新しい認証状態に応じてオプションが表示されます。

テストの時間です!

Make it Soを実行し、画面の右上隅にある歯車アイコンをクリックして設定に移動します。そこから、「アカウントの作成」オプションをクリックします。

Make it So設定画面Make it So サインアップ画面

有効な電子メールと強力なパスワードを入力してアカウントを作成します。これは機能し、設定ページにリダイレクトされるはずです。そこには、サインアウトとアカウントの削除という 2 つの新しいオプションが表示されます。 Firebase コンソールの認証ダッシュボードで [ユーザー] タブをクリックすると、作成された新しいアカウントを確認できます。

4.クラウドファイアストア

どの機能を追加しますか?

Cloud Firestore の場合、 Make it Soに表示されるタスクを表すドキュメントを保存する Firestore コレクションにリスナーを追加します。このリスナーを追加すると、このコレクションに対して行われたすべての更新を受け取るようになります。

コードを書く時間です!

StorageServiceImpl.ktで利用可能なFlow次のように更新します。

モデル/サービス/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

このコードは、 user.idに基づいてタスク コレクションにリスナーを追加しています。各タスクは、 tasksという名前のコレクション内のドキュメントによって表され、それぞれのタスクにはuserIdという名前のフィールドがあります。 currentUserのステータスが変更された場合 (サインアウトなどにより)、新しいFlowが生成されることに注意してください。

次に、 TasksViewModel.ktFlowにサービス内と同じものを反映させる必要があります。

画面/タスク/TasksViewModel.kt

val tasks = storageService.tasks

最後に、UI を表すTasksScreens.kt内のcomposable functionにこのフローを認識させ、状態として収集します。状態が変化するたびに、コンポーザブル関数は自動的に再構成し、最新の状態をユーザーに表示します。これをTasksScreen composable functionに追加します。

画面/タスク/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

コンポーズ可能な関数がこれらの状態にアクセスできるようになると、 LazyColumn (画面にリストを表示するために使用する構造) を次のように更新できます。

画面/タスク/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

テストの時間です!

機能することをテストするには、アプリを使用して新しいタスクを追加します (画面の右下隅にある追加ボタンをクリックします)。タスクの作成が完了すると、Firestore コンソールの Firestore コレクションにタスクが表示されます。同じアカウントを使用して他のデバイスでMake it Soにログインすると、To Do アイテムを編集し、すべてのデバイスでリアルタイムで更新されるのを確認できます。

5. パフォーマンスの監視

どの機能を追加しますか?

パフォーマンスが良くなく、アプリを使用して簡単なタスクを完了するのに時間がかかりすぎる場合、ユーザーはアプリの使用を断念する可能性が非常に高いため、パフォーマンスは注意を払うべき非常に重要な点です。そのため、ユーザーがアプリ内で行う特定のジャーニーに関する指標を収集すると便利な場合があります。これを支援するために、Firebase Performance Monitoring はカスタム トレースを提供します。次の手順に従ってカスタム トレースを追加し、 Make it Soのさまざまなコード部分でパフォーマンスを測定します。

コードを書く時間です!

Performance.ktファイルを開くと、trace というインライン関数が表示されます。この関数は、パフォーマンス監視 API を呼び出してカスタム トレースを作成し、トレース名をパラメータとして渡します。表示されるもう 1 つのパラメーターは、監視するコードのブロックです。各トレースに対して収集されるデフォルトのメトリックは、完全に実行されるまでにかかる時間です。

モデル/サービス/パフォーマンス.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

コードベースのどの部分を測定することが重要だと思うかを選択し、そこにカスタム トレースを追加できます。このコードラボで前に示した ( AccountServiceImpl.kt内) linkAccount関数にカスタム トレースを追加する例を次に示します。

モデル/サービス/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

今ではあなたの番です! Make it Soアプリにいくつかのカスタム トレースを追加し、次のセクションに進んで、期待どおりに動作するかどうかをテストします。

テストの時間です!

カスタム トレースの追加が完了したら、アプリを実行し、測定したい特徴を数回使用してください。次に、Firebase コンソールに移動し、パフォーマンス ダッシュボードに移動します。画面の下部には、 [ネットワーク リクエスト][カスタム トレース] 、および[画面レンダリング]の 3 つのタブがあります。

[カスタム トレース]タブに移動し、コードベースに追加したトレースがそこに表示されていること、およびこれらのコードの実行に通常どれくらい時間がかかるかを確認できることを確認します。

6. リモート設定

どの機能を追加しますか?

Remote Config には、アプリの外観をリモートで変更することから、さまざまなユーザー セグメントに合わせてさまざまな動作を構成することまで、さまざまな使用例があります。このコードラボでは、Remote Config を使用して、 Make it Soアプリの新しい編集タスク機能を表示または非表示にする機能切り替えを作成します。

コードを書く時間です!

最初に行う必要があるのは、Firebase コンソールで構成を作成することです。これを行うには、 Remote Config ダッシュボードに移動し、 [パラメーターの追加]ボタンをクリックする必要があります。以下の画像に従ってフィールドに入力します。

Remote Config パラメータの作成ダイアログ

すべてのフィールドに入力したら、 「保存」ボタンをクリックしてから「公開」をクリックします。パラメータが作成され、コードベースで使用できるようになったので、新しい値を取得するコードをアプリに追加する必要があります。 ConfigurationServiceImpl.ktファイルを開き、次の 2 つの関数の実装を更新します。

モデル/サービス/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

最初の関数はサーバーから値をフェッチし、アプリが起動するとすぐにSplashViewModel.ktで呼び出されます。これは、最初からすべての画面で最新の値を確実に利用できるようにするための最良の方法です。ユーザーが何かをしている最中に、後から UI やアプリの動作を変更すると、ユーザー エクスペリエンスは良くありません。

2 番目の関数は、コンソールで作成したパラメータに対して公開されたブール値を返します。そして、 loadTaskOptions関数に次のコードを追加して、この情報をTasksViewModel.ktで取得する必要があります。

画面/タスク/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

1 行目の値を取得し、それを使用して 2 行目のタスク項目のメニュー オプションをロードしています。値がfalseの場合、メニューに編集オプションが含まれないことを意味します。オプションのリストが得られたので、UI にそれを正しく表示させる必要があります。 Jetpack Compose を使用してアプリを構築しているときは、 TasksScreenの UI がどのように見えるかを宣言するcomposable functionを探す必要があります。そこで、 TasksScreen.ktファイルを開き、 TasksViewModel.ktで使用可能なオプションを指すようにLazyColumを更新します。

画面/タスク/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem単一タスクの UI がどのように見えるかを宣言する別のcomposable functionです。また、各タスクにはオプションを含むメニューがあり、ユーザーがタスクの最後にある 3 点アイコンをクリックすると表示されます。

テストの時間です!

これでアプリを実行する準備が整いました。 Firebase コンソールを使用して公開した値がアプリの動作と一致していることを確認します。

  • falseの場合、3 点アイコンをクリックすると 2 つのオプションのみが表示されます。
  • trueの場合、3 点アイコンをクリックすると 3 つのオプションが表示されます。

コンソールで値を数回変更し、アプリを再起動してみてください。 Remote Config を使用すると、アプリで新しい機能を簡単に起動できるようになります。

7. おめでとうございます

おめでとうございます。Firebase と Jetpack Compose を使用して Android アプリが正常に構築されました。

UI 用に Jetpack Compose で完全に構築された Android アプリに Firebase Authentication、Performance Monitoring、Remote Config、Cloud Firestore を追加し、推奨される MVVM アーキテクチャに適合させました。

参考文献

参考資料