返回

Expo EAS/本地构建失败:Stripe库问题及解决方案

Android

解决Expo管理项目EAS和本地构建失败的问题

在Expo管理项目中,当使用EAS(Expo Application Services)或者本地构建Android应用时,有时会遇到构建失败的情况。 尤其当涉及到第三方库如@stripe/stripe-react-native 时,问题可能更加棘手。 本文旨在分析此类问题的原因并提供可行的解决方案。

问题分析

构建失败的根本原因往往是R8混淆器在构建Release版本时无法找到 Stripe 库所需的特定类。这些类对于推送配置等特定功能是必要的。 通常,这些类会被 R8 视为未使用的代码而移除,导致运行时错误,即便在开发或物理设备上运行良好。

具体的报错信息中会指出缺少哪些类, 例如:

[RUN_GRADLEW] ERROR: Missing class com.stripe.android.pushProvisioning.PushProvisioningActivity$g 
[RUN_GRADLEW] Missing class com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Args
[RUN_GRADLEW] Missing class com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error
...

这意味着 R8 在构建过程中,认为这些 Stripe SDK 中用于推送配置相关的类没有被使用到,因此做了优化将其移除。 但是事实上它们又是必需的,最终导致构建失败。

解决方案

有几种方法可以解决这个问题,关键是告诉 R8 保留这些必要的类,避免被移除。

方案一:添加ProGuard 规则

ProGuard 文件定义了混淆器应保留的类、方法和字段。 我们可以在 android/app/proguard-rules.pro 文件中添加规则,显式告知 R8 需要保留 Stripe 相关的类。

  1. 创建或修改 proguard-rules.pro : 如果项目根目录下没有 android/app/proguard-rules.pro 文件, 则创建该文件; 如果已存在则打开修改它。
  2. 添加以下规则 :将下面这些配置项粘贴到 proguard-rules.pro 文件中:
-keep class com.stripe.android.pushProvisioning.** { *; }
-keep class com.stripe.android.googlepay.pushProvisioning.** { *; }
-keep class com.stripe.android.pushProvisioning.PushProvisioningActivity$g
-keep class com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Args
-keep class com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error
-keep class com.stripe.android.pushProvisioning.PushProvisioningActivityStarter
-keep class com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider

这些规则告诉 R8 不要对 com.stripe.android.pushProvisioningcom.stripe.android.googlepay.pushProvisioning 包下的所有类做混淆和优化处理。另外我们还指定了一些明确缺失的类,强制混淆器进行保留。

  1. 重新构建 : 执行以下命令重新构建Android 应用:

    npx eas build -p android --profile preview --local
    

此方案较为直接,可以有效解决因R8优化引起的类丢失问题,通常用于应对推送配置或者 Google Pay 配置缺失类导致的问题。

方案二:检查和更新依赖库版本

库版本不兼容也可能导致构建问题,确保使用的 @stripe/stripe-react-native 和其他相关库版本是兼容的,并及时进行更新。

  1. 更新依赖项 : 检查你的 package.json 文件中的 @stripe/stripe-react-native 版本,并将其更新为最新版本(可以通过 npm outdatedyarn outdated 查看可升级的版本)。 运行如下命令来升级你的 package.json:

    npm install @stripe/stripe-react-native@latest
    
  2. 重新安装依赖项 : 执行以下命令删除并重新安装依赖,防止缓存引起的问题:

      rm -rf node_modules && npm install
    
  3. 删除构建缓存 : 执行命令清除缓存文件,保证不会使用到之前的错误缓存:

    npm run android:no-cache
    
  4. 重新构建 : 执行以下命令重新构建Android 应用:

      npx eas build -p android --profile preview --local
    

库的版本不兼容问题较为常见,及时升级和排查可以解决由于版本差异而带来的冲突问题。

方案三: 使用自定义 gradle 配置

如果通过添加 proguard 规则,并且升级 stripe-react-native 库版本后依然出现构建失败问题,则可以考虑直接在 build.gradle 文件中加入一些 R8 配置选项来跳过混淆过程,这种方式不推荐使用。

  1. 修改 build.gradle: 在项目目录 android/app/build.gradle 中找到 android { ... } 部分, 然后添加 packagingOptions 代码块和 R8 相关配置。 例如:
android {
   ...

  packagingOptions {
     resources.excludes.add("META-INF/kotlin-*.kotlin_module")
     resources.excludes.add("META-INF/LICENSE.md")
  }
  buildTypes {
      release {
        // add this
       minifyEnabled false // Or use "shrinkResources false" for disable the resource shrink
          proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      }

   }
  ...
}

这里需要将 minifyEnabled 设置为 false 或者使用 shrinkResources false 跳过对资源的优化。

  1. 同步 Gradle : 确保执行了 gradle 同步命令让修改生效
 npx expo run:android
  1. 重新构建 : 尝试重新构建项目:

    npx eas build -p android --profile preview --local
    

这是一个比较激进的解决方案。禁用 R8 可以解决类丢失的问题,但这通常会导致生成更大的 APK 文件。 建议只作为最后手段尝试,并尽快找到其他合适的方案。

安全建议

  • 及时更新依赖 : 定期更新你的依赖库,以修复已知问题并引入新功能。
  • 版本控制 : 使用版本控制工具跟踪对 proguard-rules.probuild.gradle 的修改。
  • 最小权限原则 : 只在必要时添加 ProGuard 规则。
  • 谨慎使用 R8 设置 : 理解禁用 R8 的影响,并在可行时找到更好的方案。

解决构建问题往往需要细致地排查和反复尝试。通过以上分析和步骤,应该能够找到解决“EAS和本地构建失败”问题的方法,确保项目的正常构建。