在 Android 上處理 Firebase 電話號碼驗證錯誤

如果呼叫 Firebase PNV 程式庫失敗,程式庫會回報 FirebasePhoneNumberVerificationException。本頁面列出例外狀況可能包含的所有錯誤代碼、發生時間,以及應用程式應採取的行動。

本頁面假設您已按照「在 Android 上開始使用 Firebase Phone Number Verification」一文所述,整合 Firebase PNV。

錯誤回報方式

  • 非同步方法 (getVerificationSupportInfo()、getVerifiedPhoneNumber() 和自訂流程方法) 會傳回 Task。如果失敗,Task 會失敗並傳回 FirebasePhoneNumberVerificationException,您會在 addOnFailureListener 中收到。

  • enableTestSession() 為同步性質。系統會直接擲回 FirebasePhoneNumberVerificationException。

請參閱例外狀況的 errorCode,瞭解問題所在。Firebase PNV 程式碼是 FirebasePnvStatusCodes 類別中的常數。如果失敗來自 Google Play 服務,errorCode 也可以是 CommonStatusCodes 值,例如 NETWORK_ERROR。

不支援的裝置或 SIM 卡並非錯誤。getVerificationSupportInfo() 成功,並將該 SIM 卡的 isSupported() 回報為 false,而 getReason() 會說明原因。請參閱「不支援的裝置和 SIM 卡」。

錯誤代碼

測試工作階段設定

這些錯誤是由 enableTestSession() 同步擲回。

錯誤代碼 原因 建議做法
TEST_SESSION_ALREADY_ENABLED
(55508)
在同一個應用程式程序中多次呼叫 enableTestSession()。FirebasePhoneNumberVerification.getInstance() 每次都會傳回相同的例項,因此當呼叫它的 Activity 重新建立時,也會發生這種情況。 每個程序呼叫 enableTestSession() 一次,例如在 Application.onCreate() 中。請參閱「在測試模式下初始化程式庫」一節。
INVALID_TEST_NUMBER_ID
(55507)
傳遞至 enableTestSession() 的測試權杖空白。 請確認版本會傳遞您在 Firebase 控制台中產生的權杖,且只有在權杖不為空白時,才會呼叫 enableTestSession()。

驗證

這些錯誤會導致 getVerifiedPhoneNumber() 傳回的 Task 失敗。

錯誤代碼 原因 建議做法
CREDENTIAL_MANAGER_ERROR
(55506)
Android Credential Manager 未傳回電話號碼。如果例外狀況的 cause 是 GetCredentialCancellationException,使用者很可能關閉了同意畫面。 提供其他驗證電話號碼的方式,例如簡訊。請勿自動重試,否則使用者會再次看到同意畫面。
CARRIER_NOT_SUPPORTED
(55501)
不支援所選 SIM 卡的電信業者,或裝置沒有驗證所需的訂閱資訊。 改用其他驗證方法,例如簡訊。
UNSUPPORTED_OPERATION
(55505)
裝置無法使用「Firebase PNV」處理這項要求。 改用其他驗證方法,例如簡訊。
PREFLIGHT_CHECK_FAILED
(55504)
在顯示同意畫面之前,Firebase PNV 後端無法建立驗證要求。 改用其他驗證方法,例如簡訊。如果每個要求都發生這種情況,請確認應用程式設定正確 (請參閱「升級至正式環境模式」)。
INTEGRITY_CHECK_FAILED
(55503)
裝置或應用程式未通過完整性檢查。 改用其他驗證方法,例如簡訊。
INVALID_DIGITAL_CREDENTIAL_RESPONSE
(55502)
無法讀取 Credential Manager 的回應,或無法用來交換經驗證的電話號碼。 改用其他驗證方法,例如簡訊。
INVALID_TEST_NUMBER_ID
(55507)
在測試模式下,Firebase PNV 後端拒絕了測試權杖,例如因為權杖已過期。測試權杖的存留時間為 7 天。如果測試權杖遭拒,通常會回報這個代碼。如果您在測試模式中看到其他錯誤,也請檢查權杖是否為最新版本。 在 Firebase 控制台中產生新的測試權杖,然後重新建構應用程式。
ACTIVITY_CONTEXT_REQUIRED
(55509)
傳遞至 getVerifiedPhoneNumber() 的 Context 不是 Activity。這個方法需要 Activity 才能顯示同意畫面。 傳遞目前的 Activity。這是應用程式中的錯誤,而非執行階段要處理的條件。

支援檢查

只有在檢查本身無法執行時,getVerificationSupportInfo() 傳回的 Task 才會失敗。在這種情況下,errorCode 是 Google Play 服務 CommonStatusCodes 值或 CARRIER_NOT_SUPPORTED。將裝置視為不支援,並改用其他驗證方法,例如簡訊。

啟用測試工作階段時,getVerificationSupportInfo() 不會與 Firebase PNV 後端聯絡,且一律會回報測試 SIM 卡為支援狀態,即使測試權杖已過期也一樣。

自訂流程

如果您使用自訂流程,而非 getVerifiedPhoneNumber():

  • getDigitalCredentialPayload() 失敗,並顯示 PREFLIGHT_CHECK_FAILED,或在後端拒絕測試權杖時顯示 INVALID_TEST_NUMBER_ID。
  • exchangeCredentialResponseForPhoneNumber() 失敗,並顯示 INVALID_DIGITAL_CREDENTIAL_RESPONSE,或在後端拒絕測試權杖時顯示 INVALID_TEST_NUMBER_ID。
  • 您對 Credential Manager 的呼叫會擲回 GetCredentialException,您可直接處理。

不支援的裝置和 SIM 卡

如果 SIM 卡的 isSupported() 為 false,getReason() 會傳回下列其中一個 VerificationSupportStatus 值:

值 意義
INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED 不支援 SIM 卡的電信業者。請參閱「支援的電信業者」。
INCAPABLE_DUE_TO_ANDROID_VERSION 裝置搭載 Android 9 (API 級別 28) 以下版本。
INCAPABLE_DUE_TO_SIM_STATE SIM 卡尚未準備就緒。由於系統會先檢查電信業者,因此鎖定或仍在載入的 SIM 卡也可能回報 INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED。

在上述情況下,請使用其他驗證方法 (例如簡訊) 驗證該 SIM 卡。

範例

以下範例會處理一般應用程式在呼叫 getVerifiedPhoneNumber() 時需要區分的錯誤:

Kotlin

import android.util.Log
// Credential Manager is included with the Firebase PNV library.
import androidx.credentials.exceptions.GetCredentialCancellationException
import com.google.firebase.pnv.FirebasePhoneNumberVerification
import com.google.firebase.pnv.FirebasePhoneNumberVerificationException
import com.google.firebase.pnv.FirebasePnvStatusCodes

private const val TAG = "PhoneVerification"

// In your Activity:
private fun verifyPhoneNumber() {
    FirebasePhoneNumberVerification.getInstance()
        .getVerifiedPhoneNumber(this)
        .addOnSuccessListener { result ->
            // Send result.getToken() to your backend.
        }
        .addOnFailureListener { e -> handleFpnvError(e) }
}

private fun handleFpnvError(e: Exception) {
    if (e !is FirebasePhoneNumberVerificationException) {
        Log.w(TAG, "Firebase PNV failed", e)
        showSmsVerification()
        return
    }
    when (e.errorCode) {
        FirebasePnvStatusCodes.CREDENTIAL_MANAGER_ERROR -> {
            if (e.cause is GetCredentialCancellationException) {
                // The user dismissed the consent screen.
            }
            showSmsVerification()
        }
        FirebasePnvStatusCodes.INVALID_TEST_NUMBER_ID -> {
            // Test mode only: generate a new test token.
            Log.e(TAG, "Firebase PNV test token rejected", e)
        }
        FirebasePnvStatusCodes.ACTIVITY_CONTEXT_REQUIRED -> {
            // App bug: pass an Activity to getVerifiedPhoneNumber().
            Log.e(TAG, "Firebase PNV needs an Activity context", e)
        }
        else -> {
            // Carrier not supported, network errors, and other failures.
            Log.w(TAG, "Firebase PNV failed with error code ${e.errorCode}", e)
            showSmsVerification()
        }
    }
}

在這個範例中,showSmsVerification() 是應用程式現有的電話號碼驗證流程。

後續步驟