9

I am building an app bundle (.aab) for our react native app.

When I build via Android Studio, app builds, deploys to Play Store. I download and run - everything works.

When I build via FastLane, app builds, deploys to Play Store. But I download and run, I get the following error:

E AndroidRuntime: java.lang.RuntimeException: Unable to load script. Make sure you're either running a Metro server (run 'react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release.
E AndroidRuntime:   at com.facebook.react.bridge.CatalystInstanceImpl.jniLoadScriptFromAssets(Native Method)
E AndroidRuntime:   at com.facebook.react.bridge.CatalystInstanceImpl.loadScriptFromAssets(CatalystInstanceImpl.java:2)
E AndroidRuntime:   at com.facebook.react.bridge.JSBundleLoader$1.loadScript(JSBundleLoader.java:1)
E AndroidRuntime:   at com.facebook.react.bridge.CatalystInstanceImpl.runJSBundle(CatalystInstanceImpl.java:3)
W ActivityTaskManager:   Force finishing activity com.friday.pax.dev/com.friday.pax.MainActivity
RN: 0.63.4
Gradle: 4.1.1

FastLane Logs:

https://gist.githubusercontent.com/HardlyMirage/4426e411b6ec1e8abac5e7a620d979ae/raw/37daead0b55ee77b7ef7d6ddd8631d311dbc80aa/txt

index.android.bundle appears to be correctly generated.

> Task :app:bundleDevReleaseJsAndAssets
warning: the transform cache was reset.
Welcome to React Native!
Learn once, write anywhere
info Writing bundle output to:, /home/runner/work/fridayapp-pax/fridayapp-pax/android/app/build/generated/assets/react/dev/release/index.android.bundle
info Writing sourcemap output to:, /home/runner/work/fridayapp-pax/fridayapp-pax/android/app/build/generated/sourcemaps/react/dev/release/index.android.bundle.map
info Done writing bundle output
info Done writing sourcemap output
info Copying 88 asset files
info Done copying assets

Task :app:mergeDevReleaseResources is run after Task :app:copyDevReleaseBundledJs

FastFile:


def getVersionCode
  # Instead of managing the version code manually it is simply based on a timestamp in sec
  # Any build done more recently is considered to be a higher version
  # versionCode increase every minute (aka max 1 build per minute)
  # versionCode can't be smaller than legacyVersionCode
  thirtySeptemberTwentyTwenty = 1601480940 / 60
  legacyVersionCode = 10902
  versionCode = legacyVersionCode + (Time.now.to_i / 60) - thirtySeptemberTwentyTwenty

  if versionCode > 2100000000
    raise "versionCode cannot be higher than 2100000000"
  end

  versionCode.floor()
end

platform :android do

  desc "Friday (Dev)"
  lane :playstoreDevInternal do |options|
    
    # Retrieve version of my app in package.json (React Native case)
    package = load_json(json_path: "../package.json")

    # Clean build folder
    gradle(
      task: "clean"
    )

    # Bump android.defaultConfig.versionCode
    # bump_build_number
    android_set_version_code(
      version_code: package["versionName"]
    )

    # Do the bundle of the application  
    gradle(
      # task: "assemble",
      task: 'bundle',
      flavor: "dev",
      build_type: "Release",
      properties: {
        "android.injected.signing.store.file" => Dir.pwd + "/release.keystore",
        "android.injected.signing.store.password" => options[:RELEASE_KEYSTORE_PASSWORD], # keystore password
        "android.injected.signing.key.alias" => options[:RELEASE_KEYSTORE_ALIAS], # alias
        "android.injected.signing.key.password" => options[:RELEASE_KEYSTORE_KEY_PASSWORD], # key password
        "vname" => package["version"]
      }
    )

    # Upload Android App Bundle to PlayStore like Internal testing Release
    upload_to_play_store(
      package_name: 'com.friday.pax.dev',
      track: 'internal',
      release_status: 'draft',
      skip_upload_apk: true,
      version_name: package["version"]
    )
  end
end

Can anyone point out why the aab bundle from Android Studio works, but not the one generated via FastLane? Even though index.android.bundle is clearly generated.

My only thought is that perhaps the index.android.bundle path is incorrect. But I don't see a way of modifying that path.

HyderA
  • 20,651
  • 42
  • 112
  • 180
  • You can try to follow these steps in your lane: https://stackoverflow.com/questions/55441230/unable-to-load-script-make-sure-you-are-either-running-a-metro-server-or-that-yo – Akif Sep 06 '21 at 13:32
  • @Akif that question pertains to development build, mine is release. – HyderA Sep 08 '21 at 20:50
  • duplicate of https://stackoverflow.com/questions/59051365/index-android-bundle-not-updating-when-creating-release-build/74854019#74854019 – Moritz Dec 21 '22 at 06:56

2 Answers2

4

Turns out that the gradle scripts were generating the bundle into a build variant-specific folder, but the app was looking for the bundle in the default location, regardless of the build variant:

Gradle script generated bundle location (Flavor: dev, Type: release):

android/app/build/generated/assets/react/dev/release/index.android.bundle

App looking at location:

android/app/src/main/assets/index.android.bundle

So I added a script to package.json to generate this:

"generate:bundle": "react-native bundle --platform android --dev false --bundle-output android/app/src/main/assets/index.android.bundle --entry-file index.js"

And prior to running the build command in my runner script, I run the script to generate the build:

npm run generate:build

The app now finds the bundle.

HyderA
  • 20,651
  • 42
  • 112
  • 180
1

Sorry, my english is poor..

When compiling aab, the RN compilation script(react.gradle) contains a task named by bundleJsAndAssets and it's asynchronous. When the tasks of copyBundledJs and mergeResources has been executed, bundleJsAndAssets is still executing. so the JS bundle was missed in the aab

Solution:

1.If your assets directory has a bundle file, remove it.

2.add this code in your app/build.gradle

project.afterEvaluate {
def isAndroidLibrary = plugins.hasPlugin("com.android.library")
def variants = isAndroidLibrary ? android.libraryVariants : android.applicationVariants
variants.all { def variant ->
    def targetName = variant.name.capitalize()
    def mergeResourcesTask = tasks.findByName("merge${targetName}Resources")
    def assetsCopyTask = tasks.findByName("copy${targetName}BundledJs")
    def bundleAndroidTask = tasks.findByName("bundle${targetName}JsAndAssets")
    mergeResourcesTask.dependsOn(assetsCopyTask)
    assetsCopyTask.dependsOn(bundleAndroidTask)
    logger.warn("Making task ${mergeResourcesTask} depend on ${assetsCopyTask}")
    logger.warn("Making task ${assetsCopyTask} depend on ${bundleAndroidTask}")
}}
  • Finally, after searching for almost three days, this is what saved us. Thanks a lot for the detailed explanation. Added this to inside android block in app/build.gradle and now aab release bundle is working fine. – Hisham Mubarak Jul 22 '22 at 10:59