Firebase quickstart-android 各模块功能深度补充详解

复制代码
Firebase quickstart-android 进阶用法、完整业务场景代码、Android 高版本适配、高频报错解决方案**,同时完善辅助模块细节,以及模块间联动逻辑,帮助开发者快速将示例代码落地到实际项目,避开所有集成雷区。

# 一、身份认证类模块(补充进阶用法)

## 1. auth 模块(补充进阶功能+报错解决)

### (1)进阶功能:账号关联与令牌管理

实际开发中,常遇到“匿名登录转永久账号”“多账号关联”(如Google登录关联邮箱账号)、“ID Token 验证”(前后端交互),示例代码如下:

```kotlin
// 1. 匿名登录转永久账号(绑定邮箱/密码)
val auth = FirebaseAuth.getInstance()
val anonymousUser = auth.currentUser ?: return
// 创建邮箱/密码凭证
val credential = EmailAuthProvider.getCredential("test@example.com", "123456")
// 关联账号(匿名账号数据会自动迁移到新账号)
anonymousUser.linkWithCredential(credential)
    .addOnSuccessListener { result ->
        val user = result.user // 关联后的永久账号
    }
    .addOnFailureListener { e ->
        // 关联失败(如邮箱已被其他账号占用)
    }

// 2. ID Token 验证(前端获取Token,后端校验身份)
auth.currentUser?.getIdToken(true) // true表示强制刷新Token
    ?.addOnSuccessListener { tokenResult ->
        val idToken = tokenResult.token // 获取ID Token
        // 发送Token到后端,后端通过Firebase Admin SDK校验
        Log.d("AuthToken", "ID Token: $idToken")
    }

// 3. 多账号切换(退出当前账号,登录另一个账号,保留之前账号会话)
auth.signInWithEmailAndPassword(email1, password1) // 登录账号1
auth.signInWithEmailAndPassword(email2, password2) // 登录账号2(默认覆盖当前会话)
// 如需保留多账号会话,需使用 FirebaseAuth.getInstance(FirebaseApp.getInstance("secondary")) 创建新实例
```

### (2)高频报错及解决方案

- **报错1**:Google登录提示“signInResult:failed code=10”(无权限)
            
解决:① 在 Firebase 控制台「项目设置→应用→Android应用→SHA证书指纹」,添加本地调试SHA-1和发布版SHA-1;② 确保 Google 登录在 Firebase 控制台「Authentication→登录方式」中已开启;③ 同步 Gradle 后,清理项目(Build→Clean Project)再运行。
        

- **报错2**:手机号验证码提示“Too many requests”(请求过于频繁)
            
解决:在 Firebase 控制台「Authentication→登录方式→手机号」,添加测试手机号(无需真实验证码,直接通过测试模式验证);生产环境需限制验证码发送频率(如1分钟内最多1次)。

- **报错3**:注销账号后,重新登录提示“user not found”
            
解决:注销账号时,需先调用 `auth.signOut()` 退出登录,再调用 `auth.currentUser?.delete()` 删除账号,避免会话残留导致的异常。
        

## 2. auth-phone 模块(补充细节优化)

该模块核心补充「SMS Retriever API 自动填充验证码」,无需用户手动输入,优化用户体验,完整配置步骤如下:

```kotlin
// 1. 添加依赖(模块已内置,可参考)
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'

// 2. 注册 SMS Retriever 广播接收器
class SmsBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent?.action) {
            val extras = intent.extras
            val status = extras?.get(SmsRetriever.EXTRA_STATUS) as Status
            when (status.statusCode) {
                SmsRetriever.STATUS_SUCCESS -> {
                    // 获取验证码短信内容
                    val message = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String
                    // 提取验证码(示例:短信内容为“【Firebase】您的验证码是123456”)
                    val smsCode = message.replace(Regex("[^0-9]"), "")
                    // 自动填充到输入框
                    findViewById<EditText>(R.id.smsCodeEt).setText(smsCode)
                }
                SmsRetriever.STATUS_TIMEOUT -> {
                    // 验证码获取超时(5分钟),提示用户手动输入
                }
            }
        }
    }
}

// 3. 在 Activity 中启动 SMS Retriever
private fun startSmsRetriever() {
    val client = SmsRetriever.getClient(this)
    val task = client.startSmsRetriever()
    task.addOnSuccessListener {
        // 启动成功,等待接收验证码
    }
    task.addOnFailureListener {
        // 启动失败,提示用户手动输入
    }
}
```

注意:短信内容需包含 App 的签名哈希值(可通过 Firebase 控制台获取),否则无法自动提取验证码。

# 二、数据库类模块(补充高级用法+安全规则)

## 1. database 模块(补充安全规则+离线优化)

### (1)安全规则进阶配置(生产环境必配)

此前仅提供测试规则(全读写),生产环境需按“用户只能操作自己的数据”配置规则,示例如下(适配 /users/{uid} 路径):

```json
// 生产环境安全规则(仅授权用户可读写自己的信息)
{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid", // 仅当前登录用户可读取自己的数据
        ".write": "$uid === auth.uid" // 仅当前登录用户可修改自己的数据
      }
    },
    "public": {
      ".read": true, // 公开可读(如公告、商品列表)
      ".write": false // 禁止客户端写入,仅通过云函数修改
    }
  }
}
```

规则调试技巧:在 Firebase 控制台「Realtime Database→规则→模拟器」,可模拟不同用户(登录/未登录)的读写操作,验证规则是否生效。

### (2)离线优化进阶

Realtime Database 默认开启离线持久化,但可通过以下配置优化离线体验:

```kotlin
val database = FirebaseDatabase.getInstance()
// 1. 限制离线缓存大小(避免占用过多内存,默认无限制)
database.setPersistenceCacheSizeBytes(1024 * 1024 * 10) // 10MB

// 2. 手动控制离线同步(断网时暂停同步,联网后恢复)
database.goOffline() // 暂停同步(断网时调用)
database.goOnline() // 恢复同步(联网时调用)

// 3. 监听网络状态,自动切换离线/在线模式
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        database.goOnline() // 联网,恢复同步
    }

    override fun onLost(network: Network) {
        super.onLost(network)
        database.goOffline() // 断网,暂停同步
    }
})
```

## 2. firestore 模块(补充分页+批量操作+索引优化)

### (1)分页查询进阶(避免一次性加载过多数据)

实际开发中,列表数据需分页加载(如下拉加载更多),示例代码如下:

```kotlin
val db = FirebaseFirestore.getInstance()
val usersCol = db.collection("users")
var lastVisible: DocumentSnapshot? = null // 记录上一页最后一条数据的快照

// 加载第一页(10条数据)
fun loadFirstPage() {
    usersCol.orderBy("createTime", Query.Direction.DESCENDING)
        .limit(10)
        .get()
        .addOnSuccessListener { snapshot ->
            if (!snapshot.isEmpty) {
                lastVisible = snapshot.documents.last() // 记录最后一条数据
                // 解析数据并展示
                for (doc in snapshot) {
                    val user = doc.toObject(User::class.java)
                }
            }
        }
}

// 加载下一页(下拉加载更多)
fun loadNextPage() {
    if (lastVisible == null) return
    usersCol.orderBy("createTime", Query.Direction.DESCENDING)
        .startAfter(lastVisible) // 从上次最后一条数据之后开始加载
        .limit(10)
        .get()
        .addOnSuccessListener { snapshot ->
            if (!snapshot.isEmpty) {
                lastVisible = snapshot.documents.last()
                // 解析数据并追加到列表
            } else {
                // 没有更多数据
            }
        }
}
```

### (2)批量操作(避免频繁调用API)

批量新增/删除/修改数据,可减少API调用次数,提升性能:

```kotlin
val db = FirebaseFirestore.getInstance()
val batch = db.batch()

// 1. 批量新增3条数据
val user1 = User("1", "张三", 20)
val user2 = User("2", "李四", 22)
val user3 = User("3", "王五", 25)
batch.set(usersCol.document(user1.id), user1)
batch.set(usersCol.document(user2.id), user2)
batch.set(usersCol.document(user3.id), user3)

// 2. 批量删除2条数据
batch.delete(usersCol.document("4"))
batch.delete(usersCol.document("5"))

// 3. 批量修改1条数据
batch.update(usersCol.document("1"), "age", 21)

// 执行批量操作
batch.commit()
    .addOnSuccessListener { Log.d("Firestore", "批量操作成功") }
    .addOnFailureListener { e -> Log.e("Firestore", "批量操作失败:${e.message}") }
```

### (3)索引优化(解决复合查询卡顿)

当复合查询(如 whereGreaterThan + whereEqualTo)数据量较大时,需创建复合索引提升查询速度,步骤如下:

1. 运行查询,Logcat 会提示“Missing index”,并给出索引创建链接;

2. 点击链接,自动跳转到 Firebase 控制台「Firestore→索引→复合索引」,确认索引字段(如 age、city)和排序方式;

3. 创建索引(需等待几分钟生效),生效后查询速度会显著提升。

注意:索引会占用额外存储空间,避免创建不必要的索引(如单一字段查询无需创建复合索引)。

## 3. firestore-kotlin 模块(补充协程完整用法)

该模块基于 Kotlin 协程,替代传统回调,代码更简洁,支持 Flow 实时监听,完整示例如下:

```kotlin
// 1. 依赖(模块已内置)
implementation 'com.google.firebase:firebase-firestore-ktx:24.10.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'

// 2. 协程版查询(单条数据)
lifecycleScope.launch {
    val userDoc = usersCol.document("1").get().await() // 替代回调,直接获取结果
    if (userDoc.exists()) {
        val user = userDoc.toObject(User::class.java)
    } else {
        // 数据不存在
    }
}

// 3. Flow 实时监听(数据变化自动更新)
lifecycleScope.launch {
    usersCol.document("1").snapshots().collect { snapshot ->
        val user = snapshot.toObject(User::class.java)
        // 数据变化,更新UI
    }
}

// 4. 协程版批量操作
lifecycleScope.launch {
    try {
        db.runTransaction { tx ->
            val docRef = usersCol.document("1")
            val balance = tx.get(docRef).getLong("balance") ?: 0
            if (balance < 100) throw Exception("余额不足")
            tx.update(docRef, "balance", balance - 100)
            null
        }.await() // 协程等待事务完成
        Log.d("Firestore", "事务成功")
    } catch (e: Exception) {
        Log.e("Firestore", "事务失败:${e.message}")
    }
}
```

# 三、分析与监控类模块(补充高级配置+数据解读)

## 1. analytics 模块(补充转化跟踪+自定义维度)

### (1)转化跟踪(如“注册→付费”转化)

通过设置转化事件,可在 Firebase 控制台查看用户转化路径,示例代码如下:

```kotlin
val analytics = FirebaseAnalytics.getInstance(this)

// 1. 上报“注册”事件(转化起点)
analytics.logEvent(FirebaseAnalytics.Event.SIGN_UP, Bundle().apply {
    putString(FirebaseAnalytics.Param.METHOD, "email") // 注册方式
})

// 2. 上报“付费”事件(转化终点)
analytics.logEvent(FirebaseAnalytics.Event.PURCHASE, Bundle().apply {
    putString(FirebaseAnalytics.Param.PRODUCT_ID, "vip_1_month") // 商品ID
    putDouble(FirebaseAnalytics.Param.VALUE, 19.99) // 商品金额
    putString(FirebaseAnalytics.Param.CURRENCY, "CNY") // 货币类型
})
```

查看转化数据: Firebase 控制台「Analytics→转化」,创建转化事件(如“付费”),即可查看“注册→付费”的转化漏斗、转化时长等数据。

### (2)自定义维度(按用户/设备分组分析)

通过自定义维度,可按“用户等级”“设备型号”“地区”等维度分析数据,示例:

```kotlin
// 1. 在 Firebase 控制台「Analytics→自定义定义→自定义维度」,创建维度(如“user_level”)
// 2. 代码中设置维度
analytics.setUserProperty("user_level", "vip") // 用户等级:vip
analytics.setUserProperty("device_model", Build.MODEL) // 设备型号:Pixel 8
analytics.setUserProperty("region", "Beijing") // 地区:北京

// 3. 上报事件时,可关联维度
analytics.logEvent("page_view", Bundle().apply {
    putString("page_name", "home")
    putString("user_level", "vip") // 关联用户等级维度
})
```

## 2. crashlytics 模块(补充崩溃分析+自定义归因)

### (1)崩溃分析进阶(定位崩溃原因)

Crashlytics 不仅能捕获崩溃,还能通过自定义日志、用户信息,快速定位崩溃场景:

```kotlin
val crashlytics = FirebaseCrashlytics.getInstance()

// 1. 设置用户ID(关联崩溃用户)
crashlytics.setUserId("123456")

// 2. 设置自定义键值对(记录崩溃时的场景信息)
crashlytics.setCustomKey("page", "home") // 崩溃时所在页面
crashlytics.setCustomKey("network", "wifi") // 崩溃时网络状态
crashlytics.setCustomKey("version", BuildConfig.VERSION_NAME) // App版本

// 3. 记录自定义日志(辅助定位崩溃原因)
crashlytics.log("用户点击了支付按钮,开始请求接口")
crashlytics.log("接口返回数据:$response")

// 4. 捕获崩溃(主动触发/异常捕获)
try {
    val list = emptyList<String>()
    val str = list[0] // 主动触发数组越界崩溃
} catch (e: IndexOutOfBoundsException) {
    // 记录崩溃,并添加自定义描述
    crashlytics.recordException(Throwable("支付页面数组越界:${e.message}", e))
}
```

查看崩溃详情: Firebase 控制台「Crashlytics→崩溃」,可查看崩溃堆栈、用户ID、自定义键值对、日志,快速定位问题(如“支付页面,wifi网络,App 1.0.0版本,数组越界”)。

### (2)高频报错及解决

- **报错1**:崩溃不被捕获,Logcat 提示“Crashlytics could not find the manifest”
            
解决:检查模块的 AndroidManifest.xml 中,是否添加了 Crashlytics 的 meta-data 配置(模块已内置,若缺失可手动添加):
            `<meta-data
    android:name="firebase_crashlytics_collection_enabled"
    android:value="true" />`

- **报错2**:崩溃数据延迟超过10分钟
            
解决:调试时,在 Application 类中添加初始化代码,强制开启调试模式:
            `FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true)
if (BuildConfig.DEBUG) {
    FirebaseCrashlytics.getInstance().setCustomKey("debug_mode", true)
}`

## 3. performance 模块(补充自定义性能跟踪+优化建议)

该模块除了默认监控启动时间、网络请求,还可自定义跟踪“页面加载时间”“接口请求耗时”,示例:

```kotlin
val performance = FirebasePerformance.getInstance()

// 1. 自定义跟踪“页面加载时间”(从页面创建到渲染完成)
val pageTrace = performance.newTrace("home_page_load")
pageTrace.start() // 页面创建时启动跟踪

// 页面渲染完成后,停止跟踪
pageTrace.stop()

// 2. 跟踪“接口请求耗时”
val httpMetric = performance.newHttpMetric("https://api.example.com/pay", HttpMethod.POST)
httpMetric.start() // 发起请求时启动

// 请求完成后,停止跟踪并设置请求信息
httpMetric.setRequestPayloadSize(1024) // 请求体大小(字节)
httpMetric.setResponsePayloadSize(2048) // 响应体大小(字节)
httpMetric.setHttpResponseCode(200) // 响应码
httpMetric.stop()

// 3. 查看性能数据:Firebase 控制台「Performance→自定义跟踪」
```

优化建议:若监控到“启动时间过长”,可通过 Performance 控制台查看启动流程中的耗时环节(如初始化第三方SDK),针对性优化(如延迟初始化非核心SDK)。

## 4. remoteconfig 模块(补充A/B测试+配置缓存优化)

### (1)A/B测试(按用户分组下发不同配置)

通过 Remote Config 结合 Firebase A/B Testing,可给不同用户组下发不同配置(如50%用户看到“立即购买”,50%用户看到“限时优惠”),步骤如下:

1. 在 Firebase 控制台「Remote Config」,创建配置项(如“button_text”);

2. 在「A/B Testing」,创建实验,选择“Remote Config”作为实验变量,设置用户分组(如按设备型号、地区分组);

3. 代码中正常拉取配置,Remote Config 会自动根据用户分组下发对应值:
            `val remoteConfig = FirebaseRemoteConfig.getInstance()
// 拉取配置(调试时缓存过期时间设为0,实时生效)
remoteConfig.fetchAndActivate()
    .addOnSuccessListener {
        val btnText = remoteConfig.getString("button_text")
        findViewById<Button>(R.id.btn).text = btnText
    }`

### (2)配置缓存优化(减少网络请求)

Remote Config 默认有缓存(默认12小时),可根据场景调整缓存时间,避免频繁拉取配置:

```kotlin
// 1. 调试模式:缓存过期时间0,实时拉取最新配置
remoteConfig.fetch(0)
    .addOnSuccessListener {
        remoteConfig.activate() // 激活配置
    }

// 2. 生产环境:缓存1小时,减少网络请求
remoteConfig.fetch(3600) // 缓存时间(秒)
    .addOnSuccessListener {
        remoteConfig.activate()
    }

// 3. 强制刷新配置(如用户手动触发刷新)
remoteConfig.fetchAndActivate() // 忽略缓存,强制拉取
```

# 四、云存储模块(storage 补充进阶功能+权限优化)

## 1. 进阶功能:文件压缩+断点续传

### (1)图片上传前压缩(减少上传时间和存储空间)

```kotlin
// 1. 图片压缩工具类(压缩到指定尺寸和质量)
fun compressImage(file: File): File {
    val options = BitmapFactory.Options()
    options.inJustDecodeBounds = true
    BitmapFactory.decodeFile(file.path, options)
    // 计算压缩比例(示例:压缩到1080p以下)
    val targetWidth = 1080
    val targetHeight = 1920
    val widthRatio = Math.round(options.outWidth.toFloat() / targetWidth.toFloat())
    val heightRatio = Math.round(options.outHeight.toFloat() / targetHeight.toFloat())
    val inSampleSize = if (widthRatio > 0 || heightRatio > 0) {
        Math.min(widthRatio, heightRatio)
    } else {
        1
    }
    options.inJustDecodeBounds = false
    options.inSampleSize = inSampleSize
    val bitmap = BitmapFactory.decodeFile(file.path, options)
    // 保存压缩后的图片
    val compressedFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "compressed_${System.currentTimeMillis()}.jpg")
    val outputStream = FileOutputStream(compressedFile)
    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream) // 质量80%
    outputStream.close()
    return compressedFile
}

// 2. 上传压缩后的图片
val originalFile = File("/sdcard/avatar.jpg")
val compressedFile = compressImage(originalFile)
val avatarRef = storage.reference.child("images").child(userId).child("avatar.jpg")
avatarRef.putFile(Uri.fromFile(compressedFile))
    .addOnSuccessListener { /* 上传成功处理 */ }
```

### (2)断点续传(避免网络中断后重新上传)

Storage 支持断点续传,通过 UploadTask 的 pause()、resume() 方法实现:

```kotlin
val uploadTask = avatarRef.putFile(Uri.fromFile(compressedFile))
var uploadTaskSnapshot: UploadTask.TaskSnapshot? = null

// 暂停上传(如网络中断时)
findViewById<Button>(R.id.pauseBtn).setOnClickListener {
    if (uploadTask.isInProgress) {
        uploadTask.pause()
        uploadTaskSnapshot = uploadTask.snapshot // 记录当前上传进度
    }
}

// 恢复上传(如网络恢复时)
findViewById<Button>(R.id.resumeBtn).setOnClickListener {
    if (uploadTask.isPaused) {
        uploadTask.resume()
    }
}

// 监听上传进度
uploadTask.addOnProgressListener { snapshot ->
    val progress = (100.0 * snapshot.bytesTransferred) / snapshot.totalByteCount
    Log.d("Storage", "上传进度:$progress%")
}
```

## 2. 权限优化(生产环境必配)

Storage 测试规则(全读写)存在安全隐患,生产环境需按“用户只能操作自己的文件”配置规则,示例:

```json
// 生产环境 Storage 规则
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    // 用户只能上传/下载自己的头像(路径:/images/{uid}/*)
    match /images/{uid}/{allPaths=**} {
      allow read: if request.auth != null && request.auth.uid == uid;
      allow write: if request.auth != null && request.auth.uid == uid
                   && request.resource.contentType.matches('image/.*') // 仅允许上传图片
                   && request.resource.size < 5 * 1024 * 1024; // 限制图片大小不超过5MB
    }
    // 公开可读的文件(如App图标)
    match /public/{allPaths=**} {
      allow read: if true;
      allow write: if false;
    }
  }
}
```

# 五、消息推送类模块(补充适配+交互优化)

## 1. messaging 模块(补充 Android 13+ 适配+自定义通知)

### (1)Android 13+ 推送权限适配(必做)

Android 13(API 33)及以上,推送通知需申请 POST_NOTIFICATIONS 权限,示例代码:

```kotlin
// 1. 在 AndroidManifest.xml 中添加权限
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

// 2. 代码中申请权限(Android 13+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.POST_NOTIFICATIONS),
            1001 // 权限请求码
        )
    }
}

// 3. 权限请求回调
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 1001) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限授予,可正常接收推送
        } else {
            // 权限拒绝,无法接收前台通知(后台推送仍可接收,但无通知栏展示)
        }
    }
}
```

### (2)自定义通知样式(如大图通知、进度条通知)

```kotlin
// 在 MyFCMService 的 onMessageReceived 中,自定义通知样式
override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)
    val title = remoteMessage.notification?.title ?: "通知标题"
    val body = remoteMessage.notification?.body ?: "通知内容"

    // 1. 自定义通知渠道(Android 8.0+ 必配)
    val channelId = "fcm_channel"
    val channelName = "FCM 推送通知"
    val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT)
    val notificationManager = getSystemService(NotificationManager::class.java)
    notificationManager.createNotificationChannel(channel)

    // 2. 自定义通知布局(大图通知)
    val notificationBuilder = NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle(title)
        .setContentText(body)
        .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_large_icon))
        .setStyle(NotificationCompat.BigPictureStyle()
            .bigPicture(BitmapFactory.decodeResource(resources, R.drawable.big_image))
            .bigLargeIcon(null)) // 隐藏大图通知的小图标
        .setAutoCancel(true) // 点击通知后自动取消
        .setContentIntent(getPendingIntent()) // 点击通知跳转的页面

    // 3. 显示通知
    notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build())
}

// 点击通知跳转的页面
private fun getPendingIntent(): PendingIntent {
    val intent = Intent(this, MainActivity::class.java)
    intent.putExtra("from_notification", true) // 标记是否从通知跳转
    return PendingIntent.getActivity(
        this,
        0,
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
}
```

### (3)高频报错及解决

- **报错1**:Android 13+ 接收不到通知
            
解决:① 申请 POST_NOTIFICATIONS 权限;② 确认通知渠道已创建;③ 检查手机设置中,App 的通知权限是否开启。
        

- **报错2**:后台推送接收不到(App 进程被杀死)
            
解决:① 集成 Firebase Messaging Service 后,确保 Service 在 AndroidManifest 中正确注册;② 针对国产手机(华为、小米、OPPO),引导用户将 App 加入后台白名单(设置→应用→后台运行权限→允许)。
        

## 2. inappmessaging 模块(补充触发条件+样式自定义)

该模块用于展示应用内消息(如弹窗、横幅),核心是“在 Firebase 控制台配置触发条件”,补充代码中自定义样式和触发逻辑:

```kotlin
val inAppMessaging = FirebaseInAppMessaging.getInstance()

// 1. 开启/关闭应用内消息(如用户拒绝接收时关闭)
inAppMessaging.setMessagesSuppressed(false) // 开启
inAppMessaging.setMessagesSuppressed(true) // 关闭

// 2. 自定义消息展示样式(如修改弹窗背景色、文字颜色)
inAppMessaging.addClickListener { inAppMessage, action ->
    // 点击消息按钮的回调
    Log.d("InAppMessaging", "点击了按钮:${action.actionText}")
}

// 3. 手动触发消息展示(默认由 Firebase 控制台配置的条件触发,可手动触发测试)
inAppMessaging.triggerEvent("custom_event") // 触发名为“custom_event”的事件,展示对应消息
```

配置触发条件: Firebase 控制台「In-App Messaging→创建消息」,选择消息样式(弹窗/横幅/卡片),设置触发条件(如“用户登录后”“用户点击某按钮后”),保存后即可在 App 中触发展示。

# 六、安全与工具类模块(补充完整集成+部署步骤)

## 1. appcheck 模块(补充两种验证方式+调试模式)

App Check 用于防止恶意请求,支持两种验证方式:Recaptcha V3(适用于所有 Android 设备)、Play Integrity(仅适用于 Google Play 分发的设备),完整集成代码如下:

### (1)Recaptcha V3 集成

```kotlin
// 1. 添加依赖(模块已内置)
implementation 'com.google.firebase:firebase-appcheck-recaptcha:17.1.2'

// 2. 在 Application 类中初始化
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 初始化 App Check
        val appCheck = FirebaseAppCheck.getInstance()
        appCheck.installAppCheckProviderFactory(
            RecaptchaAppCheckProviderFactory.getInstance()
        )
        // 调试模式(开发时开启,避免拦截合法请求)
        if (BuildConfig.DEBUG) {
            appCheck.setTokenAutoRefreshEnabled(true)
            appCheck.getAppCheckToken(true)
                .addOnSuccessListener { tokenResult ->
                    Log.d("AppCheck", "调试 Token:${tokenResult.token}")
                }
        }
    }
}
```

### (2)Play Integrity 集成(推荐 Google Play 分发的 App)

```kotlin
// 1. 添加依赖
implementation 'com.google.firebase:firebase-appcheck-playintegrity:17.1.2'

// 2. 初始化(替换 Recaptcha 初始化代码)
appCheck.installAppCheckProviderFactory(
    PlayIntegrityAppCheckProviderFactory.getInstance()
)
```

注意:Play Integrity 需在 Google Play 控制台添加 App,且 App 需签名后才能正常使用。

## 2. functions 模块(补充云函数部署+客户端调用细节)

该模块核心是“调用云端自定义函数”,需先在 Firebase 控制台部署云函数,再在客户端调用,完整步骤如下:

### (1)部署云函数(Node.js 示例)

1. 安装 Firebase CLI:`npm install -g firebase-tools`;

2. 登录 Firebase:`firebase login`;

3. 初始化云函数:`firebase init functions`,选择对应 Firebase 项目;

4. 修改 `functions/index.js`,编写云函数(示例:计算两个数的和):
            `const functions = require("firebase-functions");

exports.addNumbers = functions.https.onCall((data, context) => {
    // 验证用户是否登录(可选)
    if (!context.auth) {
        throw new functions.https.HttpsError("unauthenticated", "用户未登录");
    }
    const num1 = data.num1;
    const num2 = data.num2;
    return { result: num1 + num2 };
});`

5. 部署云函数:`firebase deploy --only functions`,部署成功后,会生成云函数调用地址。

### (2)客户端调用云函数(Android 代码)

```kotlin
val functions = FirebaseFunctions.getInstance()

// 调用云函数 addNumbers
val data = hashMapOf(
    "num1" to 10,
    "num2" to 20
)
functions.getHttpsCallable("addNumbers")
    .call(data)
    .addOnSuccessListener { result ->
        val resultData = result.data as Map<*, *>
        val sum = resultData["result"] as Long
        Log.d("Functions", "计算结果:$sum") // 输出 30
    }
    .addOnFailureListener { e ->
        // 处理调用失败(如用户未登录、云函数报错)
        if (e is FirebaseFunctionsException) {
            val code = e.code
            val message = e.message
            Log.e("Functions", "调用失败:$code - $message")
        }
    }
```

## 3. mlkit 模块(补充各 AI 功能完整代码)

该模块演示 ML Kit 移动端 AI 能力,补充 OCR 文字识别、人脸检测、条码扫描的完整代码,适配 Android 高版本:

### (1)OCR 文字识别(识别图片中的文字)

```kotlin
// 1. 添加依赖(模块已内置)
implementation 'com.google.mlkit:text-recognition-chinese:16.0.0'

// 2. 识别图片中的文字(从相册选择图片)
private fun recognizeText(bitmap: Bitmap) {
    val textRecognizer = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build())
    val inputImage = InputImage.fromBitmap(bitmap, 0) // 0 是图片旋转角度
    textRecognizer.process(inputImage)
        .addOnSuccessListener { visionText ->
            // 识别成功,提取文字
            val text = visionText.text
            Log.d("MLKit", "识别结果:$text")
            // 提取每行文字
            for (block in visionText.textBlocks) {
                for (line in block.lines) {
                    Log.d("MLKit", "行文字:${line.text}")
                }
            }
        }
        .addOnFailureListener { e ->
            Log.e("MLKit", "识别失败:${e.message}")
        }
}
```

### (2)人脸检测(检测图片中的人脸,获取人脸信息)

```kotlin
// 1. 添加依赖
implementation 'com.google.mlkit:face-detection:16.1.5'

// 2. 人脸检测
private fun detectFaces(bitmap: Bitmap) {
    val faceDetector = FaceDetection.getClient(
        FaceDetectorOptions.Builder()
            .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST) // 快速检测
            .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) // 检测人脸关键点(眼睛、鼻子等)
            .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) // 检测表情、是否戴眼镜
            .build()
    )
    val inputImage = InputImage.fromBitmap(bitmap, 0)
    faceDetector.process(inputImage)
        .addOnSuccessListener { faces ->
            // 检测到的人脸列表
            for (face in faces) {
                // 人脸边界
                val boundingBox = face.boundingBox
                // 表情(微笑程度:0.0~1.0)
                val smileProbability = face.smilingProbability ?: 0.0
                // 是否戴眼镜
                val isWearingGlasses = face.rightEyeOpenProbability ?: 0.0 > 0.5
                Log.d("MLKit", "检测到人脸:微笑程度=$smileProbability,是否戴眼镜=$isWearingGlasses")
            }
        }
        .addOnFailureListener { e ->
            Log.e("MLKit", "人脸检测失败:${e.message}")
        }
}
```

## 4. dynamiclinks 模块(补充域名配置+跳转逻辑)

动态链接用于跨平台跳转(如从网页/微信分享链接,跳转到 App,未安装则引导下载),完整配置步骤如下:

### (1)在 Firebase 控制台配置动态链接域名

1. 进入 Firebase 控制台「Dynamic Links→开始使用」,创建动态链接域名(如“xxx.page.link”);

2. 验证域名所有权(按提示添加 DNS 解析或上传验证文件);

3. 创建动态链接,设置“深链接”(如“myapp://home”)、“未安装 App 时的跳转链接”(如应用商店下载链接)。

### (2)客户端接收动态链接跳转

```kotlin
// 1. 在 AndroidManifest.xml 中配置深链接
<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="home"
            android:scheme="myapp" /> // 深链接 scheme:myapp://home
    </intent-filter>
</activity>

// 2. 在 MainActivity 中接收动态链接
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 接收动态链接
    FirebaseDynamicLinks.getInstance()
        .getDynamicLink(intent)
        .addOnSuccessListener { pendingDynamicLinkData ->
            var deepLink: Uri? = null
            if (pendingDynamicLinkData != null) {
                deepLink = pendingDynamicLinkData.link
            }
            // 处理深链接(如跳转到对应页面)
            deepLink?.let {
                if (it.toString().contains("home")) {
                    // 跳转到首页
                } else if (it.toString().contains("product")) {
                    // 跳转到商品详情页,提取商品ID
                    val productId = it.getQueryParameter("product_id")
                }
            }
        }
        .addOnFailureListener { e ->
            Log.e("DynamicLinks", "获取动态链接失败:${e.message}")
        }
}
```

# 七、辅助模块(补充细节+解决常见问题)

## 1. internal 模块(核心作用+缺失解决)

该模块是 **项目内部工具模块**,非业务功能,核心作用:

- 提供基础工具类(如权限申请工具、日志工具、UI 工具),供其他模块复用;

- 统一管理依赖版本(如 Firebase SDK 版本、AndroidX 依赖版本),避免模块间版本冲突;

- 封装通用逻辑(如 Firebase 初始化、用户信息存储),减少重复代码。

补充此前报错(internal 模块缺失)的进阶解决方法:

```bash
# 方法1:手动下载子模块(无需重新克隆项目)
cd /Users/syxny/Workspace/AndroidStudioProjects/quickstart-android2
git submodule init auth/internal
git submodule update auth/internal

# 方法2:手动创建 internal 目录并添加基础文件(应急)
mkdir -p auth/internal/src/main/java/com/google/firebase/quickstart/auth/internal
# 从 Firebase 官方仓库下载 internal 模块的核心文件,放入上述目录
# 官方仓库 internal 模块地址:https://github.com/firebase/quickstart-android/tree/master/auth/internal
```

## 2. appdistribution 模块(应用分发+测试反馈)

该模块用于测试包分发,替代蒲公英、TestFlight,支持测试反馈收集,核心用法:

```kotlin
// 1. 添加依赖(模块已内置)
implementation 'com.google.firebase:firebase-appdistribution:16.0.1'

// 2. 初始化 App Distribution
val appDistribution = FirebaseAppDistribution.getInstance()

// 3. 检查更新(测试包更新)
appDistribution.checkForNewRelease()
    .addOnSuccessListener { release ->
        if (release != null) {
            // 有新的测试包,提示用户更新
            appDistribution.updateApp()
        }
    }

// 4. 收集测试反馈(用户点击反馈按钮时调用)
findViewById<Button
```
相关推荐
Sharewinfo_BJ9 小时前
拒绝“盲人摸象”!打破数据孤岛,重塑零售决策力
microsoft·零售
Azure DevOps10 小时前
Azure DevOps:应用远程MCP服务器,提升工作效率
服务器·microsoft·flask·azure·devops
SSONICX10 小时前
ESP32:6.ADC
microsoft
迅易科技10 小时前
在 Azure 容器化部署 OpenClaw:从零到生产环境实战指南
microsoft·flask·azure
步步为营DotNet11 小时前
深入剖析.NET 11中Microsoft.Extensions.AI的应用与优化 前言
人工智能·microsoft·.net
05大叔11 小时前
AI智能伴侣项目
人工智能·microsoft
roman_日积跬步-终至千里11 小时前
【论文ing】强化学习重塑 NL2SQL:单轮对齐、多轮交互与细粒度评估的最新进展(2020–2026)
数据库·sql·microsoft
梦想的旅途21 天前
企业微信 RPA 自动化集成方案
microsoft