【问题标题】:How to use offline bundle on android for react native project?如何在 android 上使用离线包来反应原生项目?
【发布时间】:2015-12-09 09:41:54
【问题描述】:

如何在安卓上使用离线包?
我没有看到关于在 android 上使用离线包的文档。
我试图取消注释 build.gradle 中的代码。

project.ext.react = [
        // the name of the generated asset file containing your JS bundle
    bundleAssetName: "index.android.bundle",

    // the entry file for bundle generation
    entryFile: "index.android.js",

    // whether to bundle JS and assets in debug mode
    bundleInDebug: false,

    // whether to bundle JS and assets in release mode
    bundleInRelease: true,

    // the root of your project, i.e. where "package.json" lives
    root: "../../",

    // where to put the JS bundle asset in debug mode
    jsBundleDirDebug: "$buildDir/intermediates/assets/debug",

    // where to put the JS bundle asset in release mode
    jsBundleDirRelease: "$buildDir/intermediates/assets/release",

    // where to put drawable resources / React Native assets, e.g. the ones you use via
    // require('./image.png')), in debug mode
    resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",

    // where to put drawable resources / React Native assets, e.g. the ones you use via
    // require('./image.png')), in release mode
    resourcesDirRelease: "$buildDir/intermediates/res/merged/release",

    // by default the gradle tasks are skipped if none of the JS files or assets change; this means
    // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
    // date; if you have any other folders that you want to ignore for performance reasons (gradle
    // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
    // for example, you might want to remove it from here.
    inputExcludes: ["android/**", "ios/**"]
]

但它没有工作。它仍然从服务器获取 JS 包。
有什么我错过的吗?

【问题讨论】:

  • 您找到解决方案了吗?我正在寻找类似的东西

标签: android react-native


【解决方案1】:

JS离线打包到android,首先在相应的项目路径下启动服务器:

  1. 服务器启动时,打开与项目路径相同的下一个终端
  2. 复制并粘贴此命令: 在命令 propmt 中复制和粘贴命令之前,请在项目的相应路径中创建资产文件夹
    如:
    android/app/src/main/assets

    将此命令粘贴到命令提示符并运行:

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
  1. 然后在 assets 文件夹中会出现 index.android.bundle 文件
  2. 最后,运行命令:react-native run-android(新建离线apk时不需要启动服务器,离线js文件会帮你构建apk文件。)
  3. 最后,apk 现在构建已准备好在不同设备上运行(从 app/src/build/debug.apk 运行 apk)。
  4. 有时新制作的apk会运行不显示图片,如果应用程序运行时不显示图片,则将特定的图片资源文件夹复制并粘贴到android/app/src/main/assets/(图片源文件夹)中
  5. 再次重新运行应用程序,这样构建的 apk 就可以运行了。

【讨论】:

  • 这实际上破坏了我的项目,完全按照描述的步骤进行操作。
  • 不再需要proandroiddev.com/…
  • 要创建签名的 apk,您需要从可绘制文件夹中删除图像,因为该命令将自动创建资产。如果您不删除资产(drawables),您将在创建签名 apk 时收到重复资产错误。
  • 对于 react-native 版本 0.57 及更高版本,捆绑输出路径应为:android/app/build/generated/assets/react/debug/index.android.js 有关详细信息,请参阅react-native cli documentation
【解决方案2】:

你可以阅读react.gradle的源码,你就会知道如何做离线捆绑了。

react.gradle中,它为每个构建变体创建离线bundle gradle任务,并使其在gradle进程资源之前执行,但它在某些特殊情况下启用了bundle任务,代码为:

enabled config."bundleIn${targetName}" ||
        config."bundleIn${buildTypeName.capitalize()}" ?:
        targetName.toLowerCase().contains("release")

config 对象实际上是 react 对象,因为它的定义是 def config = project.hasProperty("react") ? project.react : [];

targetName 的定义是def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}"

所以如果我们在app\build.gradle 中定义一个合适的react 属性,我们就可以启用离线捆绑任务。

例如,如果我们想在release 构建类型中启用离线包,但在debug 构建类型中不启用,我们可以将react 定义为:

ext.react = [
    bundleInDebug     : false,
    bundleInRelease   : true
]

然后在命令行执行gradle assembleRelease,gradle会执行bundle任务,js bundle会包含在最终的apk中。

现在在您的问题中,您已经定义了正确的 react 对象,但您没有提及您运行的构建类型。只有执行gradle assembleRelease才能做捆绑工作,也许你执行了gradle assembleDebug所以没有任何意义。

还有一个问题我要说(另见issue7258)。如果您启用了发布构建类型的捆绑任务并从 android studio 运行应用程序,gradle 不要执行 bundleReleaseJsAndAssets,因为 android studio 启用了功能 Configure on demand(它在文件 | 设置 | 构建、执行、部署 | 编译器)默认情况下是为了加快构建速度,在 react.gradle 中,当所有项目都配置(或称为评估)时,捆绑任务会添加到项目中,因为主要代码在 gradle.projectsEvaluated{} 块中。

按需配置模式尝试仅配置符合以下条件的项目 与请求的任务相关,即它只执行 参与构建的项目的 build.gradle 文件。

由于一些不清楚的原因,在启用Configure on demand 功能时,gradle.projectsEvaluated{} 块中定义的任何任务都不会执行。要使其可执行,请在 android studio 设置中禁用Configure on demand 功能,或将gradle.projectsEvaluated{} 更改为afterEvaluate{}

如果您在命令行工具中运行gradle assembleRelease,一切正常,因为Configure on demand 默认是禁用的。

【讨论】:

  • 感谢 Android Studio 中有关 Configure on demand 的提示。那是为我做的
  • 如果我禁用“按需配置”,我会在构建应用程序时得到Execution failed for task ':app:recordFilesBeforeBundleCommandDebug'. > A problem occurred starting process 'command 'node''。其他人得到这个吗?
  • @AvatarQing 你能根据最近更新的 API 的风味维度变化来更新这个吗?生成正确的 bundleIn 字符串?捆绑进去??? = 真
【解决方案3】:

您不必取消注释 gradle.build 文件中的任何内容。它可供参考,如果需要,您可以覆盖其中的任何默认值。

问题在于 Android Studio 没有运行负责生成包的任务。

要在 Android Studio 中解决此问题,请转到 Preferences > Build, Execution, Deployment > Build Tools > Compiler 并取消选中 "Configure on demand"

现在,您标记为需要捆绑包的任何变体都将自动生成捆绑包。

默认情况下,调试变体不会生成包:bundleInDebug : false

你可以这样改变。这里我还提供了如何更改入口点的默认位置和包的默认名称的示例。

project.ext.react = [
    bundleAssetName: "index.myapp.bundle",
    entryFile: "js/index.myapp.js",
    bundleInDebug: true
]

一旦您进行了这些调整,您可能仍然会遇到构建问题,因为 Studio 无法识别您的 shell 配置文件中的路径,因此我可能找不到节点的路径。

I posted a solution to that issue here

这是一个稳定而强大的解决方案。在环境中进行这些更改后,您无需手动执行任何操作。当您按下 IDE 中的按钮时,Bundle 将自动构建,前提是您选择了正确的构建变体(这也在 IDE 中位于 Studio 窗口底部的 LHS 栏上)。

【讨论】:

    【解决方案4】:

    当通过没有 index.android.js 和 index.ios.js 的 create-react-native-app 从 react native 项目构建一个未签名的 apk 时,首先你必须检查那个 index.js 文件在你的项目中有没有。如果它不可用,则创建一个新文件 index.js 并在那里编写此代码

    import { AppRegistry } from "react-native";
    import App from "./App";
    AppRegistry.registerComponent("VOS", () => App);
    

    在此之后弹出项目,然后运行此命令

      react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
    

    然后是react-native run-android,它会为你构建一个apk。

    【讨论】:

      【解决方案5】:

      用于带有签名 APK 的版本。

      我尝试使用未签名的 APK 文件并安装它,但是当我将它安装到我的 Android 平板电脑上时,它给了我一个错误 Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

      我想这是因为 APK 文件未签名,平板电脑对此不满意。因此,在生成 React Native 包文件后,我能够像往常一样通过 Android Studio 生成签名的 APK 文件。

      顺便说一句,我们的应用程序是一个功能齐全的 Android 应用程序,已经存在于 Play 商店中,我们只是将 React Native 小部分添加到其中,因为它很棒。 p>

      总结一下,我的步骤如下:

      1) 生成 React Native 包:

      react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/<your-package-name>/src/main/assets/index.android.bu‌​ndle --assets-dest android/<your-package-name>/src/main/res/ 
      

      2) 从 Android Studio 生成签名的 APK 文件。

      3) 将签名的 APK 文件安装到 USB 设备:

      adb -d install -r <path_to_signed_apk> 
      

      4) 利润!

      【讨论】:

        【解决方案6】:

        您可以在 ReactApplication 类中覆盖 getJSBundleFile() 函数以返回自定义文件路径。

        @Nullable
            @Override
            protected String getJSBundleFile() {
                return "/your/bundle/path/bundle.file.name.bundle";
            }
        

        之后,只需使用react-native bundle 生成包,然后将生成包放在设备中的指定路径中。

        【讨论】:

        • 路径从哪里开始?是 ReactApplication 类所在的位置吗?
        • 对我来说,我使用了绝对路径。到目前为止,它对我来说效果很好。
        • @LongVu 你如何重新加载 js 包?我从远程服务器安装包。如何以编程方式触发重新加载?
        【解决方案7】:

        我们需要在 android->app->src->main 目录中创建 assets 目录。并运行以下命令

        npx  react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
        

        对于 Windows 平台,运行以下命令

        npx  react-native bundle --platform android --dev false --entry-file index.js --bundle-output android\app\src\main\assets\index.android.bundle --assets-dest android\app\src\main\res\
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-28
          • 2019-11-19
          相关资源
          最近更新 更多