capacitor-android-dex-optimization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Capacitor Android: DEX Code Optimization

Capacitor Android:DEX 代码优化

Enable R8 in a Capacitor Android app and add the keep rules a Capacitor app needs so that the release build passes the Google Play DEX code optimization requirement without crashing at startup.
The Android project that
npx cap add android
generates sets
minifyEnabled false
, so R8 never runs and Google Play measures close to 0% obfuscation, optimization and shrinking. From February 2027, Google Play requires at least 25% in each category for apps with more than 10 MB of DEX code. Play reads the numbers from the
r8.json
file inside the app bundle for apps built with AGP 8.10 or newer.
在 Capacitor Android 应用中启用 R8,并添加 Capacitor 应用所需的 keep 规则,使 release 构建能够通过 Google Play DEX 代码优化要求,同时避免启动时崩溃。
npx cap add android
生成的 Android 项目会将
minifyEnabled
设置为
false
,因此 R8 从不运行,Google Play 测得的混淆、优化和收缩比例都接近 0%。自 2027 年 2 月起,对于 DEX 代码超过 10 MB 的应用,Google Play 要求每个类别至少达到 25%。对于使用 AGP 8.10 或更高版本构建的应用,Play 会从 app bundle 内的
r8.json
文件读取这些数值。

Prerequisites

前置条件

RequirementVersion
Capacitor6+
Android Gradle Plugin8.0+ (8.10+ for the
r8.json
check in Step 6)
JDK17 for Capacitor 6 and 7, 21 for Capacitor 8
adb
installed, with a device or emulator connected for Step 5
The project must be a Capacitor app (not a plugin) with an existing
android/
directory.
要求版本
Capacitor6+
Android Gradle Plugin8.0+(步骤 6 中检查
r8.json
需要 8.10+)
JDKCapacitor 6 和 7 使用 17,Capacitor 8 使用 21
adb
已安装,并为步骤 5 连接设备或模拟器
项目必须是 Capacitor app(而不是 plugin),并且已有
android/
目录。

Agent Behavior

Agent 行为

  • Inspect before editing. Read the current Gradle and ProGuard configuration first (Step 1). Never overwrite existing rules in
    android/app/proguard-rules.pro
    ; append to them.
  • Keep rules narrow. Never add
    -keep class com.getcapacitor.** { *; }
    or
    -dontobfuscate
    . Broad rules block the optimization that Google Play measures.
    @capacitor/android
    already ships consumer rules for plugin classes and their annotated methods.
  • Only release builds run R8. Debug builds never show whether the rules are complete. Every verification step uses a signed release build.
  • Read
    missing_rules.txt
    before pasting it.
    A
    -dontwarn
    rule is correct only for a class a plugin probes for at runtime (Step 4).
  • 编辑前先检查。 首先读取当前的 Gradle 和 ProGuard 配置(步骤 1)。绝不覆盖
    android/app/proguard-rules.pro
    中已有的规则;应将新规则追加到其中。
  • keep 规则应尽量精确。 绝不添加
    -keep class com.getcapacitor.** { *; }
    或
    -dontobfuscate
    。宽泛规则会阻止 Google Play 所统计的大部分优化。
    @capacitor/android
    已经提供 consumer rules,用于保留插件类及其带注解的方法。
  • 只有 release 构建会运行 R8。 Debug 构建无法反映规则是否完整。每个验证步骤都应使用已签名的 release 构建。
  • 粘贴前先读取
    missing_rules.txt
    。
    只有当插件会在运行时探测某个类时,对应的
    -dontwarn
    规则才是正确的(步骤 4)。

Procedures

操作步骤

Step 1: Analyze the Project

步骤 1:分析项目

  1. Verify the project is a Capacitor app:
    package.json
    lists
    @capacitor/android
    in
    dependencies
    and the
    android/
    directory exists. If
    android/
    is missing, abort and inform the user.
  2. Read the
    @capacitor/core
    version from
    package.json
    . Record the major version.
  3. Read the AGP version from
    android/build.gradle
    :
    groovy
    classpath 'com.android.tools.build:gradle:8.13.2'
    If the major version is below 8, abort and direct the user to the
    capacitor-app-upgrades
    skill first. Record whether the version is 8.10 or newer (this decides whether Step 6 applies).
  4. Read the
    release
    build type in
    android/app/build.gradle
    . Record the values of
    minifyEnabled
    ,
    shrinkResources
    (if present) and the
    proguardFiles
    line.
  5. Read
    android/app/proguard-rules.pro
    and record every existing rule.
  6. Read
    android/gradle.properties
    and record whether
    android.enableR8.fullMode
    is set. If it is set to
    false
    , inform the user that the keep rule in Step 3 makes this setting unnecessary and offer to remove it, because full mode produces higher optimization numbers.
  7. Inventory the installed Capacitor plugins from
    package.json
    dependencies
    . Match these prefixes:
    • @capacitor/*
    • @capawesome/*
      and
      @capawesome-team/*
    • @capacitor-community/*
    • @capacitor-firebase/*
    • @capacitor-mlkit/*
    • @revenuecat/*
    • Any other package with
      "capacitor"
      in its
      package.json
      keywords
      array
    Record each plugin's package name. Step 3 uses this list.
  1. 验证项目是 Capacitor app:
    package.json
    的
    dependencies
    中包含
    @capacitor/android
    ,并且存在
    android/
    目录。如果缺少
    android/
    ,则中止操作并告知用户。
  2. 从
    package.json
    中读取
    @capacitor/core
    版本。记录其主版本号。
  3. 从
    android/build.gradle
    中读取 AGP 版本:
    groovy
    classpath 'com.android.tools.build:gradle:8.13.2'
    如果主版本低于 8,则中止操作,并首先引导用户使用
    capacitor-app-upgrades
    skill。记录该版本是否为 8.10 或更高版本,这将决定步骤 6 是否适用。
  4. 读取
    android/app/build.gradle
    中的
    release
    build type。记录
    minifyEnabled
    、
    shrinkResources
    (如果存在)以及
    proguardFiles
    行的值。
  5. 读取
    android/app/proguard-rules.pro
    ,并记录每一条已有规则。
  6. 读取
    android/gradle.properties
    ,记录是否设置了
    android.enableR8.fullMode
    。如果设置为
    false
    ,告知用户步骤 3 中的 keep 规则会使此设置变得不再必要,并主动询问是否将其移除,因为 full mode 能产生更高的优化数值。
  7. 根据
    package.json
    的
    dependencies
    盘点已安装的 Capacitor 插件。匹配以下前缀:
    • @capacitor/*
    • @capawesome/*
      和
      @capawesome-team/*
    • @capacitor-community/*
    • @capacitor-firebase/*
    • @capacitor-mlkit/*
    • @revenuecat/*
    • 任何其他
      package.json
      的
      keywords
      数组中包含
      capacitor
      的包
    记录每个插件的 package name。步骤 3 会使用此列表。

Step 2: Enable R8

步骤 2:启用 R8

In
android/app/build.gradle
, update the
release
build type. Replace
minifyEnabled false
with
minifyEnabled true
and replace
proguard-android.txt
with
proguard-android-optimize.txt
:
diff
 android {
     buildTypes {
         release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            minifyEnabled true
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
 }
proguard-android.txt
contains
-dontoptimize
, which blocks most of what R8 could do, and AGP 9 no longer accepts that file by default. Do not add
shrinkResources true
. The Play metrics measure DEX code, and resource shrinking breaks resources that are referenced by name from JavaScript or
capacitor.config.ts
(for example the
smallIcon
of the Push Notifications plugin).
在
android/app/build.gradle
中更新
release
build type。将
minifyEnabled false
替换为
minifyEnabled true
,并将
proguard-android.txt
替换为
proguard-android-optimize.txt
:
diff
 android {
     buildTypes {
         release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            minifyEnabled true
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
 }
proguard-android.txt
包含
-dontoptimize
,会阻止 R8 能够完成的大部分优化,而且 AGP 9 默认不再接受此文件。不要添加
shrinkResources true
。Play 指标衡量的是 DEX 代码,而资源收缩会破坏由 JavaScript 或
capacitor.config.ts
按名称引用的资源,例如 Push Notifications 插件的
smallIcon
。

Step 3: Add Keep Rules

步骤 3:添加 Keep 规则

  1. If the Capacitor version recorded in Step 1 is below 8.6.0, append the Capacitor annotation rule to
    android/app/proguard-rules.pro
    . Skip this if the file already contains the exact rule or if the app is on Capacitor 8.6.0 or newer, which ships the rule in its consumer rules:
    diff
    +# Capacitor annotations: required below Capacitor 8.6.0 in R8 full mode (ionic-team/capacitor#8589)
    +-keep @interface com.getcapacitor.** { *; }
    R8 full mode (the default since AGP 8.0) strips annotations from classes that are not explicitly kept. Before Capacitor 8.6.0,
    @capacitor/android
    kept the classes annotated with
    @CapacitorPlugin
    but not the annotation types themselves. Without the rule, the build passes and the app crashes on startup with a
    NullPointerException
    in
    com.getcapacitor.Plugin.getPermissionStates
    the first time a plugin checks its permissions. The rule covers
    @CapacitorPlugin
    ,
    @Permission
    ,
    @PermissionCallback
    ,
    @ActivityCallback
    ,
    @PluginMethod
    and the legacy
    @NativePlugin
    .
  2. For each plugin recorded in Step 1, look up its ProGuard rules and append them to
    android/app/proguard-rules.pro
    if they are missing:
    • Read the plugin's README in
      node_modules/<package>/README.md
      and search for a
      Proguard
      ,
      ProGuard
      or
      R8
      section.
    • For Capawesome, Capacitor Firebase, Capacitor MLKit and RevenueCat plugins, the
      capacitor-plugins
      skill ships a reference file per plugin in its
      references/
      directory with the same section.
    Most plugins ship no rules of their own because the Capacitor consumer rules cover them. A plugin documents a rule only when it relies on reflection or serialization. Example for the Capawesome SQLite plugin:
    diff
    +# Capawesome plugins that rely on reflection
    +-keep class io.capawesome.capacitorjs.plugins.** { *; }
  3. Do not add rules for
    com.getcapacitor.**
    classes,
    @JavascriptInterface
    methods, Firebase or Play Services.
    @capacitor/android
    declares its own consumer rules that keep every class annotated with
    @CapacitorPlugin
    together with its
    @PluginMethod
    ,
    @PermissionCallback
    and
    @ActivityCallback
    methods. AGP's default rules keep
    @JavascriptInterface
    methods, and the large SDKs ship consumer rules of their own.
  1. 如果步骤 1 中记录的 Capacitor 版本低于 8.6.0,将 Capacitor 注解规则追加到
    android/app/proguard-rules.pro
    。如果文件中已经包含完全相同的规则,或者应用使用的是 Capacitor 8.6.0 或更高版本,则跳过此步骤,因为后者的 consumer rules 已自带该规则:
    diff
    +# Capacitor annotations: required below Capacitor 8.6.0 in R8 full mode (ionic-team/capacitor#8589)
    +-keep @interface com.getcapacitor.** { *; }
    R8 full mode(自 AGP 8.0 起为默认值)会从未显式保留的类中移除注解。在 Capacitor 8.6.0 之前,
    @capacitor/android
    会保留使用
    @CapacitorPlugin
    标注的类,但不会保留注解类型本身。如果没有此规则,构建会通过,但当某个插件首次检查权限时,应用会在
    com.getcapacitor.Plugin.getPermissionStates
    中因
    NullPointerException
    而启动崩溃。该规则涵盖
    @CapacitorPlugin
    、
    @Permission
    、
    @PermissionCallback
    、
    @ActivityCallback
    、
    @PluginMethod
    以及旧版的
    @NativePlugin
    。
  2. 对步骤 1 中记录的每个插件,查找其 ProGuard 规则;如果缺少规则,则将其追加到
    android/app/proguard-rules.pro
    :
    • 读取插件的
      node_modules/<package>/README.md
      ,搜索
      Proguard
      、
      ProGuard
      或
      R8
      章节。
    • 对于 Capawesome、Capacitor Firebase、Capacitor MLKit 和 RevenueCat 插件,
      capacitor-plugins
      skill 会在其
      references/
      目录中为每个插件提供一个包含相同章节的参考文件。
    大多数插件不会自带规则,因为 Capacitor consumer rules 已覆盖这些插件。只有当插件依赖反射或序列化时,其文档才会提供规则。以下是 Capawesome SQLite 插件的示例:
    diff
    +# Capawesome plugins that rely on reflection
    +-keep class io.capawesome.capacitorjs.plugins.** { *; }
  3. 不要为
    com.getcapacitor.**
    类、
    @JavascriptInterface
    方法、Firebase 或 Play Services 添加规则。
    @capacitor/android
    声明了自己的 consumer rules,会保留每个使用
    @CapacitorPlugin
    标注的类及其
    @PluginMethod
    、
    @PermissionCallback
    和
    @ActivityCallback
    方法。AGP 的默认规则会保留
    @JavascriptInterface
    方法,这些大型 SDK 也各自提供了 consumer rules。

Step 4: Build a Signed Release APK

步骤 4:构建已签名的 Release APK

Debug builds never run R8, and a release build has to be signed to install. Sign the local release build with the Android debug keystore through the properties that Android Studio injects into Gradle. This does not change
build.gradle
:
bash
cd android
./gradlew assembleRelease \
  -Pandroid.injected.signing.store.file=$HOME/.android/debug.keystore \
  -Pandroid.injected.signing.store.password=android \
  -Pandroid.injected.signing.key.alias=androiddebugkey \
  -Pandroid.injected.signing.key.password=android
If
$HOME/.android/debug.keystore
does not exist, run any debug build once (
./gradlew assembleDebug
) to create it, then retry.
If the build fails with
Missing class
errors, R8 writes a ready-to-paste file to
android/app/build/outputs/mapping/release/missing_rules.txt
. Read each entry and decide per class:
CaseAction
The plugin compiles against the library as
compileOnly
and probes for it at runtime with
Class.forName
(optional backend)
Add the
-dontwarn
rule to
android/app/proguard-rules.pro
.
The plugin calls the class unconditionallyDo not add
-dontwarn
. Add the missing dependency to
android/app/build.gradle
instead, or the app throws
NoClassDefFoundError
at runtime.
Known optional backends:
diff
+# Optional SQLite backends that the Capawesome SQLite plugin probes for at runtime
+-dontwarn io.requery.android.database.**
+-dontwarn net.zetetic.database.**
The Capawesome SQLite plugin compiles against both SQLCipher (
net.zetetic.database.**
) and requery's
sqlite-android
(
io.requery.android.database.**
) and bundles only the one selected in
android/variables.gradle
, so both
-dontwarn
lines are correct for that plugin.
Rebuild after every rule change until
assembleRelease
succeeds.
Debug 构建从不运行 R8,而 release 构建必须签名后才能安装。通过 Android Studio 注入 Gradle 的 properties,使用 Android debug keystore 对本地 release 构建进行签名。这不会改动
build.gradle
:
bash
cd android
./gradlew assembleRelease \
  -Pandroid.injected.signing.store.file=$HOME/.android/debug.keystore \
  -Pandroid.injected.signing.store.password=android \
  -Pandroid.injected.signing.key.alias=androiddebugkey \
  -Pandroid.injected.signing.key.password=android
如果
$HOME/.android/debug.keystore
不存在,请先运行一次任意 debug 构建(
./gradlew assembleDebug
)以创建它,然后重试。
如果构建因
Missing class
错误而失败,R8 会将可直接粘贴的文件写入
android/app/build/outputs/mapping/release/missing_rules.txt
。读取每个条目,并按类进行判断:
情况操作
插件以
compileOnly
方式针对该库编译,并在运行时通过
Class.forName
探测它(可选后端)
将对应的
-dontwarn
规则添加到
android/app/proguard-rules.pro
。
插件无条件调用该类不要添加
-dontwarn
。应改为在
android/app/build.gradle
中添加缺失的依赖,否则应用会在运行时抛出
NoClassDefFoundError
。
已知可选后端:
diff
+# Optional SQLite backends that the Capawesome SQLite plugin probes for at runtime
+-dontwarn io.requery.android.database.**
+-dontwarn net.zetetic.database.**
Capawesome SQLite 插件同时针对 SQLCipher(
net.zetetic.database.**
)和 requery 的
sqlite-android
(
io.requery.android.database.**
)进行编译,但只会将
android/variables.gradle
中选定的一个打入包,因此该插件使用这两条
-dontwarn
规则都是正确的。
每次更改规则后都重新构建,直到
assembleRelease
成功。

Step 5: Verify on a Device

步骤 5:在设备上验证

  1. Confirm a device or emulator is connected with
    adb devices
    . If none is connected, hand the following checks to the user with the exact commands.
  2. Install the release APK:
    bash
    adb install -r app/build/outputs/apk/release/app-release.apk
  3. Clear logcat, launch the app, and watch for the failure signatures while it starts:
    bash
    adb logcat -c
    adb logcat | grep -E 'FATAL EXCEPTION|ClassNotFoundException|NoSuchMethodException|NullPointerException'
    The annotation crash from Step 3 appears within the first second. Afterwards, ask the user to run every flow that requests a permission or waits for another activity (camera, file picker, settings screen, sign-in) and watch logcat during each one.
  4. Open
    android/app/build/outputs/mapping/release/mapping.txt
    and confirm that the plugin classes recorded in Step 1 still appear under their original names. Search for the plugin's Android package, for example
    io.capawesome.capacitorjs.plugins
    . A renamed plugin class means a keep rule is missing. Tell the user to archive
    mapping.txt
    with every release, since production stack traces need it.
  1. 使用
    adb devices
    确认已连接设备或模拟器。如果没有连接设备,则将以下检查和准确命令交给用户执行。
  2. 安装 release APK:
    bash
    adb install -r app/build/outputs/apk/release/app-release.apk
  3. 清空 logcat,启动应用,并在启动期间观察失败特征:
    bash
    adb logcat -c
    adb logcat | grep -E 'FATAL EXCEPTION|ClassNotFoundException|NoSuchMethodException|NullPointerException'
    步骤 3 中提到的注解崩溃会在第一秒内出现。随后,请让用户运行每个需要请求权限或等待其他 activity 的流程,例如相机、文件选择器、设置界面和登录,并在每个流程运行期间监控 logcat。
  4. 打开
    android/app/build/outputs/mapping/release/mapping.txt
    ,确认步骤 1 中记录的插件类仍以原始名称出现。搜索插件的 Android package,例如
    io.capawesome.capacitorjs.plugins
    。插件类被重命名意味着缺少相应的 keep 规则。告知用户每次发布都必须归档
    mapping.txt
    ,因为生产环境中的 stack trace 需要使用它进行还原。

Step 6: Read the Play Numbers Before Uploading

步骤 6:上传前读取 Play 数值

Skip this step if the AGP version recorded in Step 1 is below 8.10: older versions do not write
r8.json
, and Play computes the numbers itself.
Build the app bundle with the same signing properties as Step 4 and read the R8 metadata from it:
bash
./gradlew bundleRelease \
  -Pandroid.injected.signing.store.file=$HOME/.android/debug.keystore \
  -Pandroid.injected.signing.store.password=android \
  -Pandroid.injected.signing.key.alias=androiddebugkey \
  -Pandroid.injected.signing.key.password=android
unzip -p app/build/outputs/bundle/release/app-release.aab BUNDLE-METADATA/com.android.tools/r8.json
The file reports the obfuscation, optimization and shrinking percentages that Play Console shows in the app bundle explorer for that upload. Each must be at least 25%. If a value is below 25%, search
android/app/proguard-rules.pro
for broad rules (
-keep class **
,
-dontobfuscate
,
-dontoptimize
,
-dontshrink
) and narrow them.
如果步骤 1 中记录的 AGP 版本低于 8.10,则跳过此步骤:旧版本不会写入
r8.json
,而是由 Play 自行计算这些数值。
使用与步骤 4 相同的签名 properties 构建 app bundle,并从中读取 R8 元数据:
bash
./gradlew bundleRelease \
  -Pandroid.injected.signing.store.file=$HOME/.android/debug.keystore \
  -Pandroid.injected.signing.store.password=android \
  -Pandroid.injected.signing.key.alias=androiddebugkey \
  -Pandroid.injected.signing.key.password=android
unzip -p app/build/outputs/bundle/release/app-release.aab BUNDLE-METADATA/com.android.tools/r8.json
该文件会报告 Play Console 的 app bundle explorer 针对本次上传所显示的混淆、优化和收缩百分比。每个百分比都必须至少达到 25%。如果某个值低于 25%,请在
android/app/proguard-rules.pro
中搜索宽泛规则(
-keep class **
、
-dontobfuscate
、
-dontoptimize
、
-dontshrink
),并将其收窄。

Step 7: Report

步骤 7:报告

Summarize for the user:
  1. The changes to
    android/app/build.gradle
    and
    android/app/proguard-rules.pro
    .
  2. Any
    -dontwarn
    rule added and why it is safe, and any missing dependency that was added instead.
  3. The three percentages from
    r8.json
    (if Step 6 ran).
  4. That
    mapping.txt
    must be archived per release. An Android App Bundle embeds it in
    BUNDLE-METADATA/
    , so Play deobfuscates crash and ANR reports on its own. Only APK uploads need a manual upload in Play Console. The Firebase Crashlytics Gradle plugin uploads it automatically.
  5. That the release build is now a standing test target: rerun Step 5 before every upload and check
    missing_rules.txt
    again whenever a plugin is added.
向用户总结以下内容:
  1. 对
    android/app/build.gradle
    和
    android/app/proguard-rules.pro
    所做的更改。
  2. 添加了哪些
    -dontwarn
    规则、这些规则为何安全,以及是否改为添加了缺失的依赖。
  3. r8.json
    中的三个百分比(如果执行了步骤 6)。
  4. 每次发布都必须归档
    mapping.txt
    。Android App Bundle 会将其嵌入
    BUNDLE-METADATA/
    ,因此 Play 会自动反混淆 crash 和 ANR 报告。只有上传 APK 时才需要在 Play Console 中手动上传。Firebase Crashlytics Gradle plugin 会自动上传该文件。
  5. Release 构建现在应作为固定测试目标:每次上传前都重新执行步骤 5,并在添加插件后再次检查
    missing_rules.txt
    。

Error Handling

错误处理

  • App crashes on startup with
    NullPointerException
    at
    com.getcapacitor.Plugin.getPermissionStates
    : The app is on Capacitor below 8.6.0 and the
    -keep @interface com.getcapacitor.** { *; }
    rule is missing from
    android/app/proguard-rules.pro
    . Add it (Step 3) and rebuild, or upgrade to Capacitor 8.6.0, which ships the rule (ionic-team/capacitor#8646).
  • Build fails with
    Missing class <name>
    : Follow the
    missing_rules.txt
    decision table in Step 4.
  • Build fails because
    proguard-android.txt
    is not supported (AGP 9)
    : Replace it with
    proguard-android-optimize.txt
    as in Step 2.
  • A plugin method is not found at runtime (
    NoSuchMethodException
    ) or a plugin class is renamed in
    mapping.txt
    : Add the plugin's documented keep rule from its README (Step 3, item 2). If the README has none, add
    -keep class <plugin Android package>.** { *; }
    for that plugin only and report it to the user as a candidate for an upstream fix.
  • adb install
    fails with
    INSTALL_PARSE_FAILED_NO_CERTIFICATES
    : The release APK is unsigned. Rerun
    assembleRelease
    with the four
    -Pandroid.injected.signing.*
    properties from Step 4.
  • Permission checks return an empty result on Capacitor 8.5.2 or 8.5.3 without crashing: Capacitor 8.5.2 added a null check in
    getPermissionStates()
    that hides the crash but returns an empty permission map, and
    requestPermissions()
    still throws. The keep rule from Step 3 is still required on those versions.
  • Resources missing at runtime after enabling
    shrinkResources
    : Resources referenced by name from JavaScript or
    capacitor.config.ts
    are invisible to the resource shrinker. List them in
    android/app/src/main/res/raw/keep.xml
    with
    tools:keep
    , or remove
    shrinkResources true
    .
  • 应用启动时在
    com.getcapacitor.Plugin.getPermissionStates
    处发生
    NullPointerException
    崩溃
    :应用使用的 Capacitor 版本低于 8.6.0,并且
    android/app/proguard-rules.pro
    中缺少
    -keep @interface com.getcapacitor.** { *; }
    规则。添加该规则(步骤 3)并重新构建,或者升级到自带该规则的 Capacitor 8.6.0(ionic-team/capacitor#8646)。
  • 构建因
    Missing class <name>
    而失败
    :按照步骤 4 中
    missing_rules.txt
    的判断表处理。
  • 构建因不支持
    proguard-android.txt
    而失败(AGP 9)
    :按照步骤 2 的说明,将其替换为
    proguard-android-optimize.txt
    。
  • 运行时找不到插件方法(
    NoSuchMethodException
    ),或插件类在
    mapping.txt
    中被重命名
    :从插件 README 中添加其明确记录的 keep 规则(步骤 3,第 2 项)。如果 README 中没有相应规则,则仅为该插件添加
    -keep class <plugin Android package>.** { *; }
    ,并向用户说明这是一个可提交给上游修复的候选方案。
  • adb install
    因
    INSTALL_PARSE_FAILED_NO_CERTIFICATES
    而失败
    :Release APK 未签名。使用步骤 4 中的四个
    -Pandroid.injected.signing.*
    properties 重新运行
    assembleRelease
    。
  • 在 Capacitor 8.5.2 或 8.5.3 上权限检查返回空结果,但没有发生崩溃:Capacitor 8.5.2 在
    getPermissionStates()
    中添加了 null 检查,隐藏了崩溃但会返回空的权限 map,而
    requestPermissions()
    仍会抛出异常。这些版本仍然需要步骤 3 中的 keep 规则。
  • 启用
    shrinkResources
    后,运行时出现资源缺失
    :由 JavaScript 或
    capacitor.config.ts
    按名称引用的资源对资源收缩器不可见。使用
    tools:keep
    将这些资源列在
    android/app/src/main/res/raw/keep.xml
    中,或者移除
    shrinkResources true
    。

Limitations

限制

  • The skill verifies a local release build signed with the debug keystore. The Play Console numbers are only final for the bundle that is uploaded.
  • Setting
    android.enableR8.fullMode=false
    in
    android/gradle.properties
    also avoids the startup crash, but it lowers the optimization across the whole app and all its dependencies. The keep rule is the cheaper fix.
  • Capacitor 8.6.0 ships the annotation keep rule and a rule for
    @ActivityCallback
    and
    @PermissionCallback
    methods on non-public base classes in its consumer rules. On 8.6.0 or newer, an existing
    -keep @interface com.getcapacitor.** { *; }
    line in the app is redundant but harmless. Leave it in place.
  • 该 skill 验证的是使用 debug keystore 签名的本地 release 构建。只有实际上传的 bundle 所对应的 Play Console 数值才是最终结果。
  • 在
    android/gradle.properties
    中设置
    android.enableR8.fullMode=false
    也能避免启动崩溃,但会降低整个应用及其所有依赖的优化程度。keep 规则是成本更低的修复方案。
  • Capacitor 8.6.0 会在 consumer rules 中提供注解 keep 规则,以及针对非 public 基类上
    @ActivityCallback
    和
    @PermissionCallback
    方法的规则。在 8.6.0 或更高版本上,应用中已有的
    -keep @interface com.getcapacitor.** { *; }
    规则虽然多余,但无害。应将其保留。

Related Skills

相关 Skills

  • capacitor-app-development
    — General Android troubleshooting and app configuration.
  • capacitor-plugins
    — Per-plugin reference files, including the ProGuard rules a plugin documents.
  • capacitor-app-upgrades
    — Upgrade Capacitor and AGP to a version this skill supports.
  • capawesome-cloud
    — Capawesome Cloud runs the Gradle build as is, so a project with
    minifyEnabled true
    produces the minified app bundle with the mapping file embedded.
  • capacitor-app-development
    — 常规 Android 故障排查和应用配置。
  • capacitor-plugins
    — 按插件划分的参考文件,包括插件文档中记录的 ProGuard 规则。
  • capacitor-app-upgrades
    — 将 Capacitor 和 AGP 升级到此 skill 支持的版本。
  • capawesome-cloud
    — Capawesome Cloud 会按原样运行 Gradle 构建,因此启用了
    minifyEnabled true
    的项目会生成压缩后的 app bundle,并在其中嵌入 mapping 文件。