使用 Firebase Data Connect(Android)构建应用

1. 概览

ddc52cd46f923cf1.png

在此 Codelab 中,您将把 Firebase Data Connect 与 Cloud SQL 数据库集成,以构建一个电影评价 Android 应用。您将学习如何:

  • 为 Firebase Data Connect 编写 GraphQL 架构
  • 编写查询和变更
  • 实现用户身份验证以保护您的数据

前提条件

  • 最新版本的 Android Studio
  • 搭载 API 级别 23 或更高级别的 Android 模拟器

学习内容

  • 如何使用本地模拟器设置 Firebase Data Connect。
  • 如何使用 Data Connect 和 GraphQL 设计数据架构。
  • 如何为影评应用编写查询和变更。
  • 如何生成 Kotlin SDK 并在 Android 应用中使用它。
  • (可选)如何将 Data Connect 服务部署到生产环境。

2. 设置示例项目

创建 Firebase 项目

  1. 使用您的 Google 账号登录 Firebase 控制台
  2. 点击相应按钮以创建新项目,然后输入项目名称(例如 Movie Review)。
  3. 点击继续
  4. 如果看到相关提示,请查看并接受 Firebase 条款,然后点击继续
  5. (可选)在 Firebase 控制台中启用 AI 辅助功能(称为“Gemini in Firebase”)。
  6. 在此 Codelab 中,您不需要使用 Google Analytics,因此请关闭 Google Analytics 选项。
  7. 点击创建项目,等待项目完成预配,然后点击继续

下载代码

运行以下命令以克隆本 Codelab 的示例代码。这将在您的机器上创建一个名为 codelab-dataconnect-android 的目录:

git clone https://github.com/firebaseextended/codelab-dataconnect-android.git

如果您的机器上没有 git,您也可以直接从 GitHub 下载代码

添加 Firebase 配置

  1. Firebase 控制台中,选择左侧导航栏中的“项目概览”。点击 Android 按钮以选择平台。当系统提示输入软件包名称时,请使用 com.google.firebase.example.dataconnect
  2. 点击“注册应用”,然后按照说明下载 google-services.json 文件,并将其移至您刚刚下载的代码的 app/ 目录中。接着点击“下一步”

3. 设置 Data Connect

安装

自动安装

codelab-dataconnect-android 目录中运行以下命令:

curl -sL https://firebase.tools/dataconnect | bash

此脚本会尝试为您设置开发环境并启动基于浏览器的 IDE。此 IDE 提供各种工具,包括预先捆绑的 VS Code 扩展程序,可帮助您管理架构、定义要在应用中使用的查询和突变,以及生成强类型 SDK。

运行脚本后,VS Code 应该会自动打开。

注意:如果您已安装桌面版 VS Code,脚本应会自动打开该应用。如果脚本失败,请按照以下手动安装步骤操作。

手动安装

  1. 安装 Visual Studio Code
  2. 安装 Node.js
  3. 在 VS Code 中,打开 codelab-dataconnect-android 目录。
  4. Visual Studio Code Marketplace 安装 Firebase Data Connect 扩展程序。

在项目中初始化 Data Connect

在左侧面板中,点击 Firebase 图标以打开 Data Connect VS Code 扩展程序界面:

  1. 点击使用 Google 账号登录按钮。系统会打开一个浏览器窗口;请按照说明使用您的 Google 账号登录该扩展程序。ef59f25a9e9cbfff.png
  2. 点击关联 Firebase 项目按钮,然后在控制台中选择您之前创建的项目。951a836ba0682494.png

点击 Run firebase init 按钮,然后按照集成终端中的步骤操作。

配置 SDK 生成

点击“Run firebase init”按钮后,Firebase Data Connect 扩展程序应会为您初始化一个 dataconnect/ 目录。

在 VS Code 中,打开 dataconnect/connector/connector.yaml 文件,您会看到默认配置。为了更轻松地直观呈现此 Codelab 中的代码生成,请将 connectorId 更改为 movies,并将软件包更改为 com.google.firebase.example.dataconnect.generated

connectorId: movies
generate:
  kotlinSdk:
    outputDir: ../../app/src/main/java
    package: com.google.firebase.example.dataconnect.generated

如需了解每种状态的含义,请参阅下文:

  • connectorId - 此连接器的唯一名称。
  • outputDir - 将存储生成的 Data Connect SDK 的路径。此路径相对于包含 connector.yaml 文件的目录。
  • package - 要在生成的 SDK 中使用的软件包名称。

启动 Firebase 模拟器

在 VS Code 中,点击 Start emulators 按钮。

93fb67962e96a7cb.png

您应该会在集成终端中看到模拟器启动。如果它正确启动,您应该会看到如下所示的输出:

8504ae0080923823.png

配置 Android 应用以使用本地模拟器

  1. 打开 Android Studio。
  2. 在 Android Studio 的欢迎界面中,点击“打开”按钮,然后选择 codelab-dataconnect-android 目录。等待 Gradle 同步。
  3. Gradle 同步完成后,打开 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 文件并调用 useEmulator()
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.instance

class MainActivity : ComponentActivity() {
  ...

  // Initialize Firebase Data Connect
  MoviesConnector.instance.dataConnect.useEmulator("10.0.2.2", 9399)

  ...
}

4. 定义架构并预先填充数据库

在本部分中,您将通过架构定义电影应用中关键实体之间的结构和关系。MovieUserReview 等实体会映射到数据库表,并使用 Firebase Data Connect 和 GraphQL 架构指令建立关系。

核心实体和关系

Movie 类型包含标题、流派和标记等关键详细信息,应用会使用这些信息进行搜索和创建电影个人资料。User 类型用于跟踪用户互动,例如评价和收藏。Review 将用户与电影联系起来,让应用显示用户生成的评分和反馈。

用户表

用户类型定义了通过撰写影评或将电影标记为喜爱来与电影互动的用户实体。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消注释(或添加)User 表定义:

# Users
# Suppose a user can leave reviews for movies
# user  -> reviews is a one to many relationship,
# movie -> reviews is a one to many relationship
# movie <-> user is a many to many relationship
type User @table {
  id: String! @col(name: "user_auth")
  username: String! @col(name: "username", dataType: "varchar(50)")
  # The following are generated by the user: User! field in the Review table
  # reviews_on_user 
  # movies_via_Review
}

电影表格

电影类型定义了电影实体的主要结构,包括标题、类型、发布年份和分级等字段。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消注释(或添加)Movie 表定义:

# Movies
type Movie @table {
  # The below parameter values are generated by default with @table, and can be edited manually.
  # implies directive `@col(name: "movie_id")`, generating a column name
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  genre: String
}

MovieMetadata 表

MovieMetadata 类型与 Movie 类型建立了一对一关系。它包含其他数据,例如电影的导演。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消注释(或添加)MovieMetadata 表定义:

# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique indicates a 1-1 relationship
  movie: Movie! @unique 
  # movieId: UUID <- this is created by the above reference
  rating: Float
  releaseYear: Int
  description: String
}

查看表格

Review 类型表示评价实体,并以多对多关系关联 User 类型和 Movie 类型(一个用户可以留下多条评价,每部电影也可以有多条评价)。

在 VS Code 中,打开 dataconnect/schema/schema.gql 文件,然后取消注释(或添加)Review 表定义:

# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  id: UUID! @default(expr: "uuidV4()")
  user: User!
  movie: Movie!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

自动生成的字段和默认值

该架构使用 @default(expr: "uuidV4()") 等表达式自动生成唯一 ID 和时间戳。例如,在创建新记录时,系统会自动使用 UUID 填充 Movie 和 Review 类型中的 id 字段。

插入模拟数据

定义架构后,您现在可以使用模拟数据预先填充数据库以进行测试。

  1. 在 VS Code 中,打开 dataconnect/moviedata_insert.gql。确保 Firebase Data Connect 扩展程序中的模拟器正在运行。
  2. 您应该会在文件顶部看到“运行(本地)”按钮。点击此按钮可将模拟电影数据插入到数据库中。

b070f025e573ab9b.png

  1. 检查“Data Connect Execution”终端,确认数据已成功添加。

e2058cb4db857058.png

数据就绪后,请继续执行下一步,了解如何在 Data Connect 中创建查询。

5. 创建用于列出电影的查询

首先,创建一个用于列出电影的查询。对于每部电影,您将获取其 ID、片名、图片网址和流派。

定义查询

在 VS Code 中,打开 dataconnect/connector/queries.gql 文件,然后取消注释(或添加)ListMovies 查询:

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}

如需测试新查询,请点击“运行(本地)”按钮,针对本地数据库执行查询。数据库中的电影列表应显示在“数据连接执行”终端的“结果”部分下。

822bf32321df4716.png

从 Android 应用中调用该函数

现在,您已在 Data Connect 模拟器中测试了查询,接下来可以将其添加到应用中。

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MoviesScreen.kt 文件,然后添加以下代码以网格格式显示电影列表:

import com.google.firebase.example.dataconnect.generated.ListMoviesQuery
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.execute
import com.google.firebase.example.dataconnect.generated.instance

@Composable
fun MoviesScreen(
    onMovieClicked: (id: String) -> Unit
) {
    var movies by remember { mutableStateOf(emptyList<ListMoviesQuery.Data.MoviesItem>()) }
    LaunchedEffect(Unit) {
        // Queries need to be executed in a coroutine context
        try {
          movies = MoviesConnector.instance.listMovies.execute().data.movies
        } catch (e: Exception) {
          // Will be done at a later step
        }
    }
    LazyVerticalGrid(GridCells.Adaptive(150.dp)) {
        items(movies) { movie ->
            MovieCard(
                movieId = movie.id.toString(),
                movieTitle = movie.title,
                movieImageUrl = movie.imageUrl,
                movieGenre = movie.genre,
                onMovieClicked = {
                    onMovieClicked(movie.id.toString())
                }
            )
        }
    }
}

运行应用

在 Android Studio 中,点击“运行”按钮以在 Android 模拟器中启动应用。

应用启动后,您应该会看到如下所示的界面:

ddc52cd46f923cf1.png

6. 创建电影详情查询

现在,应用可以列出电影了,接下来我们创建一个查询来显示每部电影的详细信息。

定义查询

在 VS Code 中,打开 dataconnect/connector/queries.gql 文件,然后取消注释(或添加)GetMovieById 查询:

# Get movie by id
query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    id
    title
    imageUrl
    genre
    metadata: movieMetadata_on_movie {
      rating
      releaseYear
      description
    }
    reviews: reviews_on_movie {
      id
      reviewText
      reviewDate
      rating
      user {
        id
        username
      }
    }
  }
}

从 Android 应用中调用该函数

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MovieDetailScreen.kt 文件并添加以下代码:

importcom.google.firebase.example.dataconnect.generated.GetMovieByIdQuery
importcom.google.firebase.example.dataconnect.generated.MoviesConnector
importcom.google.firebase.example.dataconnect.generated.execute
importcom.google.firebase.example.dataconnect.generated.instance

@Composable
fun MovieDetailScreen(
    movieId: String
) {
    var movie by remember { mutableStateOf<GetMovieByIdQuery.Data.Movie?>(null) }
    LaunchedEffect(Unit) {
        movie = MoviesConnector.instance.getMovieById.execute(
            UUID.fromString(movieId)
        ).data.movie
    }
    if (movie == null) {
        LoadingScreen()
    } else {
        MovieDetails(
            movieTitle = movie!!.title,
            movieImageUrl = movie!!.imageUrl,
            movieGenre = movie!!.genre,
            movieRating = movie!!.metadata?.rating,
            movieReleaseYear = movie!!.metadata?.releaseYear,
            movieDescription = movie!!.metadata?.description,
        )
    }
}

运行应用

在 Android Studio 中,点击“运行”按钮以在 Android 模拟器中启动应用。

7. 创建用于插入用户的 mutation

现在,应用能够显示数据了,接下来需要从应用中添加新数据。为了安全地执行此操作,您应使用 Firebase Authentication。

在此 Codelab 中,应用使用匿名身份验证来让用户登录,但为了提高应用的安全性,请考虑使用其他身份验证方法,例如电子邮件地址/密码身份验证或联合身份提供方。

定义突变

在 VS Code 中,打开 dataconnect/connector/mutations.gql 文件,然后取消注释(或添加)UpsertUser 查询:

# Upsert (update or insert) a user's username based on their auth.uid
mutation UpsertUser($username: String!) @auth(level: USER) {
  user_upsert(
    data: {
      id_expr: "auth.uid"
      username: $username
    }
  )
}

从 Android 应用中调用该函数

在 Android Studio 中,打开 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 文件并调用 mutation:

import com.google.firebase.example.dataconnect.generated.execute

LaunchedEffect(Unit) {
  // If there's no user signed in, sign in an anonymous user
  if (firebaseAuth.currentUser == null) {
    firebaseAuth.signInAnonymously().await()
    val newUsername = getRandomUsername()
    MoviesConnector.instance.upsertUser.execute(newUsername)
  }
}

运行应用

在 Android Studio 中,点击“运行”按钮以在 Android 模拟器中启动应用。

8. 恭喜

恭喜!您已成功将 Firebase Data Connect 添加到 Android 应用中!

现在,您已了解设置 Data Connect、创建查询和突变以及处理用户身份验证所需的关键步骤。

后续步骤

可选:部署到生产环境

到目前为止,此应用仅使用了 Firebase 模拟器。如果您想了解如何将此应用部署到真实的 Firebase 项目,请继续执行下一步。

9. (可选)部署应用

到目前为止,此应用完全是本地应用,所有数据都包含在 Firebase Emulator Suite 中。在本部分中,您将学习如何配置 Firebase 项目,以便此应用在生产环境中正常运行。

启用 Firebase Authentication

在 Firebase 控制台中,前往“身份验证”部分,然后点击“开始”。前往“登录方法”标签页,然后从提供方中选择“匿名登录”选项。

启用匿名登录方法,然后点击“保存”。

部署 Firebase Data Connect 架构

重要提示:如果您是首次在项目中部署架构,此过程将创建一个 Cloud SQL PostgreSQL 实例,这可能需要大约 15 分钟。在 Cloud SQL 实例准备就绪并与 Firebase Data Connect 集成之前,您将无法进行部署。

  1. 在 Firebase Data Connect VS Code 扩展程序界面中,点击部署到生产环境
  2. 您可能需要查看架构更改并批准可能具有破坏性的修改。系统会提示您执行以下操作:
    • 使用 firebase dataconnect:sql:diff 查看架构变更
    • 对更改感到满意后,请使用 firebase dataconnect:sql:migrate 启动的流程应用更改

您的 Cloud SQL for PostgreSQL 实例将使用最终部署的架构和数据进行更新。您可以在 Firebase 控制台中监控状态。

现在,您可以像使用本地模拟器一样,在 Firebase Data Connect 面板中点击“运行(生产)”,将数据添加到生产环境中。