auth0-android-major-migration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Auth0.Android v4 Migration

Auth0.Android v4迁移

Migrates an existing Auth0.Android (
com.auth0.android:auth0
) v3 integration to v4. Every code change is gated on a search that confirms the project actually calls the affected API — if the project never uses
SecureCredentialsManager
, no
SecureCredentialsManager
code is touched. Changes follow the project's existing architecture (Kotlin or Java, callback or coroutine) and Android conventions.
将现有的Auth0.Android(
com.auth0.android:auth0
)v3集成迁移至v4版本。所有代码变更都会基于搜索确认项目是否实际调用受影响的API——如果项目从未使用
SecureCredentialsManager
,则不会修改任何与
SecureCredentialsManager
相关的代码。变更会遵循项目现有的架构(Kotlin或Java、回调或协程)以及Android规范。

Target version is argument-based

目标版本基于参数

This skill accepts an optional target version argument:
  • /auth0-android-major-migration 4.0.0
    — migrate to the exact tag
    4.0.0
    (validated before use).
  • /auth0-android-major-migration
    (no argument) — auto-resolve the latest release within the next major (v4.x), including pre-releases.
$ARGUMENTS
, when present, is the requested target tag. Step 2 validates it and resolves the final
<TARGET_TAG>
used for the rest of the migration.
该技能接受一个可选的目标版本参数:
  • /auth0-android-major-migration 4.0.0
    —— 迁移至确切标签
    4.0.0
    (使用前会验证有效性)。
  • /auth0-android-major-migration
    (无参数)—— 自动解析下一个大版本(v4.x)中的最新发布版本,包括预发布版本。
当存在
$ARGUMENTS
时,它即为请求的目标标签。步骤2会验证该标签,并解析出后续迁移流程中使用的最终
<TARGET_TAG>

When NOT to Use

不适用于以下场景

  • New Auth0 integration (no existing Auth0.Android SDK): Use auth0-android
  • Minor/patch update (e.g., 3.18 → 3.19): Bump the
    com.auth0.android:auth0
    version in Gradle — no migration needed
  • iOS / macOS apps: Use auth0-swift-major-migration
  • React Native / Expo: Use auth0-react-native or auth0-expo
  • Flutter: Use the native Flutter Auth0 SDK
  • 全新Auth0集成(无现有Auth0.Android SDK):使用auth0-android
  • 小版本/补丁更新(例如3.18 → 3.19):在Gradle中直接升级
    com.auth0.android:auth0
    版本即可——无需迁移
  • iOS / macOS应用:使用auth0-swift-major-migration
  • React Native / Expo:使用auth0-react-nativeauth0-expo
  • Flutter:使用原生Flutter Auth0 SDK

Prerequisites

先决条件

  • Existing Auth0.Android v3 integration (
    com.auth0.android:auth0:3.x
    )
  • Android SDK / Gradle toolchain installed; project builds cleanly on the current version
  • Project under git version control with a clean working tree

  • 已集成Auth0.Android v3版本(
    com.auth0.android:auth0:3.x
  • 已安装Android SDK / Gradle工具链;当前版本下项目可正常构建
  • 项目处于Git版本控制下,且工作区干净

Migration Workflow

迁移流程

Agent instruction: Execute every step in order. The goal is a green build with the smallest correct changeset. Each code-change step is gated by the Step 5 file-reading audit — if the API was not found in the project's source files, skip the entire step for that area. Never add code the project doesn't already call. v4 also raises platform requirements (Step 3) that can block the migration until satisfied — handle those before touching any Auth0 API call site.

Agent指令: 按顺序执行每一步。目标是通过最少的正确变更实现构建成功。每个代码变更步骤都受步骤5的文件读取审核限制——如果在项目源文件中未找到对应API,则跳过该区域的整个步骤。绝不要添加项目未调用的代码。v4还提高了平台要求(步骤3),这可能会阻止迁移,需先处理这些要求,再修改任何Auth0 API调用站点。

Step 1 — Pre-flight & Safety Backup

步骤1 — 预检与安全备份

bash
undefined
bash
undefined

1a. Verify clean working tree — stop if there are uncommitted changes

1a. 验证工作区是否干净——如果存在未提交的变更则停止

git status --porcelain

If the output is non-empty, ask the user:
> *"You have uncommitted changes. Should I stash them before proceeding (`git stash`), or would you like to commit first?"*

```bash
git status --porcelain

如果输出非空,请询问用户:
> *“您存在未提交的变更。是否需要先暂存这些变更(执行`git stash`),还是您想先提交?”*

```bash

1b. Create a safety branch the user can reset to at any time

1b. 创建一个安全分支,用户可随时回滚到该分支

git checkout -b auth0-v4-migration-backup git checkout -

```bash
git checkout -b auth0-v4-migration-backup git checkout -

```bash

1c. Confirm the project builds on the current version before touching anything

1c. 在修改任何内容前,确认当前版本下项目可正常构建

./gradlew assembleDebug 2>&1 | tail -15

If the build fails, stop. Ask the user to fix the existing issues first — do not migrate a project that does not build.

---
./gradlew assembleDebug 2>&1 | tail -15

如果构建失败,请停止。请用户先修复现有问题——不要迁移无法构建的项目。

---

Step 2 — Detect Current & Resolve Target Version

步骤2 — 检测当前版本并解析目标版本

Detect the current Auth0.Android version (check each location that applies):
bash
undefined
检测当前Auth0.Android版本(检查适用的每个位置):
bash
undefined

Inline dependency in a module build file (Groovy or Kotlin DSL)

模块构建文件中的内联依赖(Groovy或Kotlin DSL)

grep -rEn "com.auth0.android:auth0:[0-9]" --include=build.gradle --include=build.gradle.kts .
grep -rEn "com.auth0.android:auth0:[0-9]" --include=build.gradle --include=build.gradle.kts .

Gradle version catalog

Gradle版本目录

grep -rEn "auth0" --include=libs.versions.toml .
grep -rEn "auth0" --include=libs.versions.toml .

Resolved lockfile (most reliable if present)

已解析的锁定文件(如果存在,此方式最可靠)

grep -rEn "com.auth0.android:auth0:[0-9]" --include=gradle.lockfile .

**Resolve the target version.** There are two paths:

**Path A — the user passed a target version argument (`$ARGUMENTS`):**

Validate it against the published releases before using it. It must pass **all three** checks:

```bash
grep -rEn "com.auth0.android:auth0:[0-9]" --include=gradle.lockfile .

**解析目标版本**。有两种路径:

**路径A — 用户传入了目标版本参数(`$ARGUMENTS`):**

在使用前,需针对已发布的版本验证该参数。它必须通过**全部三项**检查:

```bash

List all published Auth0.Android release tags

列出所有已发布的Auth0.Android版本标签

gh api repos/auth0/Auth0.Android/releases --paginate
--jq '.[] | select(.draft==false) | .tag_name'

1. **Exists** — the requested tag appears in the published release list above.
2. **Next major** — the tag is within the **v4** major line (`tag_name` starts with `4`). A `3.x` or lower tag is *not* the next major; reject it.
3. **Not a downgrade** — the tag is newer than the version detected in the project.

> **On any check failing, STOP and ask the user.** Do not silently fall back. For example:
> - *"`4.9.9` isn't a published Auth0.Android release. Published v4 releases are: `4.0.0-beta.1`, … . Please pass a valid v4 tag, or omit the argument to auto-resolve the latest v4 release."*
> - *"`3.19.0` is a v3 release, not the next major. This skill migrates to v4. Pass a v4 tag (e.g. `4.0.0`) or omit the argument."*
> - *"`4.0.0-beta.0` is older than the `4.0.0-beta.1` already in your project — that's a downgrade. Pass a newer v4 tag or omit the argument."*

**Path B — no argument: auto-resolve the latest v4 release (including pre-releases):**

```bash
gh api repos/auth0/Auth0.Android/releases --paginate
--jq '.[] | select(.draft==false) | .tag_name'

1. **存在性** — 请求的标签出现在上述已发布版本列表中。
2. **大版本升级** — 标签属于**v4**大版本系列(`tag_name`以`4`开头)。`3.x`或更低版本的标签不属于下一个大版本,需拒绝。
3. **非降级** — 标签版本比项目中检测到的版本更新。

> **如果任何一项检查失败,请停止并询问用户。** 不要静默回退。例如:
> - *“`4.9.9`不是已发布的Auth0.Android版本。已发布的v4版本包括:`4.0.0-beta.1`,……。请传入有效的v4标签,或省略参数以自动解析最新的v4版本。”*
> - *“`3.19.0`是v3版本,不属于下一个大版本。本技能用于迁移至v4版本。请传入v4标签(例如`4.0.0`)或省略参数。”*
> - *“`4.0.0-beta.0`比您项目中已有的`4.0.0-beta.1`版本更旧——这属于降级操作。请传入更新的v4标签或省略参数。”*

**路径B — 无参数:自动解析最新的v4版本(包括预发布版本):**

```bash

Newest v4.x release tag (stable or pre-release), most recent first

最新的v4.x版本标签(稳定版或预发布版),按时间倒序排列

gh api repos/auth0/Auth0.Android/releases --paginate
--jq '[.[] | select(.draft==false) | select(.tag_name|startswith("4"))] | .[0].tag_name'

Record the result as `<TARGET_TAG>` and use it in every subsequent step.

> **If `<TARGET_TAG>` is a pre-release** (contains `-beta`, `-rc`, etc.), tell the user before continuing:
> *"v4 is not yet generally available — the latest v4 release is `<TARGET_TAG>` (a pre-release). I'll migrate to that. You can pin a different tag by passing it as an argument."*
>
> **If no v4 release exists yet** (the resolver returns empty), stop and tell the user there is no published v4 release to migrate to.

---
gh api repos/auth0/Auth0.Android/releases --paginate
--jq '[.[] | select(.draft==false) | select(.tag_name|startswith("4"))] | .[0].tag_name'

将结果记录为`<TARGET_TAG>`,并在后续所有步骤中使用。

> **如果`<TARGET_TAG>`是预发布版本**(包含`-beta`、`-rc`等),请在继续前告知用户:
> *“v4版本尚未正式发布——最新的v4版本是`<TARGET_TAG>`(预发布版)。我将迁移至该版本。您可以通过传入参数来固定其他标签。”*
>
> **如果尚无v4版本发布**(解析器返回空),请停止并告知用户目前没有可迁移的已发布v4版本。

---

Step 3 — Prerequisite Gate (Requirements Changes)

步骤3 — 先决条件检查(要求变更)

v4 raises the build toolchain and platform floor. Check each requirement before migrating any API. If a requirement is unmet, prompt the user and apply the build-file change (or block until they confirm) — a project that doesn't meet these will not build against v4 regardless of API changes.
Confirm the exact required versions for
<TARGET_TAG>
from the SDK's own
build.gradle
/
gradle-wrapper.properties
fetched in Step 4 if they differ from the values below (these reflect the v4 baseline).
Requirementv3v4Where to check / change
minSdk2126 (Android 8.0)
android { defaultConfig { minSdk } }
Java8+17
compileOptions { sourceCompatibility/targetCompatibility }
,
kotlinOptions { jvmTarget }
Gradle8.11.1+
gradle/wrapper/gradle-wrapper.properties
(
distributionUrl
)
AGP8.10.1+root
build.gradle
com.android.tools.build:gradle
classpath /
plugins
block
Kotlin2.0.21
ext.kotlin_version
/ version catalog (only if the project uses Kotlin)
bash
undefined
v4版本提高了构建工具链和平台的最低要求。在迁移任何API之前,请检查每项要求。如果某项要求未满足,请提示用户并应用构建文件变更(或等待用户确认后再继续)——不满足这些要求的项目,无论API如何变更,都无法基于v4版本构建。
如果以下值与v4基线不同,请从步骤4中获取的SDK自身
build.gradle
/
gradle-wrapper.properties
文件中确认
<TARGET_TAG>
的确切要求版本。
要求v3v4检查/修改位置
minSdk2126(Android 8.0)
android { defaultConfig { minSdk } }
Java8+17
compileOptions { sourceCompatibility/targetCompatibility }
,
kotlinOptions { jvmTarget }
Gradle8.11.1+
gradle/wrapper/gradle-wrapper.properties
distributionUrl
AGP8.10.1+根目录
build.gradle
中的
com.android.tools.build:gradle
类路径 /
plugins
Kotlin2.0.21
ext.kotlin_version
/ 版本目录(仅当项目使用Kotlin时)
bash
undefined

Inspect current values

检查当前值

grep -rEn "minSdk(Version)?\s*[ =]" --include=build.gradle --include=build.gradle.kts . grep -rEn "sourceCompatibility|targetCompatibility|jvmTarget" --include=build.gradle --include=build.gradle.kts . grep -En "distributionUrl" gradle/wrapper/gradle-wrapper.properties grep -rEn "com.android.tools.build:gradle|kotlin_version|kotlin("|-)" --include=build.gradle --include=build.gradle.kts --include=libs.versions.toml .

**`minSdk` below 26 is a hard block.** If the project targets API 25 or lower, tell the user this raises the minimum supported Android version (devices on Android 7.1 and below will no longer be supported) and ask them to confirm before bumping `minSdk` to 26 — or to stay on v3.

Apply the required bumps (example shapes — match the project's DSL):

```groovy
android {
    defaultConfig { minSdk 26 }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions { jvmTarget = '17' }
}
See references/process.md for Kotlin DSL, version-catalog, and Gradle/AGP wrapper edge cases.

grep -rEn "minSdk(Version)?\s*[ =]" --include=build.gradle --include=build.gradle.kts . grep -rEn "sourceCompatibility|targetCompatibility|jvmTarget" --include=build.gradle --include=build.gradle.kts . grep -En "distributionUrl" gradle/wrapper/gradle-wrapper.properties grep -rEn "com.android.tools.build:gradle|kotlin_version|kotlin("|-)" --include=build.gradle --include=build.gradle.kts --include=libs.versions.toml .

**`minSdk`低于26属于硬性限制**。如果项目目标API为25或更低,请告知用户这会提高最低支持的Android版本(Android 7.1及以下版本的设备将不再受支持),并询问用户是否确认将`minSdk`提升至26——或继续使用v3版本。

应用所需的版本提升(示例格式——匹配项目的DSL):

```groovy
android {
    defaultConfig { minSdk 26 }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions { jvmTarget = '17' }
}
有关Kotlin DSL、版本目录以及Gradle/AGP包装器的特殊情况,请参阅references/process.md

Step 4 — Fetch & Read the v4 SDK Source

步骤4 — 获取并读取v4 SDK源码

Fetch the actual Kotlin source for
<TARGET_TAG>
. The signatures here are the authoritative reference for every change made in Step 7. Do not migrate from memory or from the guide alone — confirm each signature in the fetched source.
bash
TAG=<TARGET_TAG>   # the version resolved in Step 2, e.g. 4.0.0-beta.1
BASE="https://raw.githubusercontent.com/auth0/Auth0.Android/${TAG}/auth0/src/main/java/com/auth0/android"
获取
<TARGET_TAG>
对应的实际Kotlin源码。此处的方法签名是步骤7中所有变更的权威参考。不要凭记忆或仅根据指南进行迁移——请在获取的源码中确认每个签名。
bash
TAG=<TARGET_TAG>   # 步骤2中解析的版本,例如4.0.0-beta.1
BASE="https://raw.githubusercontent.com/auth0/Auth0.Android/${TAG}/auth0/src/main/java/com/auth0/android"

List all public Kotlin files in the SDK (confirm paths for this tag)

列出SDK中所有公开的Kotlin文件(确认此标签对应的路径)

gh api "repos/auth0/Auth0.Android/git/trees/${TAG}?recursive=1"
--jq '.tree[].path | select(startswith("auth0/src/main/") and endswith(".kt"))'
gh api "repos/auth0/Auth0.Android/git/trees/${TAG}?recursive=1"
--jq '.tree[].path | select(startswith("auth0/src/main/") and endswith(".kt"))'

Fetch the files that back the breaking changes

获取与破坏性变更相关的文件

for FILE in
provider/WebAuthProvider.kt
authentication/AuthenticationAPIClient.kt
authentication/mfa/MfaApiClient.kt
authentication/storage/SecureCredentialsManager.kt
authentication/storage/CredentialsManager.kt
authentication/storage/BaseCredentialsManager.kt
authentication/storage/Storage.kt
dpop/DPoPException.kt
result/SSOCredentials.kt
request/DefaultClient.kt ; do CONTENT=$(curl -sf "${BASE}/${FILE}") [ -n "$CONTENT" ] && echo "=== ${FILE} ===" && echo "$CONTENT" done

> **If a release tag has no source yet** (e.g. during the v4 development phase, before the first tag carries the full tree), fall back to the `v4_development` branch for signature confirmation: replace `${TAG}` with `v4_development` in the URLs above. Always prefer the chosen tag when it has source.

Read the fetched source and note, for each file:
- Public method signatures that changed (parameters, return type, `@Throws`)
- Constructors that were removed
- Types/classes that were removed or renamed
- Default parameter values that changed (e.g. `minTtl`)

This is the ground truth. Every change in Step 7 must match a real signature in these files.

---
for FILE in
provider/WebAuthProvider.kt
authentication/AuthenticationAPIClient.kt
authentication/mfa/MfaApiClient.kt
authentication/storage/SecureCredentialsManager.kt
authentication/storage/CredentialsManager.kt
authentication/storage/BaseCredentialsManager.kt
authentication/storage/Storage.kt
dpop/DPoPException.kt
result/SSOCredentials.kt
request/DefaultClient.kt ; do CONTENT=$(curl -sf "${BASE}/${FILE}") [ -n "$CONTENT" ] && echo "=== ${FILE} ===" && echo "$CONTENT" done

> **如果某个版本标签尚无源码**(例如v4开发阶段,首个标签尚未包含完整代码树),请回退到`v4_development`分支确认方法签名:将上述URL中的`${TAG}`替换为`v4_development`。当所选标签有源码时,优先使用该标签的源码。

读取获取的源码,并为每个文件记录:
- 已变更的公共方法签名(参数、返回类型、`@Throws`)
- 已移除的构造函数
- 已移除或重命名的类型/类
- 已变更的默认参数值(例如`minTtl`)

这是最准确的依据。步骤7中的每个变更都必须与这些文件中的实际签名匹配。

---

Step 5 — Audit Which Auth0 APIs the Project Uses

步骤5 — 审核项目使用的Auth0 API

Find all source files that import the Auth0 SDK — these are the scope of the migration:
bash
grep -rlE "import com\.auth0\.android" --include="*.kt" --include="*.java" .
Read every file from that list. Do not grep for individual API patterns and stop there — read the full source so you can see exactly how
Auth0
,
WebAuthProvider
,
AuthenticationAPIClient
,
SecureCredentialsManager
/
CredentialsManager
, and any Auth0 types are used, including multi-line builder chains and any custom
Storage
conformances.
For each file, identify:
What to look forSection
PasskeyAuthProvider
usage
§7.1 — class removed
UsersAPIClient
,
ManagementException
,
ManagementCallback
§7.2 — Management API removed
loginWithOTP(
,
loginWithOOB(
,
loginWithRecoveryCode(
,
multifactorChallenge(
on
AuthenticationAPIClient
§7.3 — deprecated MFA methods removed
WebAuthProvider.useDPoP(
called on the object before
.login(
§7.4 —
useDPoP
moved to the login builder
DPoPException.UNSUPPORTED_ERROR
§7.5 — constant removed
.expiresIn
accessed on an
SSOCredentials
value
§7.6 — renamed to
expiresAt
(now a
Date
)
SecureCredentialsManager(
with an
Auth0
instance as the first argument
§7.7 —
Auth0
-based constructors removed
getCredentials(
/
awaitCredentials(
without an explicit
minTtl
, or
hasValidCredentials()
§9.1 — default
minTtl
0 → 60s (behavioral)
clearCredentials(
§9.3 — now clears all storage
A class implementing the
Storage
interface
§9.4 — new
removeAll()
(default impl provided)
Build a checklist: "This project uses: [list]" and "This project does NOT use: [list]". Only work through the §7.x / §9.x sections that appear in the "uses" list. Skip the rest entirely.

查找所有导入Auth0 SDK的源文件——这些是迁移的范围:
bash
grep -rlE "import com\.auth0\.android" --include="*.kt" --include="*.java" .
读取该列表中的每个文件。不要仅通过grep查找单个API模式就停止——请完整读取源码,以准确了解
Auth0
WebAuthProvider
AuthenticationAPIClient
SecureCredentialsManager
/
CredentialsManager
以及任何Auth0类型的使用方式,包括多行构建器链和任何自定义
Storage
实现。
针对每个文件,识别:
查找内容章节
PasskeyAuthProvider
的使用
§7.1 — 类已移除
UsersAPIClient
ManagementException
ManagementCallback
§7.2 — 管理API已移除
AuthenticationAPIClient
上的
loginWithOTP(
loginWithOOB(
loginWithRecoveryCode(
multifactorChallenge(
§7.3 — 已移除废弃的MFA方法
.login(
之前调用
WebAuthProvider.useDPoP(
§7.4 —
useDPoP
已移至登录构建器
DPoPException.UNSUPPORTED_ERROR
§7.5 — 常量已移除
访问
SSOCredentials
值的
.expiresIn
§7.6 — 重命名为
expiresAt
(现为
Date
类型)
使用
Auth0
实例作为第一个参数的
SecureCredentialsManager(
§7.7 — 基于
Auth0
的构造函数已移除
未显式指定
minTtl
getCredentials(
/
awaitCredentials(
,或
hasValidCredentials()
§9.1 — 默认
minTtl
从0变为60秒(行为变更)
clearCredentials(
§9.3 — 现在会清除所有存储
实现
Storage
接口的类
§9.4 — 新增
removeAll()
(提供默认实现)
创建一个检查清单:“本项目使用:[列表]”“本项目未使用:[列表]”。仅处理“使用”列表中对应的§7.x / §9.x章节。完全跳过其余章节。

Step 6 — Update the SDK Dependency

步骤6 — 更新SDK依赖

Apply the matching declaration style. Use
<TARGET_TAG>
from Step 2.
Inline — Groovy DSL (
build.gradle
):
groovy
implementation 'com.auth0.android:auth0:<TARGET_TAG>'
Inline — Kotlin DSL (
build.gradle.kts
):
kotlin
implementation("com.auth0.android:auth0:<TARGET_TAG>")
Version catalog (
gradle/libs.versions.toml
):
toml
[versions]
auth0 = "<TARGET_TAG>"
Pre-release tags (e.g.
4.0.0-beta.1
) must be pinned exactly — do not use a dynamic range like
4.+
or
[4.0,5.0)
, which Gradle may resolve to a different artifact. For stable v4 releases an exact version is still recommended for reproducibility.
Do not build yet — apply all known code changes first (Step 7), then build (Step 8) to surface any remainders.

应用匹配的声明格式。使用步骤2中的
<TARGET_TAG>
内联声明 — Groovy DSL(
build.gradle
):
groovy
implementation 'com.auth0.android:auth0:<TARGET_TAG>'
内联声明 — Kotlin DSL(
build.gradle.kts
):
kotlin
implementation("com.auth0.android:auth0:<TARGET_TAG>")
版本目录(
gradle/libs.versions.toml
):
toml
[versions]
auth0 = "<TARGET_TAG>"
预发布标签(例如
4.0.0-beta.1
)必须精确固定——不要使用动态范围,如
4.+
[4.0,5.0)
,因为Gradle可能会解析到不同的工件。对于稳定的v4版本,仍建议使用精确版本以确保可复现性。
现在不要构建——先应用所有已知的代码变更(步骤7),然后再构建(步骤8)以发现剩余问题。

Step 7 — Apply Breaking Changes

步骤7 — 应用破坏性变更

Agent instruction: Work through only the §7.x sections that matched during the Step 5 audit. Skip every section whose API the project does not use — do not touch those files. Apply each change exactly as shown, confirmed against the source fetched in Step 4. Do not rename variables, reformat, or modernise code that isn't being migrated. Match the project's existing style: callback → callback, coroutine
await
→ coroutine
await
, Kotlin → Kotlin, Java → Java.

Agent指令: 仅处理步骤5审核中匹配的§7.x章节。完全跳过项目未使用对应API的章节——不要修改这些文件。严格按照所示内容应用每个变更,并与步骤4中获取的源码进行确认。不要重命名变量、重新格式化或优化未迁移的代码。匹配项目现有的风格:回调→回调、协程
await
→协程
await
、Kotlin→Kotlin、Java→Java。

7.1 —
PasskeyAuthProvider
removed

7.1 —
PasskeyAuthProvider
已移除

Applies if: Step 5 found
PasskeyAuthProvider
in the project's source files.
The
com.auth0.android.provider.PasskeyAuthProvider
class was removed. Passkey operations now live on
AuthenticationAPIClient
:
passkeyChallenge()
,
signupWithPasskey()
, and
signinWithPasskey()
. Confirm the exact signatures in the
AuthenticationAPIClient.kt
fetched in Step 4, then migrate each call site to the corresponding client method. If a passkey flow cannot be migrated confidently from the source, add a
// TODO:
and list it in the Step 10 summary rather than guessing.

适用场景: 步骤5在项目源文件中发现
PasskeyAuthProvider
com.auth0.android.provider.PasskeyAuthProvider
类已被移除。Passkey操作现在由
AuthenticationAPIClient
提供:
passkeyChallenge()
signupWithPasskey()
signinWithPasskey()
。请在步骤4获取的
AuthenticationAPIClient.kt
中确认精确的方法签名,然后将每个调用站点迁移到对应的客户端方法。如果无法根据源码自信地迁移某个Passkey流程,请添加
// TODO:
注释,并在步骤10的总结中列出,而非猜测。

7.2 — Management API removed (
UsersAPIClient
)

7.2 — 管理API已移除(
UsersAPIClient

Applies if: Step 5 found
UsersAPIClient
,
ManagementException
, or
ManagementCallback
in the project's source files.
The entire Management API client was removed from the SDK in v4. Calling the Management API directly from a mobile app was never recommended — it requires a privileged token on the device. Do not silently delete the call sites. Add a
// TODO:
that preserves the intent and surface this in the Step 10 summary as required backend work.
kotlin
// v3 — direct Management API call from the app (e.g. updating user_metadata)
val users = UsersAPIClient(account, accessToken)
users.updateMetadata(userId, metadata)
    .start(object : Callback<UserProfile, ManagementException> { /* ... */ })

// v4 — Management client removed; preserve intent, move to a backend
// TODO: Auth0.Android v4 removed the Management API client (UsersAPIClient).
// Expose an endpoint on your own backend (e.g. PATCH /me/metadata) that performs
// this operation. Call it from the app with the user's access token as a Bearer
// token. On the backend, obtain a machine-to-machine token via Client Credentials
// and call the Management API with the minimum required scopes.
// NEVER embed a Management API token in the app.
// See: https://auth0.com/docs/manage-users/user-accounts/manage-user-metadata
This requires backend work — record it in the Step 10 summary.

适用场景: 步骤5在项目源文件中发现
UsersAPIClient
ManagementException
ManagementCallback
v4版本中,SDK已移除整个管理API客户端。从移动应用直接调用管理API从未被推荐——这需要在设备上使用特权令牌。不要静默删除调用站点。请添加
// TODO:
注释以保留原有意图,并在步骤10的总结中指出这是需要后端处理的工作。
kotlin
// v3 — 从应用直接调用管理API(例如更新user_metadata)
val users = UsersAPIClient(account, accessToken)
users.updateMetadata(userId, metadata)
    .start(object : Callback<UserProfile, ManagementException> { /* ... */ })

// v4 — 管理客户端已移除;保留原有意图,迁移至后端
// TODO: Auth0.Android v4已移除管理API客户端(UsersAPIClient)。
// 在您自己的后端暴露一个端点(例如PATCH /me/metadata)来执行此操作。
// 使用用户的访问令牌作为Bearer令牌从应用调用该端点。
// 在后端,通过客户端凭据获取机器到机器令牌,并使用最小必要的作用域调用管理API。
// 绝不要在应用中嵌入管理API令牌。
// 参考:https://auth0.com/docs/manage-users/user-accounts/manage-user-metadata
需要后端工作——请在步骤10的总结中记录。

7.3 — Deprecated MFA methods removed from
AuthenticationAPIClient
MfaApiClient

7.3 —
AuthenticationAPIClient
上的废弃MFA方法已移除 → 迁移至
MfaApiClient

Applies if: Step 5 found
loginWithOTP(
,
loginWithOOB(
,
loginWithRecoveryCode(
, or
multifactorChallenge(
called on an
AuthenticationAPIClient
in the project's source files.
These four methods were deprecated in v3 and removed in v4. Obtain an
MfaApiClient
via
AuthenticationAPIClient.mfaClient(mfaToken)
and use its APIs. Confirm the exact
MfaApiClient
method signatures in the
MfaApiClient.kt
fetched in Step 4 before applying changes.
kotlin
// v3 — removed methods on AuthenticationAPIClient
authentication
    .loginWithOTP(mfaToken, otp)
    .start(object : Callback<Credentials, AuthenticationException> { /* ... */ })

// v4 — obtain an MfaApiClient and use its verify API (confirm signature in MfaApiClient.kt)
val mfaClient = authentication.mfaClient(mfaToken)
// e.g. mfaClient.verifyWithOTP(otp) — use the exact method/parameters from the fetched source
The
mfaToken
still comes from the same place — an
AuthenticationException
where the challenge is required. List every migrated MFA flow in the Step 10 summary and ask the user to re-test each MFA flow end-to-end against their tenant. See references/process.md for the full method map.

适用场景: 步骤5在项目源文件中发现
AuthenticationAPIClient
上调用了
loginWithOTP(
loginWithOOB(
loginWithRecoveryCode(
multifactorChallenge(
这四个方法在v3中已被废弃,在v4中已被移除。请通过
AuthenticationAPIClient.mfaClient(mfaToken)
获取
MfaApiClient
并使用其API。在应用变更前,请在步骤4获取的
MfaApiClient.kt
中确认
MfaApiClient
的精确方法签名。
kotlin
// v3 — AuthenticationAPIClient上已移除的方法
authentication
    .loginWithOTP(mfaToken, otp)
    .start(object : Callback<Credentials, AuthenticationException> { /* ... */ })

// v4 — 获取MfaApiClient并使用其验证API(请在MfaApiClient.kt中确认签名)
val mfaClient = authentication.mfaClient(mfaToken)
// 例如mfaClient.verifyWithOTP(otp) — 使用获取的源码中的精确方法/参数
mfaToken
的来源不变——来自需要挑战的
AuthenticationException
。请在步骤10的总结中列出所有已迁移的MFA流程,并要求用户针对其租户端到端重新测试每个MFA流程。有关完整的方法映射,请参阅references/process.md

7.4 —
WebAuthProvider.useDPoP(context)
moved to the login builder

7.4 —
WebAuthProvider.useDPoP(context)
已移至登录构建器

Applies if: Step 5 found
WebAuthProvider.useDPoP(
called on the
WebAuthProvider
object before
.login(
. Read the actual call chain — it may span multiple lines.
In v4,
useDPoP(context)
is configured per-request on the login builder rather than globally on the
WebAuthProvider
object. Move the
.useDPoP(context)
call so it chains after
.login(account)
.
kotlin
// v3 — global configuration (no longer compiles)
WebAuthProvider
    .useDPoP(context)
    .login(account)
    .start(context, callback)

// v4 — builder-based, per-request
WebAuthProvider
    .login(account)
    .useDPoP(context)
    .start(context, callback)

适用场景: 步骤5在项目源文件中发现
WebAuthProvider
对象上
.login(
之前
调用了
WebAuthProvider.useDPoP(
。请读取实际的调用链——它可能跨多行。
在v4中,
useDPoP(context)
是在登录构建器上按请求配置的,而非在
WebAuthProvider
对象上全局配置。请将
.useDPoP(context)
调用移至
.login(account)
之后。
kotlin
// v3 — 全局配置(不再编译)
WebAuthProvider
    .useDPoP(context)
    .login(account)
    .start(context, callback)

// v4 — 基于构建器,按请求配置
WebAuthProvider
    .login(account)
    .useDPoP(context)
    .start(context, callback)

7.5 —
DPoPException.UNSUPPORTED_ERROR
removed

7.5 —
DPoPException.UNSUPPORTED_ERROR
已移除

Applies if: Step 5 found
DPoPException.UNSUPPORTED_ERROR
in the project's source files.
With the minimum SDK raised to API 26, DPoP is supported on every API level v4 targets, so this constant was removed. Remove any reference to it — for example, a
when
/
if
branch or comparison that checked for
UNSUPPORTED_ERROR
. No replacement is needed; the unsupported-version case can no longer occur.
kotlin
// v3 — guarding against the unsupported case
if (error == DPoPException.UNSUPPORTED_ERROR) {   // ❌ no longer exists in v4
    showDeviceUnsupported()
} else {
    handle(error)
}

// v4 — the guard is no longer applicable; handle the remaining cases
handle(error)

适用场景: 步骤5在项目源文件中发现
DPoPException.UNSUPPORTED_ERROR
由于最低SDK已提升至API 26,v4支持的所有API级别都支持DPoP,因此该常量已被移除。请删除所有对它的引用——例如检查
UNSUPPORTED_ERROR
when
/
if
分支或比较。无需替代方案;不支持的情况已不再可能发生。
kotlin
// v3 — 防范不支持的情况
if (error == DPoPException.UNSUPPORTED_ERROR) {   // ❌ v4中已不存在
    showDeviceUnsupported()
} else {
    handle(error)
}

// v4 — 该防范已不再适用;处理剩余情况
handle(error)

7.6 —
SSOCredentials.expiresIn
expiresAt
(
Int
Date
)

7.6 —
SSOCredentials.expiresIn
expiresAt
Int
Date

Applies if: Step 5 found
.expiresIn
accessed on an
SSOCredentials
value in the project's source files.
SSOCredentials.expiresIn
(raw seconds,
Int
) was renamed to
expiresAt
and is now an absolute
Date
(computed during deserialization, consistent with
Credentials.expiresAt
). Rename the property and update any arithmetic that assumed a duration in seconds.
The JSON wire format is unchanged — the field is still
@field:SerializedName("expires_in")
in the SDK. Only the Kotlin property name and type changed (
expiresIn: Int
expiresAt: Date
); don't expect a renamed
expires_at
key if you grep the raw JSON.
kotlin
// v3 — seconds until expiry (Int)
val secondsUntilExpiry: Int = ssoCredentials.expiresIn

// v4 — absolute expiration Date
val expirationDate: Date = ssoCredentials.expiresAt
// If you previously did `now + expiresIn` to get an absolute time, use expiresAt directly.

适用场景: 步骤5在项目源文件中发现访问
SSOCredentials
值的
.expiresIn
SSOCredentials.expiresIn
(原始秒数,
Int
类型)已重命名为
expiresAt
,现在是一个绝对
Date
类型(在反序列化期间计算,与
Credentials.expiresAt
一致)。请重命名该属性更新任何假设其为秒数时长的运算。
JSON传输格式未变——SDK中该字段仍为
@field:SerializedName("expires_in")
。仅Kotlin属性名称和类型发生了变化(
expiresIn: Int
expiresAt: Date
);如果您搜索原始JSON,不要期望找到重命名后的
expires_at
键。
kotlin
// v3 — 到期剩余秒数(Int)
val secondsUntilExpiry: Int = ssoCredentials.expiresIn

// v4 — 绝对到期日期
val expirationDate: Date = ssoCredentials.expiresAt
// 如果您之前通过`now + expiresIn`获取绝对时间,请直接使用expiresAt。

7.7 —
SecureCredentialsManager
Auth0
-based constructors removed

7.7 —
SecureCredentialsManager
基于
Auth0
的构造函数已移除

Applies if: Step 5 found
SecureCredentialsManager(
constructed with an
Auth0
instance as the first argument in the project's source files.
The two constructors that accepted an
Auth0
instance were removed. Both remaining constructors take an
AuthenticationAPIClient
first. Build the client from the
Auth0
account, then pass the same client into
SecureCredentialsManager
.
kotlin
// v3 — Auth0-based constructors (removed in v4)
val manager = SecureCredentialsManager(auth0, context, storage)
val manager = SecureCredentialsManager(auth0, context, storage, fragmentActivity, localAuthenticationOptions)

// v4 — build an AuthenticationAPIClient first, pass it in
val apiClient = AuthenticationAPIClient(auth0)
val manager = SecureCredentialsManager(apiClient, context, storage)

// v4 — biometric variant
val apiClient = AuthenticationAPIClient(auth0)
val manager = SecureCredentialsManager(
    apiClient,
    context,
    storage,
    fragmentActivity,
    localAuthenticationOptions
)
java
// Java — same change; there is no Java-specific overload
AuthenticationAPIClient apiClient = new AuthenticationAPIClient(auth0);
SecureCredentialsManager manager = new SecureCredentialsManager(apiClient, context, storage);
If the project enables DPoP, configure it on the client before passing it in:
AuthenticationAPIClient(auth0).useDPoP(context)
. Confirm the constructor signatures in the
SecureCredentialsManager.kt
fetched in Step 4.

适用场景: 步骤5在项目源文件中发现使用
Auth0
实例作为第一个参数构造
SecureCredentialsManager(
接受
Auth0
实例的两个构造函数已被移除。剩余的两个构造函数都以
AuthenticationAPIClient
作为第一个参数。请从
Auth0
账户构建客户端,然后将同一个客户端传入
SecureCredentialsManager
kotlin
// v3 — 基于Auth0的构造函数(v4中已移除)
val manager = SecureCredentialsManager(auth0, context, storage)
val manager = SecureCredentialsManager(auth0, context, storage, fragmentActivity, localAuthenticationOptions)

// v4 — 先构建AuthenticationAPIClient,再传入
val apiClient = AuthenticationAPIClient(auth0)
val manager = SecureCredentialsManager(apiClient, context, storage)

// v4 — 生物识别变体
val apiClient = AuthenticationAPIClient(auth0)
val manager = SecureCredentialsManager(
    apiClient,
    context,
    storage,
    fragmentActivity,
    localAuthenticationOptions
)
java
// Java — 变更相同;没有Java特定的重载
AuthenticationAPIClient apiClient = new AuthenticationAPIClient(auth0);
SecureCredentialsManager manager = new SecureCredentialsManager(apiClient, context, storage);
如果项目启用了DPoP,请在传入客户端前对其进行配置:
AuthenticationAPIClient(auth0).useDPoP(context)
。请在步骤4获取的
SecureCredentialsManager.kt
中确认构造函数签名。

Step 8 — Build Until Green

步骤8 — 构建直至成功

bash
./gradlew assembleDebug 2>&1 | tail -40
For each error: read it, locate the source line, match it to a Step 7 section, verify the fix against the signature fetched in Step 4, apply it in the project's existing style, then rebuild.
Common error → cause mapping:
Build errorLikely cause
unresolved reference: PasskeyAuthProvider
§7.1 — class removed; use
AuthenticationAPIClient
passkey APIs
unresolved reference: UsersAPIClient
/
ManagementException
/
ManagementCallback
§7.2 — Management API removed; add
// TODO:
+ backend follow-up
unresolved reference: loginWithOTP
/
loginWithOOB
/
loginWithRecoveryCode
/
multifactorChallenge
§7.3 — use
mfaClient(mfaToken)
/
MfaApiClient
unresolved reference: useDPoP
on
WebAuthProvider
§7.4 — move
.useDPoP(context)
after
.login(account)
unresolved reference: UNSUPPORTED_ERROR
§7.5 — remove the reference
unresolved reference: expiresIn
on
SSOCredentials
, or
Int
/
Date
type mismatch
§7.6 — rename to
expiresAt
(now a
Date
)
none of the following functions can be called
/
too many arguments
on
SecureCredentialsManager(
§7.7 — build
AuthenticationAPIClient(auth0)
first, pass it in
class … must override removeAll
(custom
Storage
)
§9.4 — the interface has a default impl; override only if needed
Limit: Up to 10 build-fix cycles. If the build still fails after 10 attempts, stop and show the remaining errors with context — do not guess.

bash
./gradlew assembleDebug 2>&1 | tail -40
针对每个错误:读取错误信息,定位源码行,匹配到步骤7对应的章节,根据步骤4获取的签名验证修复方案,按照项目现有风格应用修复,然后重新构建。
常见错误→原因映射:
构建错误可能原因
unresolved reference: PasskeyAuthProvider
§7.1 — 类已移除;使用
AuthenticationAPIClient
的Passkey API
unresolved reference: UsersAPIClient
/
ManagementException
/
ManagementCallback
§7.2 — 管理API已移除;添加
// TODO:
+ 后端后续处理
unresolved reference: loginWithOTP
/
loginWithOOB
/
loginWithRecoveryCode
/
multifactorChallenge
§7.3 — 使用
mfaClient(mfaToken)
/
MfaApiClient
unresolved reference: useDPoP
on
WebAuthProvider
§7.4 — 将
.useDPoP(context)
移至
.login(account)
之后
unresolved reference: UNSUPPORTED_ERROR
§7.5 — 删除该引用
unresolved reference: expiresIn
on
SSOCredentials
,或
Int
/
Date
类型不匹配
§7.6 — 重命名为
expiresAt
(现为
Date
类型)
none of the following functions can be called
/
too many arguments
on
SecureCredentialsManager(
§7.7 — 先构建
AuthenticationAPIClient(auth0)
,再传入
class … must override removeAll
(自定义
Storage
§9.4 — 该接口提供了默认实现;仅在需要时才重写
限制: 最多进行10次构建-修复循环。如果10次尝试后构建仍失败,请停止并向用户显示剩余错误及上下文——不要猜测。

Step 9 — Behavior & Default-Value Changes (Review, Usually No Code Change)

步骤9 — 行为与默认值变更(仅需评审,通常无需修改代码)

These changes compile without edits but alter runtime behavior. Surface each in the Step 10 summary. Only change code if the project depends on the old behavior.
这些变更无需修改代码即可编译,但会改变运行时行为。请在步骤10的总结中逐一说明。仅当项目依赖旧行为时才修改代码。

9.1 — Credentials Manager default
minTtl
0 → 60s

9.1 — Credentials Manager默认
minTtl
从0变为60秒

Applies if: the project calls
getCredentials(...)
/
awaitCredentials(...)
without an explicit
minTtl
, or calls
hasValidCredentials()
.
v4 renews credentials that expire within 60 seconds instead of only when already expired. This is the recommended behavior (avoids handing out tokens that expire mid-request). To restore v3 behavior explicitly, pass
minTtl = 0
:
kotlin
// v4 — restore v3 behavior explicitly if required
credentialsManager.getCredentials(scope = null, minTtl = 0, callback = callback)
适用场景: 项目调用
getCredentials(...)
/
awaitCredentials(...)
时未显式指定
minTtl
,或调用
hasValidCredentials()
v4版本会在凭证到期前60秒进行续订,而不是仅在凭证已到期时才续订。这是推荐的行为(避免分发在请求过程中到期的令牌)。如果需要恢复v3行为,请显式传入
minTtl = 0
kotlin
// v4 — 如果需要,显式恢复v3行为
credentialsManager.getCredentials(scope = null, minTtl = 0, callback = callback)

9.2 —
CredentialsManager
now uses the global executor

9.2 —
CredentialsManager
现在使用全局执行器

Runtime-only. Renewals across managers backed by the same
Auth0
object are now serialized, eliminating duplicate refresh-token exchanges. No code change required.
仅影响运行时。基于同一个
Auth0
对象的多个管理器的续订操作现在会被序列化,消除了重复的刷新令牌交换。无需修改代码。

9.3 —
clearCredentials()
now clears all storage

9.3 —
clearCredentials()
现在会清除所有存储

Applies if: the project calls
clearCredentials()
.
v4 calls
Storage.removeAll()
, clearing all values in the storage — including API credentials stored for specific audiences. If the project needs to preserve other data in the same
Storage
, recommend a separate
Storage
instance for API credentials, or consider the new
clearAll()
(Step 10 optional improvements).
适用场景: 项目调用
clearCredentials()
v4版本会调用
Storage.removeAll()
,清除存储中的所有值——包括为特定受众存储的API凭证。如果项目需要保留同一
Storage
中的其他数据,建议为API凭证使用单独的
Storage
实例,或考虑使用新的
clearAll()
(步骤10中的可选优化)。

9.4 —
Storage
interface gains
removeAll()

9.4 —
Storage
接口新增
removeAll()

Applies if: the project has a class implementing the
Storage
interface.
removeAll()
ships with a default empty implementation, so existing custom
Storage
implementations still compile. Override
removeAll()
to actually clear storage if that custom storage is used with
clearCredentials()
— otherwise
clearCredentials()
becomes a no-op for it.

适用场景: 项目存在实现
Storage
接口的类。
removeAll()
提供了默认的空实现,因此现有的自定义
Storage
实现仍可编译。**如果自定义存储与
clearCredentials()
一起使用,请重写
removeAll()
**以实际清除存储——否则
clearCredentials()
对该自定义存储将无效。

Step 10 — Migration Summary

步骤10 — 迁移总结

Present a concise summary covering:
1. Prerequisites changed
minSdk
/ Java / Gradle / AGP / Kotlin bumps applied, and that
minSdk 26
drops support for Android 7.1 and below.
2. Changes applied — grouped by API area (§7.x), with the files touched per area.
3. Needs manual review
  • §7.1 Passkey / §7.3 MFA flows migrated to the new clients — re-test end-to-end against the tenant.
  • Any
    // TODO:
    left for §7.2 (Management API) — backend work required.
4. Behavioral changes (no code change, verify acceptable)
  • §9.1
    minTtl
    now defaults to 60s — tokens renew 60s before expiry.
  • §9.3
    clearCredentials()
    now clears all storage (including API credentials).
  • §9.2
    CredentialsManager
    now uses the global executor (renewals serialized).
5. Backend / configuration follow-up
  • §7.2 Management API removal — list the operations stubbed with
    TODO
    and what must move to a secure backend (M2M token, never on-device).
6. Optional improvements not applied (list briefly; never auto-apply)
  • clearAll()
    — full credential and cryptographic key cleanup on logout/account removal.
  • WebAuthProvider.registerCallbacks()
    in
    onCreate()
    — prevents lost callbacks / memory leaks on configuration change or process death during authentication.
  • DefaultClient.Builder
    — the constructor is deprecated (not removed); the builder adds write/call timeouts, custom interceptors, and loggers.
  • Gson 2.8.9 → 2.11.0 (transitive) — stricter
    TypeToken
    / type coercion; see references/process.md.
7. Ask the user whether to commit the migration, explore an optional improvement, or step through specific files together.
Security reminder: Never include tokens, secrets, client credentials, or stored credential values in the summary or any build log.

呈现简洁的总结,涵盖以下内容:
1. 先决条件变更 — 已应用
minSdk
/ Java / Gradle / AGP / Kotlin版本提升,且
minSdk 26
不再支持Android 7.1及以下版本。
2. 已应用的变更 — 按API领域(§7.x)分组,列出每个领域涉及的文件。
3. 需要手动评审的内容
  • §7.1 Passkey / §7.3 MFA流程已迁移至新客户端——针对租户端到端重新测试
  • §7.2(管理API)中留下的任何
    // TODO:
    注释——需要后端工作。
4. 行为变更(无需修改代码,请确认是否可接受)
  • §9.1
    minTtl
    现在默认值为60秒——令牌会在到期前60秒续订。
  • §9.3
    clearCredentials()
    现在会清除所有存储(包括API凭证)。
  • §9.2
    CredentialsManager
    现在使用全局执行器(续订操作已序列化)。
5. 后端/配置后续工作
  • §7.2管理API移除——列出用
    TODO
    标记的操作,以及必须迁移到安全后端的内容(M2M令牌,绝不能在设备上使用)。
6. 未应用的可选优化(简要列出;绝不要自动应用)
  • clearAll()
    ——登出/移除账户时完全清除凭证加密密钥。
  • onCreate()
    中使用
    WebAuthProvider.registerCallbacks()
    ——防止在认证过程中因配置变更或进程死亡导致回调丢失/内存泄漏。
  • DefaultClient.Builder
    ——构造函数已被废弃(未移除);构建器添加了写入/调用超时、自定义拦截器和日志记录器。
  • Gson从2.8.9升级至2.11.0(传递依赖)——
    TypeToken
    /类型强制转换更严格;请参阅references/process.md
7. 询问用户 是否提交迁移变更、探索某个可选优化,或一起查看特定文件。
安全提醒: 绝不要在总结或任何构建日志中包含令牌、密钥、客户端凭证或存储的凭证值。

Detailed References

详细参考

  • Migration Process — version-argument validation, prerequisite/toolchain handling, build-system edge cases (Groovy DSL, Kotlin DSL, version catalogs), MFA method map, Management-API backend pattern, Gson transitive notes, rollback, and "deprecated ≠ removed" guidance.
  • Security Checklist — invariants that must hold before and after migration.
  • 迁移流程 — 版本参数验证、先决条件/工具链处理、构建系统特殊情况(Groovy DSL、Kotlin DSL、版本目录)、MFA方法映射、管理API后端模式、Gson传递依赖说明、回滚以及“废弃≠移除”指南。
  • 安全清单 — 迁移前后必须保持不变的安全规则。

Common Mistakes

常见错误

MistakeCorrect approach
Applying a §7.x section when Step 5 didn't find that API in the projectStep 5 file-reading is the gate. Not found = skip the section entirely
Using grep alone to decide if an API is usedGrep misses multi-line builder chains (e.g.
useDPoP
before
login
) and aliased variables. Read the actual files
Migrating API call sites before meeting the Step 3 prerequisitesA project below
minSdk 26
/ Java 17 won't build against v4. Handle prerequisites first
Accepting a target-version argument without validating itValidate exists / next-major / not-a-downgrade, then stop and ask on failure
Using a dynamic range (
4.+
) for a pre-release tag
Pin pre-releases exactly — ranges may resolve to a different artifact
Silently deleting Management API or removed-MFA call sitesAdd
// TODO:
and surface in the summary — deletion breaks functionality
Applying changes from the migration guide without confirming the SDK sourceEvery fix must trace to a signature in the files fetched in Step 4
Treating
DefaultClient(...)
constructor as a breaking change
It is deprecated, not removed — leave it; note the Builder as optional
Starting on a dirty working treeAlways verify
git status --porcelain
is empty first
Continuing past 10 failed build cyclesStop and show the user the remaining errors
Skipping the migration summaryAlways produce the full summary — the user needs it
错误做法正确做法
步骤5未在项目中找到对应API,仍应用§7.x章节的变更步骤5的文件读取是变更的依据。未找到对应API则完全跳过该章节
仅使用grep判断是否使用某个APIGrep会遗漏多行构建器链(例如
useDPoP
login
之前)和别名变量。请读取实际文件
在满足步骤3的先决条件之前迁移API调用站点
minSdk
低于26 / Java版本低于17的项目无法基于v4构建。请先处理先决条件
未验证就接受目标版本参数验证参数的存在性/是否为下一个大版本/是否非降级,失败时停止并询问用户
对预发布标签使用动态范围(
4.+
精确固定预发布版本——动态范围可能会解析到不同的工件
静默删除管理API或已移除的MFA调用站点添加
// TODO:
注释并在总结中指出——删除会破坏功能
未确认SDK源码就应用迁移指南中的变更每个修复都必须追溯到步骤4获取的文件中的签名
DefaultClient(...)
构造函数视为破坏性变更
它只是被废弃,而非被移除——保留即可;将Builder列为可选优化
在不干净的工作区开始迁移始终先验证
git status --porcelain
输出为空
超过10次构建失败仍继续停止并向用户显示剩余错误
跳过迁移总结始终生成完整的总结——用户需要这些信息

Related Skills

相关技能



References

参考链接

Security: Never echo tokens, client secrets, or credentials in build logs or terminal output. Never commit secrets to version control.
安全提示: 绝不要在构建日志或终端输出中回显令牌、客户端密钥或凭证。绝不要将密钥提交到版本控制系统。