API参考
-
+
-
-
@@ -99,7 +99,7 @@
{expired: true}
:该应用原生包已过期(已从 pushy 服务器中删除),需要前往应用市场下载新的版本(在设置中填写 downloadUrl)。
+{expired: true}
:该应用原生包版本被设置为过期(或已从 pushy 服务器中删除,或从未上传),需要前往应用市场下载新的版本(在设置中填写 downloadUrl)。-
-
diff --git a/docs/changelog.html b/docs/changelog.html
index 1d4e687..2c05070 100644
--- a/docs/changelog.html
+++ b/docs/changelog.html
@@ -48,7 +48,7 @@
}
}
})
-
- 9.0.0(2023-09-02)
- 8.0.1(2022-07-05)
- 7.4.1(2022-05-04) diff --git a/docs/cli.html b/docs/cli.html index 42baad1..7c8ff93 100644 --- a/docs/cli.html +++ b/docs/cli.html @@ -48,7 +48,7 @@ } } }) -
- 安装
-
diff --git a/docs/faq.html b/docs/faq.html
index 71aeee2..0c5188d 100644
--- a/docs/faq.html
+++ b/docs/faq.html
@@ -48,7 +48,7 @@
}
}
})
-
常见问题
最近修改时间2023-09-19 03:16:41-
+
-
-
diff --git a/docs/getting-started.html b/docs/getting-started.html
index d2c266d..c3ab306 100644
--- a/docs/getting-started.html
+++ b/docs/getting-started.html
@@ -48,7 +48,7 @@
}
}
})
-
- 安装
-
diff --git a/docs/integration.html b/docs/integration.html
index 6c1d52b..381e595 100644
--- a/docs/integration.html
+++ b/docs/integration.html
@@ -48,7 +48,7 @@
}
}
})
-
代码集成
最近修改时间2023-09-19 03:16:41-
+
- 极简快速集成
-
diff --git a/docs/publish.html b/docs/publish.html
index 27a4f36..db5affa 100644
--- a/docs/publish.html
+++ b/docs/publish.html
@@ -48,7 +48,7 @@
}
}
})
-
发布热更新
最近修改时间2023-09-19 03:16:41-
+
-
-
diff --git a/page-data/docs/api.html/page-data.json b/page-data/docs/api.html/page-data.json
index 66c18dc..536dfb0 100644
--- a/page-data/docs/api.html/page-data.json
+++ b/page-data/docs/api.html/page-data.json
@@ -1 +1 @@
-{"componentChunkName":"component---src-templates-docs-tsx","path":"/docs/api.html","result":{"data":{"markdownRemark":{"html":"
{expired: true}
:该应用原生包已过期(已从 pushy 服务器中删除),需要前往应用市场下载新的版本(在设置中填写 downloadUrl)。 \n{upToDate: true}
:当前已经更新到最新,无需进行更新。 \n{update: true}
:当前有新版本可以更新。info 的name
、description
字段可以用于提示用户,而metaInfo
字段则可以根据你的需求自定义一些标记(如是否静默更新、是否强制更新等等,自己根据标记的属性做一些条件流程控制),具体用法可参考场景实践。另外还有几个字段,包含了热更新文件的下载地址, \n- \n\n\n \n
- \n\n\n \n
- \n\n\n \n
- iOS 方法 \n
{expired: true}
:该应用原生包版本被设置为过期(或已从 pushy 服务器中删除,或从未上传),需要前往应用市场下载新的版本(在设置中填写 downloadUrl)。 \n{upToDate: true}
:当前已经更新到最新,无需进行更新。 \n{update: true}
:当前有新版本可以更新。info 的name
、description
字段可以用于提示用户,而metaInfo
字段则可以根据你的需求自定义一些标记(如是否静默更新、是否强制更新等等,自己根据标记的属性做一些条件流程控制),具体用法可参考场景实践。另外还有几个字段,包含了热更新文件的下载地址, \n- \n\n\n \n
- \n\n\n \n
- \n\n\n \n
- iOS 方法 \n
- 启用 proguard 压缩混淆源码。但这一步可能导致一些使用反射的代码运行时报错,启用后需要充分测试每个页面和功能,以及需要阅读一些第三方关于 proguard 的特别设置说明。 \n
- 分开编译不同的 cpu 架构。找到
android/app/build.gradle
中的 cpu 架构部分,如下所示启用enable
选项: \n - js 包成分分析。可以借助一些第三方工具(如react-native-bundle-visualizer)来分析 js 文件中哪些占比较大,是否可以用其他库替换等(如 dayjs 替换 moment,lodash-es 替换 lodash)。 \n
- \n
图片优化。
\n- \n
- 在保证体验的情况下,使用一些工具对图片进行裁剪压缩。 \n
- 如不需要图片的透明像素,可以考虑将 png 格式转为 jpg 格式。 \n
- 还可以进一步考虑压缩比更高的图片格式,例如 webp 格式(需要第三方原生插件例如react-native-webp-format),heif 格式(iOS 11 和 Android 10 以上原生支持)等。这里有个图片格式对比可供参考 https://compare.rokka.io/_compare/#heif=40&jpeg=80&webp=80&av1=40&width=800。 \n
\n - 如果渠道包的
js代码和初始资源
有差别(无论多么细微的差别都会生成不同的 jsbundle),那么只能单独生成 apk,分别上传和绑定。可以考虑写一些脚本自动调用 cli 来执行批量操作。 \n - 如果渠道包的
js代码和初始资源
完全一致,可以考虑使用Flavor 构建,或其他一些动态生成渠道包的方案(比如腾讯的 VasDolly,美团的 walle等),这样所有的渠道包基于同一个基础 apk 生成(因而会有相同的编译时间戳和 jsbundle)。这样可以只用上传一个基础 apk,对此 apk 的热更操作可以对所有渠道包生效。 \n - \n\n\n \n
- 有很多渠道包需要热更,如何操作比较方便? \n
- 如何支持 aab 格式的原生包? \n
- CI 的集成 \n
- 测试、发布与回滚 \n
- 元信息(Meta Info)的使用 \n
- 启用 proguard 压缩混淆源码。但这一步可能导致一些使用反射的代码运行时报错,启用后需要充分测试每个页面和功能,以及需要阅读一些第三方关于 proguard 的特别设置说明。 \n
- 分开编译不同的 cpu 架构。找到
android/app/build.gradle
中的 cpu 架构部分,如下所示启用enable
选项: \n - js 包成分分析。可以借助一些第三方工具(如react-native-bundle-visualizer)来分析 js 文件中哪些占比较大,是否可以用其他库替换等(如 dayjs 替换 moment,lodash-es 替换 lodash)。 \n
- \n
图片优化。
\n- \n
- 在保证体验的情况下,使用一些工具对图片进行裁剪压缩。 \n
- 如不需要图片的透明像素,可以考虑将 png 格式转为 jpg 格式。 \n
- 还可以进一步考虑压缩比更高的图片格式,例如 webp 格式(需要第三方原生插件例如react-native-webp-format),heif 格式(iOS 11 和 Android 10 以上原生支持)等。这里有个图片格式对比可供参考 https://compare.rokka.io/_compare/#heif=40&jpeg=80&webp=80&av1=40&width=800。 \n
\n - 如果渠道包的
js代码和初始资源
有差别(无论多么细微的差别都会生成不同的 jsbundle),那么只能单独生成 apk,分别上传和绑定。可以考虑写一些脚本自动调用 cli 来执行批量操作。 \n - 如果渠道包的
js代码和初始资源
完全一致,可以考虑使用Flavor 构建,或其他一些动态生成渠道包的方案(比如腾讯的 VasDolly,美团的 walle等),这样所有的渠道包基于同一个基础 apk 生成(因而会有相同的编译时间戳和 jsbundle)。这样可以只用上传一个基础 apk,对此 apk 的热更操作可以对所有渠道包生效。 \n - \n\n\n \n
- 有很多渠道包需要热更,如何操作比较方便? \n
- 如何支持 aab 格式的原生包? \n
- CI 的集成 \n
- 测试、发布与回滚 \n
- 元信息(Meta Info)的使用 \n
- 初步支持新架构 \n
- 添加事件回调以方便统计 \n
- 没有update.json文件的情况下不会再报错 \n
- 修复极少数热更失败的情况 \n
- 新增快速集成方法。 \n
- 默认使用AndroidX支持库(使用
npx jetify -r
命令转换可以支持老的support库) \n - 新增查看本地版本信息的方法(
getCurrentVersionInfo()
) \n - 库文件体积优化 \n
- 修复android 7及以下版本可能解压失败的问题 \n
- 修复频繁调用下载更新导致的图片丢失问题 \n
- 修复android 7及以下版本安装apk报错的问题 \n
- 换用 hdiff 算法,更新所需流量更少,速度更快 \n
- 修复一些少见的崩溃问题 \n
- 提升 iOS 更新的稳定性 \n
- 可在应用内直接下载安装新版本 apk \n
- 加入下载进度回调 \n
- 初始化时检查 Android 的 bundle url 是否正确配置 \n
- 修复 iOS 更新偶尔报找不到 app.json 的问题 \n
- 修复编译时找不到 generateiOSBuildTime.sh 的问题 \n
- 提供 setCustomInstanceManager 方法,方便自己集成 RN 的用户调用 \n
- bundle 时清除缓存 \n
- 修复更新包过大时可能出现的崩溃 \n
- publish 时检查文件格式 \n
- 提升服务健壮性 \n
- 防止某些情况下安卓找不到 bundle 文件引起的崩溃 \n
- 忽略 hermes 的输出避免 buffer 溢出 \n
- 修复使用 use_frameworks 时无法读取时间戳的问题 \n
- 打包时加入时间戳 \n
- 修改类名方法名 \n
- 可以禁用 ios 端以避免审核被拒 \n
- 替换 apk reader 以避免某些环境读取 apk 版本号报错的问题 \n
- 添加 proguard 混淆规则以解决开启混淆后闪退的问题 \n
- 解决某些情形下 Android 调用 switchVersion 不能重启的问题 \n
- 改进 windows 端打更新包的兼容性(部分 windows 机器上会产生空 ppk 文件) \n
- 支持 RN 0.61 的 hermes(路径变化) \n
- iOS 端使用第三方的 SSZipArchive 以减少重名冲突 \n
- 修复一处导致 iOS 回滚的问题 \n
- 检测如果开启了 hermes,则自动编译为 hermes 字节码格式 \n
- 添加 typescript 声明 \n
- 支持 cocoapods \n
- 重写 bundle 命令以提升版本兼容性 \n
- 改进命令行的输出样式 \n
- 服务器迁移到 https \n
- android 支持 64 位 \n
- 解决 Android 热更新后部分图片丢失问题:
\n同一个项目中放置了多个完全相同的文件,在 5.1.0 至 5.1.5 之间的版本中,更新后有时会出现其中的部分无法显示。此问题在 5.1.6 版本修复。修复此问题涉及原生部分,需要重新打包。 \n - 9.0.0(2023-09-02) \n
- 8.0.1(2022-07-05) \n
- 7.4.1(2022-05-04) \n
- 7.3.4(2021-11-04) \n
- 6.4.0(2021-10-06) \n
- 6.3.0(2021-10-04) \n
- 6.2.0(2021-08-13) \n
- 6.1.0(2021-07-29) \n
- 6.0.2(2021-05-18) \n
- 6.0.0(2021-05-04) \n
- 5.10.0(2020-12-18) \n
- 5.9.0(2020-09-27) \n
- 5.8.3(2020-09-24) \n
- 5.7.0(2020-08-13) \n
- 5.6.0(2020-05-26) \n
- 5.5.9 (2020-04-14) \n
- 5.5.8 (2020-04-02) \n
- 5.5.6 (2020-02-11) \n
- 5.5.5 (2020-01-18) \n
- 5.5.4 (2020-01-13) \n
- 5.5.3 (2019-12-18) \n
- 5.5.2 (2019-12-06) \n
- 5.5.0 (2019-11-24) \n
- 5.4.0 (2019-11-16) \n
- 5.3.2 (2019-10-25) \n
- 5.3.0 (2019-09-19) \n
- 5.2.9 (2019-09-18) \n
- 5.2.8 \n
- 5.2.7 \n
- 5.2.4 \n
- 5.2.2 \n
- 5.2.1 \n
- 5.2.0 \n
- 5.1.9 \n
- 5.1.8 \n
- 5.1.6 \n
- 初步支持新架构 \n
- 添加事件回调以方便统计 \n
- 没有update.json文件的情况下不会再报错 \n
- 修复极少数热更失败的情况 \n
- 新增快速集成方法。 \n
- 默认使用AndroidX支持库(使用
npx jetify -r
命令转换可以支持老的support库) \n - 新增查看本地版本信息的方法(
getCurrentVersionInfo()
) \n - 库文件体积优化 \n
- 修复android 7及以下版本可能解压失败的问题 \n
- 修复频繁调用下载更新导致的图片丢失问题 \n
- 修复android 7及以下版本安装apk报错的问题 \n
- 换用 hdiff 算法,更新所需流量更少,速度更快 \n
- 修复一些少见的崩溃问题 \n
- 提升 iOS 更新的稳定性 \n
- 可在应用内直接下载安装新版本 apk \n
- 加入下载进度回调 \n
- 初始化时检查 Android 的 bundle url 是否正确配置 \n
- 修复 iOS 更新偶尔报找不到 app.json 的问题 \n
- 修复编译时找不到 generateiOSBuildTime.sh 的问题 \n
- 提供 setCustomInstanceManager 方法,方便自己集成 RN 的用户调用 \n
- bundle 时清除缓存 \n
- 修复更新包过大时可能出现的崩溃 \n
- publish 时检查文件格式 \n
- 提升服务健壮性 \n
- 防止某些情况下安卓找不到 bundle 文件引起的崩溃 \n
- 忽略 hermes 的输出避免 buffer 溢出 \n
- 修复使用 use_frameworks 时无法读取时间戳的问题 \n
- 打包时加入时间戳 \n
- 修改类名方法名 \n
- 可以禁用 ios 端以避免审核被拒 \n
- 替换 apk reader 以避免某些环境读取 apk 版本号报错的问题 \n
- 添加 proguard 混淆规则以解决开启混淆后闪退的问题 \n
- 解决某些情形下 Android 调用 switchVersion 不能重启的问题 \n
- 改进 windows 端打更新包的兼容性(部分 windows 机器上会产生空 ppk 文件) \n
- 支持 RN 0.61 的 hermes(路径变化) \n
- iOS 端使用第三方的 SSZipArchive 以减少重名冲突 \n
- 修复一处导致 iOS 回滚的问题 \n
- 检测如果开启了 hermes,则自动编译为 hermes 字节码格式 \n
- 添加 typescript 声明 \n
- 支持 cocoapods \n
- 重写 bundle 命令以提升版本兼容性 \n
- 改进命令行的输出样式 \n
- 服务器迁移到 https \n
- android 支持 64 位 \n
- 解决 Android 热更新后部分图片丢失问题:
\n同一个项目中放置了多个完全相同的文件,在 5.1.0 至 5.1.5 之间的版本中,更新后有时会出现其中的部分无法显示。此问题在 5.1.6 版本修复。修复此问题涉及原生部分,需要重新打包。 \n - 9.0.0(2023-09-02) \n
- 8.0.1(2022-07-05) \n
- 7.4.1(2022-05-04) \n
- 7.3.4(2021-11-04) \n
- 6.4.0(2021-10-06) \n
- 6.3.0(2021-10-04) \n
- 6.2.0(2021-08-13) \n
- 6.1.0(2021-07-29) \n
- 6.0.2(2021-05-18) \n
- 6.0.0(2021-05-04) \n
- 5.10.0(2020-12-18) \n
- 5.9.0(2020-09-27) \n
- 5.8.3(2020-09-24) \n
- 5.7.0(2020-08-13) \n
- 5.6.0(2020-05-26) \n
- 5.5.9 (2020-04-14) \n
- 5.5.8 (2020-04-02) \n
- 5.5.6 (2020-02-11) \n
- 5.5.5 (2020-01-18) \n
- 5.5.4 (2020-01-13) \n
- 5.5.3 (2019-12-18) \n
- 5.5.2 (2019-12-06) \n
- 5.5.0 (2019-11-24) \n
- 5.4.0 (2019-11-16) \n
- 5.3.2 (2019-10-25) \n
- 5.3.0 (2019-09-19) \n
- 5.2.9 (2019-09-18) \n
- 5.2.8 \n
- 5.2.7 \n
- 5.2.4 \n
- 5.2.2 \n
- 5.2.1 \n
- 5.2.0 \n
- 5.1.9 \n
- 5.1.8 \n
- 5.1.6 \n
- platform: ios|android 对应的平台 \n
- entryFile: 入口脚本文件 \n
- intermediaDir: 临时文件输出目录 \n
- output: 最终 ppk 文件输出路径 \n
- dev: 是否打包开发版本 \n
- sourcemap: 是否生成sourcemap(需cli版本1.11.0+) \n
- output: diff 文件输出路径 \n
- output: diff 文件输出路径 \n
- output: diff 文件输出路径 \n
- platform: ios|android 对应的平台 \n
- name: 应用名称 \n
- downloadUrl: 应用安装包的下载地址 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- name: 当前热更新版本的名字(版本号) \n
- description: 当前热更新版本的描述信息,可以对用户进行展示 \n
- metaInfo: 当前热更新版本的元信息,可以用来保存一些额外信息,具体用法可参考场景实践。 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- versionId: 要绑定的热更新版本 ID \n
- packageId: 要绑定的原生包 ID (与版本名二选一) \n
- packageVersion: 要绑定的原生包版本名(与 ID 二选一,需 cli 版本 1.7.2 或以上) \n
- 安装 \n
- \n\n
- \n
- pushy bundle \n
- pushy parseIpa ipaFile \n
- pushy parseApk apkFile \n
- pushy diff origin \n
- pushy diffFromApk apkFile \n
- pushy diffFromIpa ipaFile \n
- pushy login email \n
- pushy logout \n
- pushy me \n
- pushy createApp \n
- pushy deleteApp appId \n
- pushy apps \n
- pushy selectApp appId \n
- pushy uploadIpa ipaFile \n
- pushy uploadApk apkFile \n
- pushy packages \n
- pushy publish ppkFile \n
- pushy versions \n
- pushy update \n
\n - platform: ios|android 对应的平台 \n
- entryFile: 入口脚本文件 \n
- intermediaDir: 临时文件输出目录 \n
- output: 最终 ppk 文件输出路径 \n
- dev: 是否打包开发版本 \n
- sourcemap: 是否生成sourcemap(需cli版本1.11.0+) \n
- output: diff 文件输出路径 \n
- output: diff 文件输出路径 \n
- output: diff 文件输出路径 \n
- platform: ios|android 对应的平台 \n
- name: 应用名称 \n
- downloadUrl: 应用安装包的下载地址 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- name: 当前热更新版本的名字(版本号) \n
- description: 当前热更新版本的描述信息,可以对用户进行展示 \n
- metaInfo: 当前热更新版本的元信息,可以用来保存一些额外信息,具体用法可参考场景实践。 \n
- platform: ios|android 对应的平台 \n
- platform: ios|android 对应的平台 \n
- versionId: 要绑定的热更新版本 ID \n
- packageId: 要绑定的原生包 ID (与版本名二选一) \n
- packageVersion: 要绑定的原生包版本名(与 ID 二选一,需 cli 版本 1.7.2 或以上) \n
- 安装 \n
- \n\n
- \n
- pushy bundle \n
- pushy parseIpa ipaFile \n
- pushy parseApk apkFile \n
- pushy diff origin \n
- pushy diffFromApk apkFile \n
- pushy diffFromIpa ipaFile \n
- pushy login email \n
- pushy logout \n
- pushy me \n
- pushy createApp \n
- pushy deleteApp appId \n
- pushy apps \n
- pushy selectApp appId \n
- pushy uploadIpa ipaFile \n
- pushy uploadApk apkFile \n
- pushy packages \n
- pushy publish ppkFile \n
- pushy versions \n
- pushy update \n
\n - \n
不可热更新 —— 原生修改,即所有需要
\n编译
后才能生效的修改:- \n
- 任何在 iOS 或者 Android 目录中的修改、增删。 \n
- 任何含有原生代码的第三方组件的更新、修改。 \n
\n - \n
可以热更新 —— 非原生修改,即所有
\n无需编译
,刷新即可生效的修改:- \n
- js 代码修改,包括第三方纯 js 组件的更新、修改。 \n
- 可以在 js 代码中 require/import 的资源文件,例如图片。 \n
\n - 没有正确配置 bundleUrl \n
- 没有正确调用 markSuccess \n
- 我忘记上传过
1A包
,1B包
没有实质更改且还没有客户安装。此时应当放弃1B包
,只让客户下载安装1A包
。 \n - 我忘记上传过
1A包
,又生成了1B包
且已有客户安装。此时1A包
客户可以获取热更新,1B包
客户无法获取热更新。要使两批客户都能获取热更新,要么想办法通知1B包
客户装回1A包
,要么重新发布一个高于1.0
版本的原生包且上传到 pushy 服务器,并删除1.0
版本的记录,此时1A包
和1B包
的客户都会收到版本过期需要下载新版本的通知。 \n - 我知道上传过
1A包
,但我有原生方面的修改需要打了一个新的1B包
。此时若将1B包
上传到 pushy 服务器会提示版本验证错误,因为已经存在有相同的1.0
版本。所以需要首先更改原生版本号再次打包,并首先
将此新版本上传到服务器,然后
分发给客户。这样1.0版本
和新版本
可以并存且都可以获得热更新。 \n - 可创建的应用数量,注意 iOS 和 Android 版本记做不同的应用。 \n
- 原生包数量及大小。原生包指通过
pushy uploadIpa/uploadApk
命令上传到 Pushy 服务器上作为热更新起始版本的完整 apk/ipa 安装包。 \n - 热更包数量及大小。热更包指通过
pushy bundle
所命令生成的 ppk 文件。注意这不是用户实际下载的更新文件,用户下载的是通过比对生成的增量 diff 文件(比 ppk 文件要小得多)。 \n - \n\n\n \n
- \n\n\n \n
- \n
不可热更新 —— 原生修改,即所有需要
\n编译
后才能生效的修改:- \n
- 任何在 iOS 或者 Android 目录中的修改、增删。 \n
- 任何含有原生代码的第三方组件的更新、修改。 \n
\n - \n
可以热更新 —— 非原生修改,即所有
\n无需编译
,刷新即可生效的修改:- \n
- js 代码修改,包括第三方纯 js 组件的更新、修改。 \n
- 可以在 js 代码中 require/import 的资源文件,例如图片。 \n
\n - 没有正确配置 bundleUrl \n
- 没有正确调用 markSuccess \n
- 我忘记上传过
1A包
,1B包
没有实质更改且还没有客户安装。此时应当放弃1B包
,只让客户下载安装1A包
。 \n - 我忘记上传过
1A包
,又生成了1B包
且已有客户安装。此时1A包
客户可以获取热更新,1B包
客户无法获取热更新。要使两批客户都能获取热更新,要么想办法通知1B包
客户装回1A包
,要么重新发布一个高于1.0
版本的原生包且上传到 pushy 服务器,并删除1.0
版本的记录,此时1A包
和1B包
的客户都会收到版本过期需要下载新版本的通知。 \n - 我知道上传过
1A包
,但我有原生方面的修改需要打了一个新的1B包
。此时若将1B包
上传到 pushy 服务器会提示版本验证错误,因为已经存在有相同的1.0
版本。所以需要首先更改原生版本号再次打包,并首先
将此新版本上传到服务器,然后
分发给客户。这样1.0版本
和新版本
可以并存且都可以获得热更新。 \n - 可创建的应用数量,注意 iOS 和 Android 版本记做不同的应用。 \n
- 原生包数量及大小。原生包指通过
pushy uploadIpa/uploadApk
命令上传到 Pushy 服务器上作为热更新起始版本的完整 apk/ipa 安装包。 \n - 热更包数量及大小。热更包指通过
pushy bundle
所命令生成的 ppk 文件。注意这不是用户实际下载的更新文件,用户下载的是通过比对生成的增量 diff 文件(比 ppk 文件要小得多)。 \n - \n\n\n \n
- \n\n\n \n
- 在 ios/Podfile 中添加 \n
- 在项目的 ios 目录下运行
pod install
\n - 重新编译 \n
- 在 XCode 中的 Project Navigator 里,右键点击
Libraries
➜Add Files to [你的工程名]
\n - 进入
node_modules
➜react-native-update
➜ios 并选中
RCTPushy.xcodeproj` \n - 在 XCode 中的 project navigator 里,选中你的工程,在
Build Phases
➜Link Binary With Libraries
中添加libRCTPushy.a
、libz.tbd
、libbz2.1.0.tbd
\n - 继续在
Build Settings
里搜索Header Search Path
,添加$(SRCROOT)/../node_modules/react-native-update/ios
,勾选recursive
。 \n - 在
Build Phases
添加一个New Run Script Phase
运行脚本,内容如下 \n - 尝试编译一下,顺利的话就会在
../node_modules/react-native-update/ios/
文件夹下面生成一个pushy_build_time.txt
文件。然后在Copy Bundle Resources
里把生成的pushy_build_time.txt
文件添加进去。 \n - \n
在
\nandroid/settings.gradle
中添加如下代码:\ninclude ':react-native-update'\nproject(':react-native-update').projectDir = new File(rootProject.projectDir, \t'../node_modules/react-native-update/android')
\n - \n
在
\nandroid/app/build.gradle
的 dependencies 部分增加如下代码:\nimplementation project(':react-native-update')
\n - 打开
android/app/src/main/java/[...]/MainApplication.java
, \n - 在文件开头增加
import cn.reactnative.modules.update.UpdatePackage;
\n - \n
在
\ngetPackages()
方法中增加new UpdatePackage()
(注意上一行可能要增加一个逗号)
JavaScript 常量
\n
\ndownloadRootDir
\n下载的根目录。你可以使用 react-native-fs 等第三方组件检查其中的内容。
\n
\npackageVersion
\n当前应用原生包的版本。其中 android 取自
\nversionName
字段(位于android/app/build.gradle
中)。ios 取自CFBundleShortVersionString
字段(位于ios/项目名/Info.plist
中)。
\ncurrentVersion
\n当前热更新版本(jsbundle 文件)的 Hash 号。
\n
\nisFirstTime
\n是否更新后的首次启动。当此项为真时,你需要在合适的时候调用
\nmarkSuccess()
以确保更新成功。否则应用下一次启动时将会回滚。
\nisRolledBack
\n是否刚刚经历了一次回滚。
\nJavaScript 方法
\n
\nasync function checkUpdate(appKey)
\n检查更新,返回值有三种情形:
\n- \n
\n{\n expired: true,\n downloadUrl: 'http://appstore/downloadUrl',\n }
- \n
\n{\n update: true,\n name: '1.0.3-rc',\n hash: 'hash',\n description: '添加聊天功能\\n修复商城页面BUG',\n metaInfo: '{"silent":true}',\n pdiffUrl: 'http://update-packages.reactnative.cn/hash',\n diffUrl: 'http://update-packages.reactnative.cn/hash',\n }
\nasync function downloadUpdate(info, callbacks)
\n下载更新版本。
\ninfo
为checkUpdate
函数的返回值,并且仅当update:true
时实际进行下载。从
\nv5.8.3
版本开始新增接受第二个可选参数,为下载进度的回调函数(onDownloadProgress
)。可根据回调参数自行设计进度的展示。示例:\nconst hash = await downloadUpdate(\n info,\n // 下载回调为可选参数,自v5.8.3版本起可用\n {\n onDownloadProgress: ({ received, total }) => {\n // 已下载的字节数, 总字节数\n console.log(received, total);\n },\n },\n);
\nasync function downloadAndInstallApk({ url, onDownloadProgress })
\n下载更新的 apk 包并直接安装。
\nurl
必须为可直接下载到 apk 文件的地址,onDownloadProgress
为可选的下载进度回调函数,可根据回调参数自行设计进度的展示。自v5.9.0
版本起可用。
\nfunction markSuccess()
\n在
\nisFirstTime
为true
时,必须调用此函数作为更新成功的标记(否则下次启动会默认失败自动回滚)。
\nasync function getCurrentVersionInfo()
\n获取当前已热更版本的信息(如尚未热更过则返回空对象)。
\n返回值示例:
\n\n{\n name: '1.0.3-rc',\n description: '添加聊天功能\\n修复商城页面BUG',\n metaInfo: '{"silent":true}',\n }
\nfunction switchVersion(hash)
\n立即重启应用,并加载已经下载完毕的版本。
\n
\nfunction switchVersionLater(hash)
\n在下一次启动应用的时候加载已经下载完毕的版本。
\n
\nAndroid 方法
\nUpdateContext.setCustomInstanceManager(ReactInstanceManager instanceManager)
\n如果是集成/混编 Android 方案,则可以使用此方法传入你自行创建的 ReactInstanceManager。自
\nv5.5.8
版本起可用。示例:
\n\nimport cn.reactnative.modules.update.UpdateContext\n\nmReactInstanceManager = ReactInstanceManager.builder()\n // ...各种setter,但注意不要调用setBundleAssetName\n .setJSBundleFile(UpdateContext.getBundleUrl(mContext, \"assets://index.android.bundle\"))\n .build();\nUpdateContext.setCustomInstanceManager(mReactInstanceManager);
iOS 方法
\n待补充
","tableOfContents":"- \n
JavaScript 常量
\n
\ndownloadRootDir
\n下载的根目录。你可以使用 react-native-fs 等第三方组件检查其中的内容。
\n
\npackageVersion
\n当前应用原生包的版本。其中 android 取自
\nversionName
字段(位于android/app/build.gradle
中)。ios 取自CFBundleShortVersionString
字段(位于ios/项目名/Info.plist
中)。
\ncurrentVersion
\n当前热更新版本(jsbundle 文件)的 Hash 号。
\n
\nisFirstTime
\n是否更新后的首次启动。当此项为真时,你需要在合适的时候调用
\nmarkSuccess()
以确保更新成功。否则应用下一次启动时将会回滚。
\nisRolledBack
\n是否刚刚经历了一次回滚。
\nJavaScript 方法
\n
\nasync function checkUpdate(appKey)
\n检查更新,返回值有三种情形:
\n- \n
\n{\n expired: true,\n downloadUrl: 'http://appstore/downloadUrl',\n }
- \n
\n{\n update: true,\n name: '1.0.3-rc',\n hash: 'hash',\n description: '添加聊天功能\\n修复商城页面BUG',\n metaInfo: '{"silent":true}',\n pdiffUrl: 'http://update-packages.reactnative.cn/hash',\n diffUrl: 'http://update-packages.reactnative.cn/hash',\n }
\nasync function downloadUpdate(info, callbacks)
\n下载更新版本。
\ninfo
为checkUpdate
函数的返回值,并且仅当update:true
时实际进行下载。从
\nv5.8.3
版本开始新增接受第二个可选参数,为下载进度的回调函数(onDownloadProgress
)。可根据回调参数自行设计进度的展示。示例:\nconst hash = await downloadUpdate(\n info,\n // 下载回调为可选参数,自v5.8.3版本起可用\n {\n onDownloadProgress: ({ received, total }) => {\n // 已下载的字节数, 总字节数\n console.log(received, total);\n },\n },\n);
\nasync function downloadAndInstallApk({ url, onDownloadProgress })
\n下载更新的 apk 包并直接安装。
\nurl
必须为可直接下载到 apk 文件的地址,onDownloadProgress
为可选的下载进度回调函数,可根据回调参数自行设计进度的展示。自v5.9.0
版本起可用。
\nfunction markSuccess()
\n在
\nisFirstTime
为true
时,必须调用此函数作为更新成功的标记(否则下次启动会默认失败自动回滚)。
\nasync function getCurrentVersionInfo()
\n获取当前已热更版本的信息(如尚未热更过则返回空对象)。
\n返回值示例:
\n\n{\n name: '1.0.3-rc',\n description: '添加聊天功能\\n修复商城页面BUG',\n metaInfo: '{"silent":true}',\n }
\nfunction switchVersion(hash)
\n立即重启应用,并加载已经下载完毕的版本。
\n
\nfunction switchVersionLater(hash)
\n在下一次启动应用的时候加载已经下载完毕的版本。
\n
\nAndroid 方法
\nUpdateContext.setCustomInstanceManager(ReactInstanceManager instanceManager)
\n如果是集成/混编 Android 方案,则可以使用此方法传入你自行创建的 ReactInstanceManager。自
\nv5.5.8
版本起可用。示例:
\n\nimport cn.reactnative.modules.update.UpdateContext\n\nmReactInstanceManager = ReactInstanceManager.builder()\n // ...各种setter,但注意不要调用setBundleAssetName\n .setJSBundleFile(UpdateContext.getBundleUrl(mContext, \"assets://index.android.bundle\"))\n .build();\nUpdateContext.setCustomInstanceManager(mReactInstanceManager);
iOS 方法
\n待补充
","tableOfContents":"- \n
优化原生和热更包体积
\niOS 原生包优化(ipa)
\n对于同一份 archive(其版本号、编译时间和内置 bundle 已固定,不会受导出方式所影响),可以用不同选项多次导出 ipa,选择其中最小的上传到 pushy 服务器作为热更基准包。
\n\n \n \n \n \n
\nAndroid 原生包优化(apk)
\napk 的优化主要考虑两个方向:
\n- \n
\nsplits {\n abi {\n reset()\n- enable enableSeparateBuildPerCPUArchitecture\n+ enable true // 启用单独的 cpu 架构编译\n universalApk false // If true, also generate a universal APK\n }\n}
如此一来会在编译目录中输出多个 apk 文件,分发和上传到热更新服务时只需要使用
\napp-arm64-v8a-release.apk
文件,可以大幅减小 apk 的大小。热更新包优化(ppk)
\n热更新包的主要内容是 js 包和其所引用的静态资源(主要是图片)。
\n- \n
有很多渠道包需要热更,如何操作比较方便?
\n- \n
如何支持 aab 格式的原生包?
\n如果您需要使用 aab 格式的 android 原生包,那么可以在上传到 Google play 之后,在其控制台中下载转换后的 apk 格式(见下图),然后将这个 apk 包上传到热更新的后台,即可正常支持热更新。
\n\n \n \n \n \n
\nCI 的集成
\n在开发环境中,每次 bundle 都会生成一个不同名字的 ppk 文件,这不利于持续集成(CI)系统的引入。
\n要解决这个问题,你可以使用
\n--output
参数来指定输出 ppk 文件的名字和路径,便于进行自动发布。测试、发布与回滚
\n我们强烈建议您先发布一个测试包,再发布一个除了版本号以外均完全相同的正式包。
\n例如,假设我们有一个正式包,版本为
\n1.6.0
,那么可以修改版本号重新打包一个1001.6.0
,以一个明显不太正常的版本号来标识它是一个测试版本,同时后几位相同,可以表明它和某个正式版本存在关联(内容/依赖一致)。在每次往发布包发起热更新之前,先对测试包
\n1001.6.0
进行更新操作,基本测试通过之后,再在网页后台上将热更包重新绑定到正式包1.6.0
上。如果在测试包中发现了重大问题,你就可以先进行修复,更新测试确认通过后再部署到正式线上环境。这样,可以最大程度的避免发生线上事故。万一确实发生线上事故需要回滚的话,首先利用版本控制系统回滚代码到正常的状态,然后重新生成热更包并推送即可。
\n元信息(Meta Info)的使用
\n在发布热更新版本时,或者在网页端,你可以编辑版本的元信息。这是一段在检查更新时可以获得的字符串,你可以在其中按你所想的格式(一般建议用JSON 格式)保存一些信息。
\n比如我们可以在元信息中约定字段标志
\nsilent
,表示需要静默更新。当我们上传热更包填写 metainfo 时,以JSON 格式输入:\n{ \"silent\": true }
\n
\n请注意,我们并不对输入做任何格式校验和约束,请自行校验输入是否正确。
\n此时在客户端检查更新时,能获取到我们刚刚输入的元信息,但它并不具备任何功能,只是一个字符串而已。所以我们其实需要预先在更新流程中加入对应的处理逻辑:
\n\n// 调用 checkUpdate 获取 info\nif (info.expired) {\n // ... 原生包版本过期,下载或跳转下载页面\n} else if (info.upToDate) {\n // ... 没有更新,弹提示或忽略\n} else {\n // 有更新,一般来说我们在这里给用户弹窗提示,让用户选择是否更新\n // 那么静默更新的本质其实就是不弹窗,直接执行,所以可以在这里加入额外的判断流程\n Alert.alert('提示', '检查到新的版本' + info.name + ',是否下载?\\n' + info.description, [\n {\n text: '是',\n onPress: () => {\n this.doUpdate(info);\n },\n },\n { text: '否' },\n ]);\n}
我们在原有的更新流程中加入元信息的读取和判断:
\n\nlet metaInfo = {};\ntry {\n // 注意 JSON 输入有可能有错误,需要用 try 语句来避免应用被带崩\n metaInfo = JSON.parse(info.metaInfo);\n} catch (e) {\n // 异常处理,忽略或上报?\n}\n\nif (metaInfo.silent) {\n // 如果热更包携带有 silent 字段,不询问用户,直接执行更新\n this.doUpdate(info);\n} else {\n // 否则还是走之前的询问流程\n // Alert.alert('提示', '检查到新的版本.......\n}
又比如,可能某个版本包含一些重要的公告内容,所以还可以在上面插入一个公告字段等等。如何使用元信息,完全取决于您的想象力!
","tableOfContents":"- \n
优化原生和热更包体积
\niOS 原生包优化(ipa)
\n对于同一份 archive(其版本号、编译时间和内置 bundle 已固定,不会受导出方式所影响),可以用不同选项多次导出 ipa,选择其中最小的上传到 pushy 服务器作为热更基准包。
\n\n \n \n \n \n
\nAndroid 原生包优化(apk)
\napk 的优化主要考虑两个方向:
\n- \n
\nsplits {\n abi {\n reset()\n- enable enableSeparateBuildPerCPUArchitecture\n+ enable true // 启用单独的 cpu 架构编译\n universalApk false // If true, also generate a universal APK\n }\n}
如此一来会在编译目录中输出多个 apk 文件,分发和上传到热更新服务时只需要使用
\napp-arm64-v8a-release.apk
文件,可以大幅减小 apk 的大小。热更新包优化(ppk)
\n热更新包的主要内容是 js 包和其所引用的静态资源(主要是图片)。
\n- \n
有很多渠道包需要热更,如何操作比较方便?
\n- \n
如何支持 aab 格式的原生包?
\n如果您需要使用 aab 格式的 android 原生包,那么可以在上传到 Google play 之后,在其控制台中下载转换后的 apk 格式(见下图),然后将这个 apk 包上传到热更新的后台,即可正常支持热更新。
\n\n \n \n \n \n
\nCI 的集成
\n在开发环境中,每次 bundle 都会生成一个不同名字的 ppk 文件,这不利于持续集成(CI)系统的引入。
\n要解决这个问题,你可以使用
\n--output
参数来指定输出 ppk 文件的名字和路径,便于进行自动发布。测试、发布与回滚
\n我们强烈建议您先发布一个测试包,再发布一个除了版本号以外均完全相同的正式包。
\n例如,假设我们有一个正式包,版本为
\n1.6.0
,那么可以修改版本号重新打包一个1001.6.0
,以一个明显不太正常的版本号来标识它是一个测试版本,同时后几位相同,可以表明它和某个正式版本存在关联(内容/依赖一致)。在每次往发布包发起热更新之前,先对测试包
\n1001.6.0
进行更新操作,基本测试通过之后,再在网页后台上将热更包重新绑定到正式包1.6.0
上。如果在测试包中发现了重大问题,你就可以先进行修复,更新测试确认通过后再部署到正式线上环境。这样,可以最大程度的避免发生线上事故。万一确实发生线上事故需要回滚的话,首先利用版本控制系统回滚代码到正常的状态,然后重新生成热更包并推送即可。
\n元信息(Meta Info)的使用
\n在发布热更新版本时,或者在网页端,你可以编辑版本的元信息。这是一段在检查更新时可以获得的字符串,你可以在其中按你所想的格式(一般建议用JSON 格式)保存一些信息。
\n比如我们可以在元信息中约定字段标志
\nsilent
,表示需要静默更新。当我们上传热更包填写 metainfo 时,以JSON 格式输入:\n{ \"silent\": true }
\n
\n请注意,我们并不对输入做任何格式校验和约束,请自行校验输入是否正确。
\n此时在客户端检查更新时,能获取到我们刚刚输入的元信息,但它并不具备任何功能,只是一个字符串而已。所以我们其实需要预先在更新流程中加入对应的处理逻辑:
\n\n// 调用 checkUpdate 获取 info\nif (info.expired) {\n // ... 原生包版本过期,下载或跳转下载页面\n} else if (info.upToDate) {\n // ... 没有更新,弹提示或忽略\n} else {\n // 有更新,一般来说我们在这里给用户弹窗提示,让用户选择是否更新\n // 那么静默更新的本质其实就是不弹窗,直接执行,所以可以在这里加入额外的判断流程\n Alert.alert('提示', '检查到新的版本' + info.name + ',是否下载?\\n' + info.description, [\n {\n text: '是',\n onPress: () => {\n this.doUpdate(info);\n },\n },\n { text: '否' },\n ]);\n}
我们在原有的更新流程中加入元信息的读取和判断:
\n\nlet metaInfo = {};\ntry {\n // 注意 JSON 输入有可能有错误,需要用 try 语句来避免应用被带崩\n metaInfo = JSON.parse(info.metaInfo);\n} catch (e) {\n // 异常处理,忽略或上报?\n}\n\nif (metaInfo.silent) {\n // 如果热更包携带有 silent 字段,不询问用户,直接执行更新\n this.doUpdate(info);\n} else {\n // 否则还是走之前的询问流程\n // Alert.alert('提示', '检查到新的版本.......\n}
又比如,可能某个版本包含一些重要的公告内容,所以还可以在上面插入一个公告字段等等。如何使用元信息,完全取决于您的想象力!
","tableOfContents":"- \n
9.0.0(2023-09-02)
\n- \n
8.0.1(2022-07-05)
\n- \n
7.4.1(2022-05-04)
\n- \n
7.3.4(2021-11-04)
\n- \n
6.4.0(2021-10-06)
\n- \n
6.3.0(2021-10-04)
\n- \n
6.2.0(2021-08-13)
\n- \n
6.1.0(2021-07-29)
\n- \n
6.0.2(2021-05-18)
\n- \n
6.0.0(2021-05-04)
\n- \n
5.10.0(2020-12-18)
\n- \n
5.9.0(2020-09-27)
\n- \n
5.8.3(2020-09-24)
\n- \n
5.7.0(2020-08-13)
\n- \n
5.6.0(2020-05-26)
\n- \n
5.5.9 (2020-04-14)
\n- \n
5.5.8 (2020-04-02)
\n- \n
5.5.6 (2020-02-11)
\n- \n
5.5.5 (2020-01-18)
\n- \n
5.5.4 (2020-01-13)
\n- \n
5.5.3 (2019-12-18)
\n- \n
5.5.2 (2019-12-06)
\n- \n
5.5.0 (2019-11-24)
\n- \n
5.4.0 (2019-11-16)
\n- \n
5.3.2 (2019-10-25)
\n- \n
5.3.0 (2019-09-19)
\n- \n
5.2.9 (2019-09-18)
\n- \n
5.2.8
\n- \n
5.2.7
\n- \n
5.2.4
\n- \n
5.2.2
\n- \n
5.2.1
\n- \n
5.2.0
\n- \n
5.1.9
\n- \n
5.1.8
\n- \n
5.1.6
\n- \n
- \n
9.0.0(2023-09-02)
\n- \n
8.0.1(2022-07-05)
\n- \n
7.4.1(2022-05-04)
\n- \n
7.3.4(2021-11-04)
\n- \n
6.4.0(2021-10-06)
\n- \n
6.3.0(2021-10-04)
\n- \n
6.2.0(2021-08-13)
\n- \n
6.1.0(2021-07-29)
\n- \n
6.0.2(2021-05-18)
\n- \n
6.0.0(2021-05-04)
\n- \n
5.10.0(2020-12-18)
\n- \n
5.9.0(2020-09-27)
\n- \n
5.8.3(2020-09-24)
\n- \n
5.7.0(2020-08-13)
\n- \n
5.6.0(2020-05-26)
\n- \n
5.5.9 (2020-04-14)
\n- \n
5.5.8 (2020-04-02)
\n- \n
5.5.6 (2020-02-11)
\n- \n
5.5.5 (2020-01-18)
\n- \n
5.5.4 (2020-01-13)
\n- \n
5.5.3 (2019-12-18)
\n- \n
5.5.2 (2019-12-06)
\n- \n
5.5.0 (2019-11-24)
\n- \n
5.4.0 (2019-11-16)
\n- \n
5.3.2 (2019-10-25)
\n- \n
5.3.0 (2019-09-19)
\n- \n
5.2.9 (2019-09-18)
\n- \n
5.2.8
\n- \n
5.2.7
\n- \n
5.2.4
\n- \n
5.2.2
\n- \n
5.2.1
\n- \n
5.2.0
\n- \n
5.1.9
\n- \n
5.1.8
\n- \n
5.1.6
\n- \n
- \n
安装
\n\n$ npm install -g react-native-update-cli
命令
\npushy bundle
\n生成资源包
\n- \n
\npushy parseIpa [ipaFile]
\n解析 ipa 文件并输出一些相关信息,如版本号,编译时间戳等。
\n
\npushy parseApk [apkFile]
\n解析 apk 文件并输出一些相关信息,如版本号,编译时间戳等。
\n
\npushy diff [origin][next]
\n提供两个 ppk 文件,生成从 origin 到 next 版本的差异更新包。
\n- \n
\npushy diffFromApk [apkFile][next]
\n提供一个 apk 文件和一个 ppk 文件,生成从 apk 文件到 next 版本的差异更新包。
\n如果使用热更新开放平台,你不需要自己执行此命令。
\n- \n
\npushy diffFromIpa [ipaFile][next]
\n提供一个 ipa 文件和一个 ppk 文件,生成从 ipa 文件到 next 版本的差异更新包。
\n如果使用热更新开放平台,你不需要自己执行此命令。
\n- \n
\npushy login [email][pwd]
\n登录热更新开放平台。你需要先登录才能使用下面的命令。
\n
\npushy logout
\n登出并清除本地的登录信息
\n
\npushy me
\n查看自己是否已经登录,以及昵称等信息。
\n
\npushy createApp
\n创建应用并立刻绑定到当前工程。这项操作也可以在网页管理端进行。
\n- \n
\npushy deleteApp [appId]
\n删除已有应用。所有已创建的应用包、热更新版本都会被同时删除。这项操作也可以在网页管理端进行。
\n- \n
\npushy apps
\n查看当前已创建的全部应用。这项操作也可以在网页管理端进行。
\n- \n
\npushy selectApp [appId]
\n绑定应用到当前工程。
\n- \n
\npushy uploadIpa [ipaFile]
\n上传 ipa 文件到开放平台。
\n
\npushy uploadApk [apkFile]
\n上传 apk 文件到开放平台。
\n
\npushy packages
\n查看已经上传的原生包。这项操作也可以在网页管理端进行。
\n- \n
\npushy publish [ppkFile]
\n发布新的热更新版本(ppk 文件)。
\n- \n
\npushy versions
\n分页列举可用的版本。这项操作也可以在网页管理端进行。
\n- \n
\npushy update
\n为一个原生包版本绑定一个热更新版本。这项操作也可以在网页管理端进行。
\n- \n
- \n
安装
\n\n$ npm install -g react-native-update-cli
命令
\npushy bundle
\n生成资源包
\n- \n
\npushy parseIpa [ipaFile]
\n解析 ipa 文件并输出一些相关信息,如版本号,编译时间戳等。
\n
\npushy parseApk [apkFile]
\n解析 apk 文件并输出一些相关信息,如版本号,编译时间戳等。
\n
\npushy diff [origin][next]
\n提供两个 ppk 文件,生成从 origin 到 next 版本的差异更新包。
\n- \n
\npushy diffFromApk [apkFile][next]
\n提供一个 apk 文件和一个 ppk 文件,生成从 apk 文件到 next 版本的差异更新包。
\n如果使用热更新开放平台,你不需要自己执行此命令。
\n- \n
\npushy diffFromIpa [ipaFile][next]
\n提供一个 ipa 文件和一个 ppk 文件,生成从 ipa 文件到 next 版本的差异更新包。
\n如果使用热更新开放平台,你不需要自己执行此命令。
\n- \n
\npushy login [email][pwd]
\n登录热更新开放平台。你需要先登录才能使用下面的命令。
\n
\npushy logout
\n登出并清除本地的登录信息
\n
\npushy me
\n查看自己是否已经登录,以及昵称等信息。
\n
\npushy createApp
\n创建应用并立刻绑定到当前工程。这项操作也可以在网页管理端进行。
\n- \n
\npushy deleteApp [appId]
\n删除已有应用。所有已创建的应用包、热更新版本都会被同时删除。这项操作也可以在网页管理端进行。
\n- \n
\npushy apps
\n查看当前已创建的全部应用。这项操作也可以在网页管理端进行。
\n- \n
\npushy selectApp [appId]
\n绑定应用到当前工程。
\n- \n
\npushy uploadIpa [ipaFile]
\n上传 ipa 文件到开放平台。
\n
\npushy uploadApk [apkFile]
\n上传 apk 文件到开放平台。
\n
\npushy packages
\n查看已经上传的原生包。这项操作也可以在网页管理端进行。
\n- \n
\npushy publish [ppkFile]
\n发布新的热更新版本(ppk 文件)。
\n- \n
\npushy versions
\n分页列举可用的版本。这项操作也可以在网页管理端进行。
\n- \n
\npushy update
\n为一个原生包版本绑定一个热更新版本。这项操作也可以在网页管理端进行。
\n- \n
- \n
如果本页面没能回答您的疑问,您可以去issues 区或 QQ 群 729013783 提问,或给我们发邮件。
\n业务问题
\n热更新究竟能否上架?
\n您可能听说过各种说法,但大量实践表明,热更新目前能够顺利上架 AppStore 和其他各种应用市场。唯一需要注意的是,在审核期间请不要发布热更新,不要让审核人员看到各种更新相关的提示和弹窗,即可顺利通过。
\n
\n是否可以在海外使用?
\n可以的,国内外都有高速 CDN 节点。
\n
\n哪些修改可以热更新?哪些不能?
\n我们把对应用的修改分为两类:
\n- \n
需要注意的是,即便资源文件可以热更新,但这些热更新后的资源文件会以
\nfile://
协议的形式提供访问,某些读取资源文件的第三方可能并不支持file://
协议。
\n我是否可以搭建自己的热更新服务?
\n你可以单独使用本组件的原生部分(不包括 js 模块)和命令行工具中的
\nbundle
、diff
、diffFromIpa
、diffFromApk
四个功能。这些功能都不会使用我们的热更新服务,也无需注册或登录账号。但你可能要编写自己的 js 模块来与不同的热更新服务器通讯。
\n如果您有兴趣搭建私有云服务,可以邮件联系我们。
\n
\nXCode 编译时报错 \"_BZ2_bzRead\", referenced from 等
\n在工程 target 的 Build Phases->Link Binary with Libraries 中加入 libz.tbd、libbz2.1.0.tbd
\n
\n热更新成功完成,但是重启后又回滚了是怎么回事?
\n可以正常更新,但是重启后回滚,一般有两种可能的情况:
\n- \n
如果你确定上述两个步骤都正确无误,请在issues 区给我们留言反馈。
\n
\n热更新报错:“热更新已暂停,原因:编译时间戳与服务器记录不一致。”
\n当您每次编译产生一个原生包时,其中都会记录一个编译时间戳
\nbuildTime
(可以使用pushy parseIpa a.ipa
或是pushy parseApk a.apk
命令来查看)。如果您需要把这个包发给客户并希望使用热更新功能,那么就需要使用 upload 命令来上传到我们的服务器,而服务器端会记录这个包的版本号和编译时间戳以便后续比对记录。举例来说,假如我已经上传了一个 1.0 版本原生包(
\n1A包
),但后来由于种种原因我又重新打包了(1B包
)但没有上传,这两个包有相同的版本号,但会有不同的编译时间戳。此时有几种可能的情况:- \n
请谨记,任何时候生成原生包,请 1)先修改原生版本号,2)并上传到 pushy 服务器,才可以正常获得热更新。
\n如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\n
\n付费问题
\n我应该选择哪个业务版本呢?
\n其实完全无需考虑,先从最高配额的专业版开始体验(新用户注册验证通过后,将自动获得 7 天
\n专业版
试用),各个版本功能完全一致!当试用时间到期后,若当前版本的配额不能满足需求,可随时补差价升级到更高配额的版本。升级自动按天数计算差价,绝无额外费用。
\n我可以试用付费版本先评估一下效果吗?
\n新用户注册验证通过后,将自动获得 7 天
\n专业版
试用。如您需要更长的评估时间,可将注册用户名、邮箱、公司(或个人)名称发送至hi@charmlot.com,标题注明“pushy 评估试用延长”,我们会为您酌情延长评估时间。
\n配额具体如何计算?
\n配额主要分为 3 种:
\n- \n
\n
\n这里有一些对包大小的优化建议可供参考。
\n以上 2、3 条为针对每个应用单独计算。具体配额和费用由于运营成本可能会有调整,请以价格表页面为准。已购买的用户在续费前不受调整影响。
\n
\n达到配额后还可以正常使用吗?
\n当应用、原生包、热更包数量达到配额限制后,您将无法执行相应的新增操作。但用户端仍可正常检查更新,下载已发布的更新。您可选择升级到更高配额,或是通过删除已不再使用的应用、原生包、热更包来使数量降低到配额以内,以便继续执行新增操作。
\n
\n若原生包、热更包大小超过限额,则会导致上传失败。您可以选择升级到更高配额,或是想办法进行精简优化。
\n我可以单独升级某项配额吗?
\n我们暂时无法为某个单项配额提供升级选项,请选择更高版本的配额。如果专业版本配额仍然不能满足需求,请通过邮件hi@charmlot.com与我们联系,我们将根据您的个性化需求为您定制方案。
\n
\n付费业务到期后不续费,现有应用还能否正常使用?
\n到期后按免费版额度执行。如您现有应用已超出配额,则必须通过删除操作降低到配额以内,方可执行新的操作(如创建应用,上传热更等),但不影响用户获取之前已发布的热更。
\n
\n如何获取付费的专人技术支持?
\n请将您的用户名和订单截图发送至hi@charmlot.com,同时提供您希望的技术联系方式(QQ、微信等),核实后会有技术专员添加您为好友。
\n
\n如何开具发票?
\n请将具体开票需求发送至hi@charmlot.com,并附上注册邮箱和订单截图。我们默认会回复普通电子发票到
\n注册邮箱
,类目为软件服务。如需指定接受邮箱或手机,请在邮件正文
中注明。如需要邮寄纸质发票请注明邮寄地址,邮费为到付。
\n可以使用银行转账付款吗?
\n可以的。请对照价格表,将对应版本的款项转账至:
\n\n\n\n
\n\n \n\n\n公司名称 \n武汉青罗网络科技有限公司 \n\n \n开户行名称 \n浙江网商银行 \n\n \n\n账号 \n8888888048825564 \n转账完成后请截图发送至hi@charmlot.com,并写明注册邮箱,我们将在一个工作日内开通对应服务。
\n
","tableOfContents":"- \n
如果本页面没能回答您的疑问,您可以去issues 区或 QQ 群 729013783 提问,或给我们发邮件。
\n业务问题
\n热更新究竟能否上架?
\n您可能听说过各种说法,但大量实践表明,热更新目前能够顺利上架 AppStore 和其他各种应用市场。唯一需要注意的是,在审核期间请不要发布热更新,不要让审核人员看到各种更新相关的提示和弹窗,即可顺利通过。
\n
\n是否可以在海外使用?
\n可以的,国内外都有高速 CDN 节点。
\n
\n哪些修改可以热更新?哪些不能?
\n我们把对应用的修改分为两类:
\n- \n
需要注意的是,即便资源文件可以热更新,但这些热更新后的资源文件会以
\nfile://
协议的形式提供访问,某些读取资源文件的第三方可能并不支持file://
协议。
\n我是否可以搭建自己的热更新服务?
\n你可以单独使用本组件的原生部分(不包括 js 模块)和命令行工具中的
\nbundle
、diff
、diffFromIpa
、diffFromApk
四个功能。这些功能都不会使用我们的热更新服务,也无需注册或登录账号。但你可能要编写自己的 js 模块来与不同的热更新服务器通讯。
\n如果您有兴趣搭建私有云服务,可以邮件联系我们。
\n
\nXCode 编译时报错 \"_BZ2_bzRead\", referenced from 等
\n在工程 target 的 Build Phases->Link Binary with Libraries 中加入 libz.tbd、libbz2.1.0.tbd
\n
\n热更新成功完成,但是重启后又回滚了是怎么回事?
\n可以正常更新,但是重启后回滚,一般有两种可能的情况:
\n- \n
如果你确定上述两个步骤都正确无误,请在issues 区给我们留言反馈。
\n
\n热更新报错:“热更新已暂停,原因:编译时间戳与服务器记录不一致。”
\n当您每次编译产生一个原生包时,其中都会记录一个编译时间戳
\nbuildTime
(可以使用pushy parseIpa a.ipa
或是pushy parseApk a.apk
命令来查看)。如果您需要把这个包发给客户并希望使用热更新功能,那么就需要使用 upload 命令来上传到我们的服务器,而服务器端会记录这个包的版本号和编译时间戳以便后续比对记录。举例来说,假如我已经上传了一个 1.0 版本原生包(
\n1A包
),但后来由于种种原因我又重新打包了(1B包
)但没有上传,这两个包有相同的版本号,但会有不同的编译时间戳。此时有几种可能的情况:- \n
请谨记,任何时候生成原生包,请 1)先修改原生版本号,2)并上传到 pushy 服务器,才可以正常获得热更新。
\n如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\n
\n付费问题
\n我应该选择哪个业务版本呢?
\n其实完全无需考虑,先从最高配额的专业版开始体验(新用户注册验证通过后,将自动获得 7 天
\n专业版
试用),各个版本功能完全一致!当试用时间到期后,若当前版本的配额不能满足需求,可随时补差价升级到更高配额的版本。升级自动按天数计算差价,绝无额外费用。
\n我可以试用付费版本先评估一下效果吗?
\n新用户注册验证通过后,将自动获得 7 天
\n专业版
试用。如您需要更长的评估时间,可将注册用户名、邮箱、公司(或个人)名称发送至hi@charmlot.com,标题注明“pushy 评估试用延长”,我们会为您酌情延长评估时间。
\n配额具体如何计算?
\n配额主要分为 3 种:
\n- \n
\n
\n这里有一些对包大小的优化建议可供参考。
\n以上 2、3 条为针对每个应用单独计算。具体配额和费用由于运营成本可能会有调整,请以价格表页面为准。已购买的用户在续费前不受调整影响。
\n
\n达到配额后还可以正常使用吗?
\n当应用、原生包、热更包数量达到配额限制后,您将无法执行相应的新增操作。但用户端仍可正常检查更新,下载已发布的更新。您可选择升级到更高配额,或是通过删除已不再使用的应用、原生包、热更包来使数量降低到配额以内,以便继续执行新增操作。
\n
\n若原生包、热更包大小超过限额,则会导致上传失败。您可以选择升级到更高配额,或是想办法进行精简优化。
\n我可以单独升级某项配额吗?
\n我们暂时无法为某个单项配额提供升级选项,请选择更高版本的配额。如果专业版本配额仍然不能满足需求,请通过邮件hi@charmlot.com与我们联系,我们将根据您的个性化需求为您定制方案。
\n
\n付费业务到期后不续费,现有应用还能否正常使用?
\n到期后按免费版额度执行。如您现有应用已超出配额,则必须通过删除操作降低到配额以内,方可执行新的操作(如创建应用,上传热更等),但不影响用户获取之前已发布的热更。
\n
\n如何获取付费的专人技术支持?
\n请将您的用户名和订单截图发送至hi@charmlot.com,同时提供您希望的技术联系方式(QQ、微信等),核实后会有技术专员添加您为好友。
\n
\n如何开具发票?
\n请将具体开票需求发送至hi@charmlot.com,并附上注册邮箱和订单截图。我们默认会回复普通电子发票到
\n注册邮箱
,类目为软件服务。如需指定接受邮箱或手机,请在邮件正文
中注明。如需要邮寄纸质发票请注明邮寄地址,邮费为到付。
\n可以使用银行转账付款吗?
\n可以的。请对照价格表,将对应版本的款项转账至:
\n\n\n\n
\n\n \n\n\n公司名称 \n武汉青罗网络科技有限公司 \n\n \n开户行名称 \n浙江网商银行 \n\n \n\n账号 \n8888888048825564 \n转账完成后请截图发送至hi@charmlot.com,并写明注册邮箱,我们将在一个工作日内开通对应服务。
\n
","tableOfContents":"- \n
首先你应该有一个基于 React Native 开发的应用,我们把具有 package.json 的目录叫做你的\"应用根目录\"。
\n如果你还没有初始化应用,请参阅开始使用 React Native。
\n所以我们也假设你已经拥有了开发 React Native 应用的一切环境,包括
\nNode.js
、XCode
、Android SDK
等等。安装
\n在你的项目根目录下运行以下命令:
\n\n# 先全局安装命令行工具,每台电脑只用装一次\nnpm i -g react-native-update-cli\n\n# 然后在项目目录中安装热更新模块\n# 0.71 及以上版本使用最新版本如下\nnpm i react-native-update\n\n# 0.71 以下版本请使用8.x版本\n# npm i react-native-update@8.x
\n
\n如果下载极慢或者显示网络失败,请设置使用淘宝镜像
\nnpx nrm use taobao
\n
\n注意请不要混用
\nnpm/yarn/pnpm
等包管理器及对应的lock
文件,团队成员请坚持使用同一包管理器,且仅保留统一格式的lock
文件如果你的 RN 版本 >= 0.60,请在 ios 目录下执行:
\n\npod install
如果你的 RN 版本 < 0.60,那么需要先在
\npackage.json
文件的scripts
中加入:\n\"postinstall\": \"npx jetify -r\"
然后按照手动 link的说明操作。
\n\n
\n注意:如果是混编 RN 项目,由于目前官方集成文档并不完善,参照官方文档可能无法实现自动 link 功能。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link 操作。
\n\n\n\n如果你的RN版本比较老(< 0.46),请点击这里的注意事项\n
\n如果你的 RN 版本比较老,请按下面表格尝试老一些的版本(但这些版本我们已不再维护,不能保证可以使用):
\n\n\n
\n\n \n\n\nReact Native 版本 \nreact-native-update 版本 \n\n \n0.26 及以下 \n1.0.x \n\n \n0.27 - 0.28 \n2.x \n\n \n0.29 - 0.33 \n3.x \n\n \n0.34 - 0.45 \n4.x \n\n \n\n0.46 - 0.70 \n8.x \n安装命令示例:
\n\nnpm i react-native-update@4.x
如果 RN 的版本是 0.45 及以下,你还必须安装Android NDK,版本最好选用 r10e,并设置环境变量
\nANDROID_NDK_HOME
,指向你的 NDK 根目录(例如/Users/tdzl2003/Downloads/android-ndk-r10e
)。\n
\n请记得,任意在 ios 和 android 目录下的修改,一定要重新编译(npx react-native run-ios 或 run-android 命令编译,或在 Xcode/Android Studio 中重新编译)才能生效。
\n手动 link
\n如果 RN 版本 >= 0.60 则不需要此手动 link 步骤。
\n\n
\n注意:如果是混编 RN 项目,由于目前官方集成文档并不完善,参照官方文档可能无法实现自动 link 功能。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link 操作。
\niOS
\n\n\nRN < 0.60且使用CocoaPods(推荐)
\n- \n
\npod 'react-native-update', path: '../node_modules/react-native-update'
- \n
\n\nRN < 0.60且不使用CocoaPods
\n- \n
\n#!/bin/bash\nset -x\nDEST="../node_modules/react-native-update/ios/"\ndate +%s > "$DEST/pushy_build_time.txt"
- \n
Android
\n\n\nRN < 0.60
\n- \n
\n\n - 安装 \n
- \n\n\n \n
- \n\n\n \n
- 禁用 android 的 crunch 优化 \n
- 登录与创建应用 \n
- 在 ios/Podfile 中添加 \n
- 在项目的 ios 目录下运行
pod install
\n - 重新编译 \n
- 在 XCode 中的 Project Navigator 里,右键点击
Libraries
➜Add Files to [你的工程名]
\n - 进入
node_modules
➜react-native-update
➜ios 并选中
RCTPushy.xcodeproj` \n - 在 XCode 中的 project navigator 里,选中你的工程,在
Build Phases
➜Link Binary With Libraries
中添加libRCTPushy.a
、libz.tbd
、libbz2.1.0.tbd
\n - 继续在
Build Settings
里搜索Header Search Path
,添加$(SRCROOT)/../node_modules/react-native-update/ios
,勾选recursive
。 \n - 在
Build Phases
添加一个New Run Script Phase
运行脚本,内容如下 \n - 尝试编译一下,顺利的话就会在
../node_modules/react-native-update/ios/
文件夹下面生成一个pushy_build_time.txt
文件。然后在Copy Bundle Resources
里把生成的pushy_build_time.txt
文件添加进去。 \n - \n
在
\nandroid/settings.gradle
中添加如下代码:\ninclude ':react-native-update'\nproject(':react-native-update').projectDir = new File(rootProject.projectDir, \t'../node_modules/react-native-update/android')
\n - \n
在
\nandroid/app/build.gradle
的 dependencies 部分增加如下代码:\nimplementation project(':react-native-update')
\n - 打开
android/app/src/main/java/[...]/MainApplication.java
, \n - 在文件开头增加
import cn.reactnative.modules.update.UpdatePackage;
\n - \n
在
\ngetPackages()
方法中增加new UpdatePackage()
(注意上一行可能要增加一个逗号) - 安装 \n
- \n\n\n \n
- \n\n\n \n
- 禁用 android 的 crunch 优化 \n
- 登录与创建应用 \n
{expired: true}
:该应用原生包已过期(已从 pushy 服务器中删除),开发者应该在 pushy 控制台添加一个更新下载链接,并自行提示用户下载。 \n{upToDate: true}
:当前已经更新到最新,无需进行更新。 \n{update: true}
:当前有新版本可以更新。info 的name
、description
字段可以用于提示用户,而metaInfo
字段则可以根据你的需求自定义其它属性(如是否静默更新、是否强制更新等等),具体用法可参考场景实践。另外还有几个字段,包含了补丁包的下载地址等。 pushy 会首先尝试耗费流量更少的更新方式。将info
对象传递给downloadUpdate
方法作为参数即可。 \n{expired: true}
:该应用原生包已过期(已从 pushy 服务器中删除),开发者应该在 pushy 控制台添加一个更新下载链接,并自行提示用户下载。 \n{upToDate: true}
:当前已经更新到最新,无需进行更新。 \n{update: true}
:当前有新版本可以更新。info 的name
、description
字段可以用于提示用户,而metaInfo
字段则可以根据你的需求自定义其它属性(如是否静默更新、是否强制更新等等),具体用法可参考场景实践。另外还有几个字段,包含了补丁包的下载地址等。 pushy 会首先尝试耗费流量更少的更新方式。将info
对象传递给downloadUpdate
方法作为参数即可。 \n- Xcode 中运行设备选真机或 Generic iOS Device \n
- 菜单中选择 Product - Archive \n
- Archive 完成后选择
Export
生成.ipa 文件,此时建议取消 bitcode 选项以减少 ipa 大小 \n - 然后运行如下命令上传到 pushy 服务器以供后续版本比对之用 \n
- Xcode 中运行设备选真机或 Generic iOS Device \n
- 菜单中选择 Product - Archive \n
- Archive 完成后选择
Export
生成.ipa 文件,此时建议取消 bitcode 选项以减少 ipa 大小 \n - 然后运行如下命令上传到 pushy 服务器以供后续版本比对之用 \n
发布热更新
最近修改时间2023-09-25 07:17:26配置 Bundle URL
\n注意此步骤无论任何版本,目前都需要手动配置。
\niOS
\n在你的 AppDelegate.mm 或 AppDelegate.m 文件(不同 RN 版本可能后缀名不同)中增加如下代码:
\n\n// ... 其它代码\n#import \"AppDelegate.h\"\n\n#import \"RCTPushy.h\" // <-- import头文件,注意要放到if条件外面\n\n// 可能项目里有一些条件编译语句,例如像较新版本RN自带的flipper\n// #if DEBUG\n// 注意**不要**在这里面引入\"RCTPushy.h\"\n// #import <FlipperKit/FlipperClient.h>\n// ...\n// #endif\n\n\n// 如果RN版本 >= 0.59,修改sourceURLForBridge\n- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge\n{\n#if DEBUG\n // 原先这里的写法继续保留(所以debug模式下不可热更新)\n return .....\n#else\n // 把这里非DEBUG的情况替换为热更新bundle的写法\n return [RCTPushy bundleURL];\n#endif\n}\n\n// 如果RN版本 < 0.59,修改didFinishLaunchingWithOptions\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n#if DEBUG\n // 原来的jsCodeLocation保留在这里(所以debug模式下不可热更新)\n jsCodeLocation = ..........\n#else\n // 把这里非DEBUG的情况替换为热更新bundle的写法\n jsCodeLocation = [RCTPushy bundleURL];\n#endif\n // ... 其它代码\n}
Android
\n在 MainApplication 中增加如下代码(如果是混编原生的项目或其他原因没有使用 ReactApplication,请使用此 api 集成):
\n\n// ... 其它代码\n\n// ↓↓↓请注意不要少了这句import\nimport cn.reactnative.modules.update.UpdateContext;\n// ↑↑↑\n\npublic class MainApplication extends Application implements ReactApplication {\n\n private final ReactNativeHost mReactNativeHost =\n // 老版本 RN 这里可能是 new ReactNativeHost(this)\n new DefaultReactNativeHost(this) {\n\n // ↓↓↓将下面这一段添加到 DefaultReactNativeHost 内部!\n @Override\n protected String getJSBundleFile() {\n return UpdateContext.getBundleUrl(MainApplication.this);\n }\n // ↑↑↑\n\n // ...其他代码\n }\n}
\n
\n请记得,任意在 ios 和 android 目录下的修改,一定要重新编译(npx react-native run-ios 或 run-android 命令编译,或在 Xcode/Android Studio 中重新编译)才能生效。
\n禁用 android 的 crunch 优化
\nandroid 会在生成 apk 时自动对 png 图片进行压缩,此操作既耗时又影响增量补丁的生成。为了保证补丁能正常生成,您需要在
\nandroid/app/build.gradle
中关闭此操作:\n...\nandroid {\n ...\n signingConfigs { ... }\n buildTypes {\n release {\n ...\n // 添加下面这行以禁用crunch\n crunchPngs false\n }\n }\n}\n...
登录与创建应用
\n首先请在https://update.reactnative.cn注册帐号,然后在你的项目根目录下运行以下命令:
\n\n$ pushy login\nemail: <输入你的注册邮箱>\npassword: <输入你的密码>
这会在项目文件夹下创建一个
\n.update
文件,注意不要把这个文件上传到 Git 等 CVS 系统上。你可以在.gitignore
末尾增加一行.update
来忽略这个文件。登录之后可以创建应用。注意 iOS 平台和安卓平台需要分别创建:
\n\n$ pushy createApp --platform ios\nApp Name: <输入应用名字>\n$ pushy createApp --platform android\nApp Name: <输入应用名字>
\n
\n两次输入的名字可以相同,这没有关系。
\n如果你已经在网页端或者其它地方创建过应用,也可以直接选择应用:
\n\n$ pushy selectApp --platform ios\n1) 鱼多多(ios)\n2) 招财旺(ios)\n\nTotal 2 ios apps\nEnter appId: <输入应用前面的编号>
选择或者创建过应用后,你将可以在文件夹下看到
\nupdate.json
文件,其内容类似如下形式:\n{\n \"ios\": {\n \"appId\": 1,\n \"appKey\": \"<一串随机字符串>\"\n },\n \"android\": {\n \"appId\": 2,\n \"appKey\": \"<一串随机字符串>\"\n }\n}
你可以安全的把
\nupdate.json
上传到 Git 等 CVS 系统上,与你的团队共享这个文件,它不包含任何敏感信息。当然,他们在使用任何功能之前,都必须首先输入pushy login
进行登录。至此应用的创建/选择就已经成功了。下一步,你需要给代码添加相应的功能,请参阅代码集成。
","tableOfContents":"- \n
首先你应该有一个基于 React Native 开发的应用,我们把具有 package.json 的目录叫做你的\"应用根目录\"。
\n如果你还没有初始化应用,请参阅开始使用 React Native。
\n所以我们也假设你已经拥有了开发 React Native 应用的一切环境,包括
\nNode.js
、XCode
、Android SDK
等等。安装
\n在你的项目根目录下运行以下命令:
\n\n# 先全局安装命令行工具,每台电脑只用装一次\nnpm i -g react-native-update-cli\n\n# 然后在项目目录中安装热更新模块\n# 0.71 及以上版本使用最新版本如下\nnpm i react-native-update\n\n# 0.71 以下版本请使用8.x版本\n# npm i react-native-update@8.x
\n
\n如果下载极慢或者显示网络失败,请设置使用淘宝镜像
\nnpx nrm use taobao
\n
\n注意请不要混用
\nnpm/yarn/pnpm
等包管理器及对应的lock
文件,团队成员请坚持使用同一包管理器,且仅保留统一格式的lock
文件如果你的 RN 版本 >= 0.60,请在 ios 目录下执行:
\n\npod install
如果你的 RN 版本 < 0.60,那么需要先在
\npackage.json
文件的scripts
中加入:\n\"postinstall\": \"npx jetify -r\"
然后按照手动 link的说明操作。
\n\n
\n注意:如果是混编 RN 项目,由于目前官方集成文档并不完善,参照官方文档可能无法实现自动 link 功能。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link 操作。
\n\n\n\n如果你的RN版本比较老(< 0.46),请点击这里的注意事项\n
\n如果你的 RN 版本比较老,请按下面表格尝试老一些的版本(但这些版本我们已不再维护,不能保证可以使用):
\n\n\n
\n\n \n\n\nReact Native 版本 \nreact-native-update 版本 \n\n \n0.26 及以下 \n1.0.x \n\n \n0.27 - 0.28 \n2.x \n\n \n0.29 - 0.33 \n3.x \n\n \n0.34 - 0.45 \n4.x \n\n \n\n0.46 - 0.70 \n8.x \n安装命令示例:
\n\nnpm i react-native-update@4.x
如果 RN 的版本是 0.45 及以下,你还必须安装Android NDK,版本最好选用 r10e,并设置环境变量
\nANDROID_NDK_HOME
,指向你的 NDK 根目录(例如/Users/tdzl2003/Downloads/android-ndk-r10e
)。\n
\n请记得,任意在 ios 和 android 目录下的修改,一定要重新编译(npx react-native run-ios 或 run-android 命令编译,或在 Xcode/Android Studio 中重新编译)才能生效。
\n手动 link
\n如果 RN 版本 >= 0.60 则不需要此手动 link 步骤。
\n\n
\n注意:如果是混编 RN 项目,由于目前官方集成文档并不完善,参照官方文档可能无法实现自动 link 功能。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link 操作。
\niOS
\n\n\nRN < 0.60且使用CocoaPods(推荐)
\n- \n
\npod 'react-native-update', path: '../node_modules/react-native-update'
- \n
\n\nRN < 0.60且不使用CocoaPods
\n- \n
\n#!/bin/bash\nset -x\nDEST="../node_modules/react-native-update/ios/"\ndate +%s > "$DEST/pushy_build_time.txt"
- \n
Android
\n\n\n\n\nRN < 0.60
\n- \n
配置 Bundle URL
\n注意此步骤无论任何版本,目前都需要手动配置。
\niOS
\n在你的 AppDelegate.mm 或 AppDelegate.m 文件(不同 RN 版本可能后缀名不同)中增加如下代码:
\n\n// ... 其它代码\n#import \"AppDelegate.h\"\n\n#import \"RCTPushy.h\" // <-- import头文件,注意要放到if条件外面\n\n// 可能项目里有一些条件编译语句,例如像较新版本RN自带的flipper\n// #if DEBUG\n// 注意**不要**在这里面引入\"RCTPushy.h\"\n// #import <FlipperKit/FlipperClient.h>\n// ...\n// #endif\n\n\n// 如果RN版本 >= 0.59,修改sourceURLForBridge\n- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge\n{\n#if DEBUG\n // 原先这里的写法继续保留(所以debug模式下不可热更新)\n return .....\n#else\n // 把这里非DEBUG的情况替换为热更新bundle的写法\n return [RCTPushy bundleURL];\n#endif\n}\n\n// 如果RN版本 < 0.59,修改didFinishLaunchingWithOptions\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n#if DEBUG\n // 原来的jsCodeLocation保留在这里(所以debug模式下不可热更新)\n jsCodeLocation = ..........\n#else\n // 把这里非DEBUG的情况替换为热更新bundle的写法\n jsCodeLocation = [RCTPushy bundleURL];\n#endif\n // ... 其它代码\n}
Android
\n在 MainApplication 中增加如下代码(如果是混编原生的项目或其他原因没有使用 ReactApplication,请使用此 api 集成):
\n\n// ... 其它代码\n\n// ↓↓↓请注意不要少了这句import\nimport cn.reactnative.modules.update.UpdateContext;\n// ↑↑↑\n\npublic class MainApplication extends Application implements ReactApplication {\n\n private final ReactNativeHost mReactNativeHost =\n // 老版本 RN 这里可能是 new ReactNativeHost(this)\n new DefaultReactNativeHost(this) {\n\n // ↓↓↓将下面这一段添加到 DefaultReactNativeHost 内部!\n @Override\n protected String getJSBundleFile() {\n return UpdateContext.getBundleUrl(MainApplication.this);\n }\n // ↑↑↑\n\n // ...其他代码\n }\n}
\n
\n请记得,任意在 ios 和 android 目录下的修改,一定要重新编译(npx react-native run-ios 或 run-android 命令编译,或在 Xcode/Android Studio 中重新编译)才能生效。
\n禁用 android 的 crunch 优化
\nandroid 会在生成 apk 时自动对 png 图片进行压缩,此操作既耗时又影响增量补丁的生成。为了保证补丁能正常生成,您需要在
\nandroid/app/build.gradle
中关闭此操作:\n...\nandroid {\n ...\n signingConfigs { ... }\n buildTypes {\n release {\n ...\n // 添加下面这行以禁用crunch\n crunchPngs false\n }\n }\n}\n...
登录与创建应用
\n首先请在https://update.reactnative.cn注册帐号,然后在你的项目根目录下运行以下命令:
\n\n$ pushy login\nemail: <输入你的注册邮箱>\npassword: <输入你的密码>
这会在项目文件夹下创建一个
\n.update
文件,注意不要把这个文件上传到 Git 等 CVS 系统上。你可以在.gitignore
末尾增加一行.update
来忽略这个文件。登录之后可以创建应用。注意 iOS 平台和安卓平台需要分别创建:
\n\n$ pushy createApp --platform ios\nApp Name: <输入应用名字>\n$ pushy createApp --platform android\nApp Name: <输入应用名字>
\n
\n两次输入的名字可以相同,这没有关系。
\n如果你已经在网页端或者其它地方创建过应用,也可以直接选择应用:
\n\n$ pushy selectApp --platform ios\n1) 鱼多多(ios)\n2) 招财旺(ios)\n\nTotal 2 ios apps\nEnter appId: <输入应用前面的编号>
选择或者创建过应用后,你将可以在文件夹下看到
\nupdate.json
文件,其内容类似如下形式:\n{\n \"ios\": {\n \"appId\": 1,\n \"appKey\": \"<一串随机字符串>\"\n },\n \"android\": {\n \"appId\": 2,\n \"appKey\": \"<一串随机字符串>\"\n }\n}
你可以安全的把
\nupdate.json
上传到 Git 等 CVS 系统上,与你的团队共享这个文件,它不包含任何敏感信息。当然,他们在使用任何功能之前,都必须首先输入pushy login
进行登录。至此应用的创建/选择就已经成功了。下一步,你需要给代码添加相应的功能,请参阅代码集成。
","tableOfContents":"- \n
安装配置完成后,确定应用编译顺利通过,下面我们来进行代码集成。
\n极简快速集成
\n我们从 v8.x 版本开始提供极简的三行式集成(老版本只能使用自定义集成方式):
\n\nimport { simpleUpdate } from 'react-native-update';\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];\n\n// 整个应用的根组件,class 或函数组件都可以\nclass App extends Component {\n // 这是个空的示例,请替换为你自己的根组件\n}\n\n// 对根组件使用simpleUpdate方法封装后导出\nexport default simpleUpdate(App, { appKey });
此方式默认在 App 启动,以及从后台切换到前台时触发更新检查,弹出提示的内容也固定。如需自定义触发时机,以及修改界面提示等,请参考下面的自定义集成方式。
\n自定义集成
\n获取 appKey
\n检查更新时必须提供你的
\nappKey
,这个值保存在update.json
中,并且根据平台不同而不同。你可以用如下的代码获取:\nimport { Platform } from 'react-native';\n\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];
如果你不使用 pushy 命令行,也可以从网页端查看到两个应用 appKey,并根据平台的不同来选择。
\n检查更新、下载更新
\n异步函数
\ncheckUpdate
可以检查当前版本是否需要更新:\nconst info = await checkUpdate(appKey);
返回的
\ninfo
有三种情况:- \n
\nconst hash = await downloadUpdate(\n info,\n // 下载回调为可选参数,从v5.8.3版本开始加入\n {\n onDownloadProgress: ({ received, total }) => {\n // 已下载的字节数, 总字节数\n console.log(received, total);\n },\n },\n);
\ndownloadUpdate
方法从v5.8.3
版本开始新增接受第二个可选参数,为下载进度的回调函数(onDownloadProgress
)。可根据回调参数自行设计进度的展示。切换版本
\n
\ndownloadUpdate
的返回值是一个 hash 字符串,它是当前热更新版本的唯一标识。你可以使用
\nswitchVersion(hash)
函数立即切换版本(此时应用会立即重新加载),或者选择调用switchVersionLater(hash)
,让应用在下一次启动的时候再加载新的版本。首次启动、回滚
\n在每次更新完毕后的首次启动时,
\nisFirstTime
常量会为true
。你必须在应用退出前合适的任何时机,调用markSuccess
,否则应用下一次启动的时候将会进行回滚操作。这一机制称作“反触发”,这样当你应用启动初期即遭遇问题的时候,也能在下一次启动时恢复运作。你可以通过
\nisFirstTime
来获知这是当前版本的首次启动,也可以通过isRolledBack
来获知应用刚刚经历了一次回滚操作。你可以在此时给予用户合理的提示。以上提及的所有 api 的说明文档可在这里查看。
\n完整的示例
\n\nimport React, { Component } from 'react';\n\nimport { StyleSheet, Platform, Text, View, Alert, TouchableOpacity, Linking } from 'react-native';\n\nimport {\n isFirstTime,\n isRolledBack,\n packageVersion,\n currentVersion,\n checkUpdate,\n downloadUpdate,\n switchVersion,\n switchVersionLater,\n markSuccess,\n downloadAndInstallApk,\n} from 'react-native-update';\n\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];\n\nexport default class MyProject extends Component {\n state = {\n received: 0,\n total: 0,\n };\n componentDidMount() {\n if (isFirstTime) {\n // 必须调用此更新成功标记方法\n // 否则默认更新失败,下一次启动会自动回滚\n markSuccess();\n console.log('更新完成');\n } else if (isRolledBack) {\n console.log('刚刚更新失败了,版本被回滚.');\n }\n }\n doUpdate = async (info) => {\n try {\n const hash = await downloadUpdate(info, {\n onDownloadProgress: ({ received, total }) => {\n this.setState({\n received,\n total,\n });\n },\n });\n if (!hash) {\n return;\n }\n Alert.alert('提示', '下载完毕,是否重启应用?', [\n {\n text: '是',\n onPress: () => {\n switchVersion(hash);\n },\n },\n { text: '否' },\n {\n text: '下次启动时',\n onPress: () => {\n switchVersionLater(hash);\n },\n },\n ]);\n } catch (err) {\n Alert.alert('更新失败', err.message);\n }\n };\n checkUpdate = async () => {\n if (__DEV__) {\n // 开发模式不支持热更新,跳过检查\n return;\n }\n let info;\n try {\n info = await checkUpdate(appKey);\n } catch (err) {\n Alert.alert('更新检查失败', err.message);\n return;\n }\n if (info.expired) {\n Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [\n {\n text: '确定',\n onPress: () => {\n if (info.downloadUrl) {\n // apk可直接下载安装\n if (Platform.OS === 'android' && info.downloadUrl.endsWith('.apk')) {\n downloadAndInstallApk({\n url: info.downloadUrl,\n onDownloadProgress: ({ received, total }) => {\n this.setState({\n received,\n total,\n });\n },\n });\n } else {\n Linking.openURL(info.downloadUrl);\n }\n }\n },\n },\n ]);\n } else if (info.upToDate) {\n Alert.alert('提示', '您的应用版本已是最新.');\n } else {\n Alert.alert('提示', '检查到新的版本' + info.name + ',是否下载?\\n' + info.description, [\n {\n text: '是',\n onPress: () => {\n this.doUpdate(info);\n },\n },\n { text: '否' },\n ]);\n }\n };\n render() {\n const { received, total } = this.state;\n return (\n <View style={styles.container}>\n <Text style={styles.welcome}>欢迎使用热更新服务</Text>\n <Text style={styles.instructions}>\n 这是版本一 {'\\n'}\n 当前原生包版本号: {packageVersion}\n {'\\n'}\n 当前热更新版本Hash: {currentVersion || '(空)'}\n {'\\n'}\n </Text>\n <Text>\n 下载进度:{received} / {total}\n </Text>\n <TouchableOpacity onPress={this.checkUpdate}>\n <Text style={styles.instructions}>点击这里检查更新</Text>\n </TouchableOpacity>\n </View>\n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: '#F5FCFF',\n },\n welcome: {\n fontSize: 20,\n textAlign: 'center',\n margin: 10,\n },\n instructions: {\n textAlign: 'center',\n color: '#333333',\n marginBottom: 5,\n },\n});
现在,你的应用已经可以通过 pushy 服务检查版本并进行更新了。下一步,你可以开始尝试发布应用包和版本,请参阅发布热更新。
","tableOfContents":"","frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"path":"/docs/integration.md","slug":"/docs/integration","modifiedTime":1695093374415}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"常见问题","order":23,"type":"其他"},"fields":{"slug":"/docs/faq","path":"/docs/faq.md"}}},{"node":{"frontmatter":{"title":"更新日志","order":22,"type":"其他"},"fields":{"slug":"/docs/changelog","path":"/docs/changelog.md"}}},{"node":{"frontmatter":{"title":"场景实践","order":13,"type":"开发指南"},"fields":{"slug":"/docs/bestpractice","path":"/docs/bestpractice.md"}}},{"node":{"frontmatter":{"title":"命令行工具","order":12,"type":"开发指南"},"fields":{"slug":"/docs/cli","path":"/docs/cli.md"}}},{"node":{"frontmatter":{"title":"API参考","order":11,"type":"开发指南"},"fields":{"slug":"/docs/api","path":"/docs/api.md"}}},{"node":{"frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"slug":"/docs/publish","path":"/docs/publish.md"}}},{"node":{"frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"slug":"/docs/integration","path":"/docs/integration.md"}}},{"node":{"frontmatter":{"title":"安装配置","order":0,"type":"快速入门"},"fields":{"slug":"/docs/getting-started","path":"/docs/getting-started.md"}}}]}},"pageContext":{"slug":"/docs/integration","type":"/docs/"}},"staticQueryHashes":[]} \ No newline at end of file +{"componentChunkName":"component---src-templates-docs-tsx","path":"/docs/integration.html","result":{"data":{"markdownRemark":{"html":"安装配置完成后,确定应用编译顺利通过,下面我们来进行代码集成。
\n极简快速集成
\n我们从 v8.x 版本开始提供极简的三行式集成(老版本只能使用自定义集成方式):
\n\nimport { simpleUpdate } from 'react-native-update';\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];\n\n// 整个应用的根组件,class 或函数组件都可以\nclass App extends Component {\n // 这是个空的示例,请替换为你自己的根组件\n}\n\n// 对根组件使用simpleUpdate方法封装后导出\nexport default simpleUpdate(App, { appKey });
此方式默认在 App 启动,以及从后台切换到前台时触发更新检查,弹出提示的内容也固定。如需自定义触发时机,以及修改界面提示等,请参考下面的自定义集成方式。
\n自定义集成
\n获取 appKey
\n检查更新时必须提供你的
\nappKey
,这个值保存在update.json
中,并且根据平台不同而不同。你可以用如下的代码获取:\nimport { Platform } from 'react-native';\n\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];
如果你不使用 pushy 命令行,也可以从网页端查看到两个应用 appKey,并根据平台的不同来选择。
\n检查更新、下载更新
\n异步函数
\ncheckUpdate
可以检查当前版本是否需要更新:\nconst info = await checkUpdate(appKey);
返回的
\ninfo
有三种情况:- \n
\nconst hash = await downloadUpdate(\n info,\n // 下载回调为可选参数,从v5.8.3版本开始加入\n {\n onDownloadProgress: ({ received, total }) => {\n // 已下载的字节数, 总字节数\n console.log(received, total);\n },\n },\n);
\ndownloadUpdate
方法从v5.8.3
版本开始新增接受第二个可选参数,为下载进度的回调函数(onDownloadProgress
)。可根据回调参数自行设计进度的展示。切换版本
\n
\ndownloadUpdate
的返回值是一个 hash 字符串,它是当前热更新版本的唯一标识。你可以使用
\nswitchVersion(hash)
函数立即切换版本(此时应用会立即重新加载),或者选择调用switchVersionLater(hash)
,让应用在下一次启动的时候再加载新的版本。首次启动、回滚
\n在每次更新完毕后的首次启动时,
\nisFirstTime
常量会为true
。你必须在应用退出前合适的任何时机,调用markSuccess
,否则应用下一次启动的时候将会进行回滚操作。这一机制称作“反触发”,这样当你应用启动初期即遭遇问题的时候,也能在下一次启动时恢复运作。你可以通过
\nisFirstTime
来获知这是当前版本的首次启动,也可以通过isRolledBack
来获知应用刚刚经历了一次回滚操作。你可以在此时给予用户合理的提示。以上提及的所有 api 的说明文档可在这里查看。
\n完整的示例
\n\nimport React, { Component } from 'react';\n\nimport { StyleSheet, Platform, Text, View, Alert, TouchableOpacity, Linking } from 'react-native';\n\nimport {\n isFirstTime,\n isRolledBack,\n packageVersion,\n currentVersion,\n checkUpdate,\n downloadUpdate,\n switchVersion,\n switchVersionLater,\n markSuccess,\n downloadAndInstallApk,\n} from 'react-native-update';\n\nimport _updateConfig from './update.json';\nconst { appKey } = _updateConfig[Platform.OS];\n\nexport default class MyProject extends Component {\n state = {\n received: 0,\n total: 0,\n };\n componentDidMount() {\n if (isFirstTime) {\n // 必须调用此更新成功标记方法\n // 否则默认更新失败,下一次启动会自动回滚\n markSuccess();\n console.log('更新完成');\n } else if (isRolledBack) {\n console.log('刚刚更新失败了,版本被回滚.');\n }\n }\n doUpdate = async (info) => {\n try {\n const hash = await downloadUpdate(info, {\n onDownloadProgress: ({ received, total }) => {\n this.setState({\n received,\n total,\n });\n },\n });\n if (!hash) {\n return;\n }\n Alert.alert('提示', '下载完毕,是否重启应用?', [\n {\n text: '是',\n onPress: () => {\n switchVersion(hash);\n },\n },\n { text: '否' },\n {\n text: '下次启动时',\n onPress: () => {\n switchVersionLater(hash);\n },\n },\n ]);\n } catch (err) {\n Alert.alert('更新失败', err.message);\n }\n };\n checkUpdate = async () => {\n if (__DEV__) {\n // 开发模式不支持热更新,跳过检查\n return;\n }\n let info;\n try {\n info = await checkUpdate(appKey);\n } catch (err) {\n Alert.alert('更新检查失败', err.message);\n return;\n }\n if (info.expired) {\n Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [\n {\n text: '确定',\n onPress: () => {\n if (info.downloadUrl) {\n // apk可直接下载安装\n if (Platform.OS === 'android' && info.downloadUrl.endsWith('.apk')) {\n downloadAndInstallApk({\n url: info.downloadUrl,\n onDownloadProgress: ({ received, total }) => {\n this.setState({\n received,\n total,\n });\n },\n });\n } else {\n Linking.openURL(info.downloadUrl);\n }\n }\n },\n },\n ]);\n } else if (info.upToDate) {\n Alert.alert('提示', '您的应用版本已是最新.');\n } else {\n Alert.alert('提示', '检查到新的版本' + info.name + ',是否下载?\\n' + info.description, [\n {\n text: '是',\n onPress: () => {\n this.doUpdate(info);\n },\n },\n { text: '否' },\n ]);\n }\n };\n render() {\n const { received, total } = this.state;\n return (\n <View style={styles.container}>\n <Text style={styles.welcome}>欢迎使用热更新服务</Text>\n <Text style={styles.instructions}>\n 这是版本一 {'\\n'}\n 当前原生包版本号: {packageVersion}\n {'\\n'}\n 当前热更新版本Hash: {currentVersion || '(空)'}\n {'\\n'}\n </Text>\n <Text>\n 下载进度:{received} / {total}\n </Text>\n <TouchableOpacity onPress={this.checkUpdate}>\n <Text style={styles.instructions}>点击这里检查更新</Text>\n </TouchableOpacity>\n </View>\n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: '#F5FCFF',\n },\n welcome: {\n fontSize: 20,\n textAlign: 'center',\n margin: 10,\n },\n instructions: {\n textAlign: 'center',\n color: '#333333',\n marginBottom: 5,\n },\n});
现在,你的应用已经可以通过 pushy 服务检查版本并进行更新了。下一步,你可以开始尝试发布应用包和版本,请参阅发布热更新。
","tableOfContents":"","frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"path":"/docs/integration.md","slug":"/docs/integration","modifiedTime":1695626244266}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"常见问题","order":23,"type":"其他"},"fields":{"slug":"/docs/faq","path":"/docs/faq.md"}}},{"node":{"frontmatter":{"title":"更新日志","order":22,"type":"其他"},"fields":{"slug":"/docs/changelog","path":"/docs/changelog.md"}}},{"node":{"frontmatter":{"title":"场景实践","order":13,"type":"开发指南"},"fields":{"slug":"/docs/bestpractice","path":"/docs/bestpractice.md"}}},{"node":{"frontmatter":{"title":"命令行工具","order":12,"type":"开发指南"},"fields":{"slug":"/docs/cli","path":"/docs/cli.md"}}},{"node":{"frontmatter":{"title":"API参考","order":11,"type":"开发指南"},"fields":{"slug":"/docs/api","path":"/docs/api.md"}}},{"node":{"frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"slug":"/docs/publish","path":"/docs/publish.md"}}},{"node":{"frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"slug":"/docs/integration","path":"/docs/integration.md"}}},{"node":{"frontmatter":{"title":"安装配置","order":0,"type":"快速入门"},"fields":{"slug":"/docs/getting-started","path":"/docs/getting-started.md"}}}]}},"pageContext":{"slug":"/docs/integration","type":"/docs/"}},"staticQueryHashes":[]} \ No newline at end of file diff --git a/page-data/docs/publish.html/page-data.json b/page-data/docs/publish.html/page-data.json index 5d54b6b..8693728 100644 --- a/page-data/docs/publish.html/page-data.json +++ b/page-data/docs/publish.html/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-templates-docs-tsx","path":"/docs/publish.html","result":{"data":{"markdownRemark":{"html":"现在你的应用已经具备了检测更新的功能,下面我们来尝试发布并更新它。流程可参考下图:
\n\n \n \n \n \n
\n一般来说我们需要先发布原生基准版本,然后在基准版本之上迭代业务逻辑,发布热更新版本。如果迭代过程中有原生方面的修改,则需要发布新的基准版本。可以只保留一个原生基准版本,也可以多版本同时维护。
\n发布原生基准版本
\niOS
\n首先参考文档-在设备上运行,确定你正在使用离线包。然后点击菜单。
\n按照正常的发布流程打包
\n.ipa
文件:- \n
\n$ pushy uploadIpa <ipa后缀文件>
此 ipa 的
\nCFBundleShortVersionString
字段(位于ios/项目名/Info.plist
中)会被记录为原生版本号packageVersion
。随后你可以选择往 AppStore 上传这个版本(可以重新 export 并调整相关选项,但请不要重新 archive),也可以先通过Test flight或蒲公英等渠道进行真机安装测试。请注意:暂不支持通过 Xcode 直接进行热更新测试。
\n如果后续需要再次 archive 打包(例如修改原生代码或配置),请先更改版本号,并在打包完成后再次
\nuploadIpa
到服务器端记录,否则后续生成的相同版本的原生包会由于编译时间戳不一致而无法获取热更新
。\n
\n注意:如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\nAndroid
\n首先参考文档-打包 APK设置签名,然后在 android 文件夹下运行
\n./gradlew assembleRelease
或./gradlew aR
,你就可以在android/app/build/outputs/apk/release/app-release.apk
中找到你的应用包。\n
\n如果你需要使用 aab 格式(android app bundle,google 市场专用)的包,请参考这里的做法将其转换为 apk 格式后再操作。
\n然后运行如下命令
\n\n$ pushy uploadApk android/app/build/outputs/apk/release/app-release.apk
即可上传 apk 以供后续版本比对之用。此 apk 的
\nversionName
字段(位于android/app/build.gralde
中)会被记录为原生版本号packageVersion
。随后你可以选择往应用市场发布这个版本,也可以先往设备上直接安装这个 apk 文件以进行测试。
\n如果后续需要再次打包(例如修改原生代码或配置),请先更改版本号,并再次
\nuploadApk
到服务器端记录,否则后续生成的相同版本的原生包会由于编译时间戳不一致而无法获取热更新
。\n
\n注意:如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\n发布热更新版本
\n你可以尝试修改一行代码(譬如将版本一修改为版本二),然后使用
\npushy bundle --platform <ios|android>
命令来生成新的热更新版本。\n$ pushy bundle --platform android\nBundling with React Native version: 0.22.2\n<各种进度输出>\nBundled saved to: build/output/android.1459850548545.ppk\nWould you like to publish it?(Y/N)
如果想要立即上传,此时输入 Y。当然,你也可以在将来使用
\npushy publish --platform android build/output/android.1459850548545.ppk
来上传刚才打包好的热更新包。\nUploading [========================================================] 100% 0.0s\nEnter version name: <输入热更新版本名字,如1.0.0-rc>\nEnter description: <输入热更新版本描述>\nEnter meta info: {"ok":1}\nOk.\nWould you like to bind packages to this version?(Y/N)
此时版本已经提交到 pushy 服务,但用户暂时看不到此更新,你需要先将特定的原生包版本绑定到此热更新版本上。
\n此时输入 Y 立即绑定,你也可以在将来使用
\npushy update --platform <ios|android>
来对已上传的热更包和原生包进行绑定。除此以外,你还可以在网页端操作,简单的将对应的原生包版本拖到需要的热更新版本下即可。\n┌────────────┬──────────────────────────────────────┐\n│ Package Id │ Version │\n├────────────┼──────────────────────────────────────┤\n│ 46272 │ 2.0(normal) │\n├────────────┼──────────────────────────────────────┤\n│ 45577 │ 1.0(normal) │\n└────────────┴──────────────────────────────────────┘\n共 2 个包\n输入原生包 id: 46272
版本绑定完毕后,服务器会在几秒内生成差量补丁,客户端就可以获取到更新了。
\n后续要继续发布新的热更新,只需反复执行
\npushy bundle
命令即可。恭喜你,至此为止,你已经完成了植入代码热更新的全部工作。
\n测试、发布与回滚
\n我们强烈建议您先发布一个测试包,再发布一个除了版本号以外均完全相同的正式包。
\n例如,假设我们有一个正式包,版本为
\n1.6.0
,那么可以修改版本号重新打包一个1001.6.0
,以一个明显不太正常的版本号来标识它是一个测试版本,同时后几位相同,可以表明它和某个正式版本存在关联(内容/依赖一致)。在每次往发布包发起热更新之前,先对测试包
\n1001.6.0
进行更新操作,基本测试通过之后,再在网页后台上将热更包重新绑定到正式包1.6.0
上。如果在测试包中发现了重大问题,你就可以先进行修复,更新测试确认通过后再部署到正式线上环境。这样,可以最大程度的避免发生线上事故。万一确实发生线上事故需要回滚的话,首先利用版本控制系统回滚代码到正常的状态,然后重新生成热更包并推送即可。
","tableOfContents":"","frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"path":"/docs/publish.md","slug":"/docs/publish","modifiedTime":1695093374415}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"常见问题","order":23,"type":"其他"},"fields":{"slug":"/docs/faq","path":"/docs/faq.md"}}},{"node":{"frontmatter":{"title":"更新日志","order":22,"type":"其他"},"fields":{"slug":"/docs/changelog","path":"/docs/changelog.md"}}},{"node":{"frontmatter":{"title":"场景实践","order":13,"type":"开发指南"},"fields":{"slug":"/docs/bestpractice","path":"/docs/bestpractice.md"}}},{"node":{"frontmatter":{"title":"命令行工具","order":12,"type":"开发指南"},"fields":{"slug":"/docs/cli","path":"/docs/cli.md"}}},{"node":{"frontmatter":{"title":"API参考","order":11,"type":"开发指南"},"fields":{"slug":"/docs/api","path":"/docs/api.md"}}},{"node":{"frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"slug":"/docs/publish","path":"/docs/publish.md"}}},{"node":{"frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"slug":"/docs/integration","path":"/docs/integration.md"}}},{"node":{"frontmatter":{"title":"安装配置","order":0,"type":"快速入门"},"fields":{"slug":"/docs/getting-started","path":"/docs/getting-started.md"}}}]}},"pageContext":{"slug":"/docs/publish","type":"/docs/"}},"staticQueryHashes":[]} \ No newline at end of file +{"componentChunkName":"component---src-templates-docs-tsx","path":"/docs/publish.html","result":{"data":{"markdownRemark":{"html":"现在你的应用已经具备了检测更新的功能,下面我们来尝试发布并更新它。流程可参考下图:
\n\n \n \n \n \n
\n一般来说我们需要先发布原生基准版本,然后在基准版本之上迭代业务逻辑,发布热更新版本。如果迭代过程中有原生方面的修改,则需要发布新的基准版本。可以只保留一个原生基准版本,也可以多版本同时维护。
\n发布原生基准版本
\niOS
\n首先参考文档-在设备上运行,确定你正在使用离线包。然后点击菜单。
\n按照正常的发布流程打包
\n.ipa
文件:- \n
\n$ pushy uploadIpa <ipa后缀文件>
此 ipa 的
\nCFBundleShortVersionString
字段(位于ios/项目名/Info.plist
中)会被记录为原生版本号packageVersion
。随后你可以选择往 AppStore 上传这个版本(可以重新 export 并调整相关选项,但请不要重新 archive),也可以先通过Test flight或蒲公英等渠道进行真机安装测试。请注意:暂不支持通过 Xcode 直接进行热更新测试。
\n如果后续需要再次 archive 打包(例如修改原生代码或配置),请先更改版本号,并在打包完成后再次
\nuploadIpa
到服务器端记录,否则后续生成的相同版本的原生包会由于编译时间戳不一致而无法获取热更新
。\n
\n注意:如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\nAndroid
\n首先参考文档-打包 APK设置签名,然后在 android 文件夹下运行
\n./gradlew assembleRelease
或./gradlew aR
,你就可以在android/app/build/outputs/apk/release/app-release.apk
中找到你的应用包。\n
\n如果你需要使用 aab 格式(android app bundle,google 市场专用)的包,请参考这里的做法将其转换为 apk 格式后再操作。
\n然后运行如下命令
\n\n$ pushy uploadApk android/app/build/outputs/apk/release/app-release.apk
即可上传 apk 以供后续版本比对之用。此 apk 的
\nversionName
字段(位于android/app/build.gralde
中)会被记录为原生版本号packageVersion
。随后你可以选择往应用市场发布这个版本,也可以先往设备上直接安装这个 apk 文件以进行测试。
\n如果后续需要再次打包(例如修改原生代码或配置),请先更改版本号,并再次
\nuploadApk
到服务器端记录,否则后续生成的相同版本的原生包会由于编译时间戳不一致而无法获取热更新
。\n
\n注意:如果你在上传之前就运行了新的原生版本,由于服务器端没有记录,会暂停其更新数小时。可删除原先安装的 app 再重新安装以清空暂停设置。在上传之后安装的客户端不会受此影响。
\n发布热更新版本
\n你可以尝试修改一行代码(譬如将版本一修改为版本二),然后使用
\npushy bundle --platform <ios|android>
命令来生成新的热更新版本。\n$ pushy bundle --platform android\nBundling with React Native version: 0.22.2\n<各种进度输出>\nBundled saved to: build/output/android.1459850548545.ppk\nWould you like to publish it?(Y/N)
如果想要立即上传,此时输入 Y。当然,你也可以在将来使用
\npushy publish --platform android build/output/android.1459850548545.ppk
来上传刚才打包好的热更新包。\nUploading [========================================================] 100% 0.0s\nEnter version name: <输入热更新版本名字,如1.0.0-rc>\nEnter description: <输入热更新版本描述>\nEnter meta info: {"ok":1}\nOk.\nWould you like to bind packages to this version?(Y/N)
此时版本已经提交到 pushy 服务,但用户暂时看不到此更新,你需要先将特定的原生包版本绑定到此热更新版本上。
\n此时输入 Y 立即绑定,你也可以在将来使用
\npushy update --platform <ios|android>
来对已上传的热更包和原生包进行绑定。除此以外,你还可以在网页端操作,简单的将对应的原生包版本拖到需要的热更新版本下即可。\n┌────────────┬──────────────────────────────────────┐\n│ Package Id │ Version │\n├────────────┼──────────────────────────────────────┤\n│ 46272 │ 2.0(normal) │\n├────────────┼──────────────────────────────────────┤\n│ 45577 │ 1.0(normal) │\n└────────────┴──────────────────────────────────────┘\n共 2 个包\n输入原生包 id: 46272
版本绑定完毕后,服务器会在几秒内生成差量补丁,客户端就可以获取到更新了。
\n后续要继续发布新的热更新,只需反复执行
\npushy bundle
命令即可。恭喜你,至此为止,你已经完成了植入代码热更新的全部工作。
\n测试、发布与回滚
\n我们强烈建议您先发布一个测试包,再发布一个除了版本号以外均完全相同的正式包。
\n例如,假设我们有一个正式包,版本为
\n1.6.0
,那么可以修改版本号重新打包一个1001.6.0
,以一个明显不太正常的版本号来标识它是一个测试版本,同时后几位相同,可以表明它和某个正式版本存在关联(内容/依赖一致)。在每次往发布包发起热更新之前,先对测试包
\n1001.6.0
进行更新操作,基本测试通过之后,再在网页后台上将热更包重新绑定到正式包1.6.0
上。如果在测试包中发现了重大问题,你就可以先进行修复,更新测试确认通过后再部署到正式线上环境。这样,可以最大程度的避免发生线上事故。万一确实发生线上事故需要回滚的话,首先利用版本控制系统回滚代码到正常的状态,然后重新生成热更包并推送即可。
","tableOfContents":"","frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"path":"/docs/publish.md","slug":"/docs/publish","modifiedTime":1695626244266}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"常见问题","order":23,"type":"其他"},"fields":{"slug":"/docs/faq","path":"/docs/faq.md"}}},{"node":{"frontmatter":{"title":"更新日志","order":22,"type":"其他"},"fields":{"slug":"/docs/changelog","path":"/docs/changelog.md"}}},{"node":{"frontmatter":{"title":"场景实践","order":13,"type":"开发指南"},"fields":{"slug":"/docs/bestpractice","path":"/docs/bestpractice.md"}}},{"node":{"frontmatter":{"title":"命令行工具","order":12,"type":"开发指南"},"fields":{"slug":"/docs/cli","path":"/docs/cli.md"}}},{"node":{"frontmatter":{"title":"API参考","order":11,"type":"开发指南"},"fields":{"slug":"/docs/api","path":"/docs/api.md"}}},{"node":{"frontmatter":{"title":"发布热更新","order":2,"type":"快速入门"},"fields":{"slug":"/docs/publish","path":"/docs/publish.md"}}},{"node":{"frontmatter":{"title":"代码集成","order":1,"type":"快速入门"},"fields":{"slug":"/docs/integration","path":"/docs/integration.md"}}},{"node":{"frontmatter":{"title":"安装配置","order":0,"type":"快速入门"},"fields":{"slug":"/docs/getting-started","path":"/docs/getting-started.md"}}}]}},"pageContext":{"slug":"/docs/publish","type":"/docs/"}},"staticQueryHashes":[]} \ No newline at end of file -
代码集成
最近修改时间2023-09-25 07:17:26
安装配置
最近修改时间2023-09-19 03:16:41-
+
安装配置
最近修改时间2023-09-25 07:17:26
常见问题
最近修改时间2023-09-25 07:17:26 -
更新日志
最近修改时间2023-09-19 03:16:41-
+
更新日志
最近修改时间2023-09-25 07:17:26命令行工具
最近修改时间2023-09-19 03:16:41-
+
命令行工具
最近修改时间2023-09-25 07:17:26
async function checkUpdate(appKey)
检查更新,返回值有三种情形:
-
-
{ expired: true, diff --git a/docs/bestpractice.html b/docs/bestpractice.html index ccfa375..aea9b63 100644 --- a/docs/bestpractice.html +++ b/docs/bestpractice.html @@ -48,7 +48,7 @@ } } }) -
场景实践
最近修改时间2023-09-19 03:16:41-
+
场景实践
最近修改时间2023-09-25 07:17:26