diff --git a/site/pages/docs/getting-started.mdx b/site/pages/docs/getting-started.mdx index 5852898..ed49cb7 100644 --- a/site/pages/docs/getting-started.mdx +++ b/site/pages/docs/getting-started.mdx @@ -6,10 +6,14 @@ type: 快速入门 import { Callout, Steps, Tabs } from "nextra/components"; + + 请注意,当前版本的api经过了完全重构,与之前的版本(v10.0以下)不兼容。如果你需要查看之前版本的文档,请点击[这里](https://v9--pushy-site.netlify.app/) + + 首先你应该有一个基于 React Native 开发的应用,我们把具有 package.json 的目录叫做你的`应用根目录`。 如果你还没有初始化应用,请参阅[开始使用 React Native](https://reactnative.cn/docs/getting-started)。 -我们假设你已经拥有了开发 React Native 应用的一切环境,包括`Node.js`、`XCode`、`Android SDK`等等。 +我们假设你已经拥有了开发 React Native 应用的一切环境,包括`Node.js`、`Xcode`、`Android SDK`等等。 ### 安装 @@ -21,11 +25,11 @@ import { Callout, Steps, Tabs } from "nextra/components"; npm i -g react-native-update-cli # 然后在项目目录中安装热更新模块 -# 0.71 及以上版本使用最新版本如下 npm i react-native-update -# 0.71 以下版本请使用8.x版本 -# npm i react-native-update@8.x +# 然后进入ios目录安装iOS模块 +cd ios && pod install + ``` @@ -36,45 +40,6 @@ npm i react-native-update 注意请不要混用`npm/yarn/pnpm`等包管理器及对应的`lock`文件,团队成员请坚持使用同一包管理器,且仅保留统一格式的`lock`文件 -如果你的 RN 版本 >= 0.60,请在 ios 目录下执行: - -```bash -pod install -``` - -如果你的 RN 版本 < 0.60,那么需要先在`package.json`文件的`scripts`中加入: - -```json -"postinstall": "npx jetify -r" -``` - -然后按照[手动 link](#手动-link)的说明操作。 - -
- -如果你的RN版本比较老(< 0.46),请点击这里的注意事项 - - -如果你的 RN 版本比较老,请按下面表格尝试老一些的版本(但这些版本我们已不再维护,不能保证可以使用): - -| React Native 版本 | react-native-update 版本 | -| ----------------- | ------------------------ | -| 0.26 及以下 | 1.0.x | -| 0.27 - 0.28 | 2.x | -| 0.29 - 0.33 | 3.x | -| 0.34 - 0.45 | 4.x | -| 0.46 - 0.70 | 8.x | - -安装命令示例: - -```bash -npm i react-native-update@4.x -``` - -如果 RN 的版本是 0.45 及以下,你还必须安装`[Android NDK](http://androiddevtools.cn)`,版本最好选用 r10e,并设置环境变量`ANDROID_NDK_HOME`,指向你的 NDK 根目录(例如`/Users/tdzl2003/Downloads/android-ndk-r10e`)。 - -
- 请记得,任意在 ios 和 android 目录下的修改,一定要重新编译(使用 npx react-native run-ios 或 run-android 命令编译,或在 Xcode/Android Studio @@ -87,7 +52,8 @@ npm i react-native-update@4.x 注意:如果是混编 RN 项目,由于自定义的配置可能不完整,自动 link - 的功能可能不能正常工作。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link 操作。 + 的功能可能不能正常工作。此时即便 RN 版本 >= 0.60,你可能也需要执行手动 link + 操作。 #### iOS @@ -165,7 +131,7 @@ date +%s > "$DEST/pushy_build_time.txt" #import "RCTPushy.h" // <-- import头文件,注意要放到if条件外面 -// 可能项目里有一些条件编译语句,例如像较新版本RN自带的flipper +// 可能项目里有一些条件编译语句,例如有些版本RN自带的flipper // #if DEBUG // 注意**不要**在这里面引入"RCTPushy.h" // #import diff --git a/site/pages/docs/integration.md b/site/pages/docs/integration.md index db7edde..3c107f5 100644 --- a/site/pages/docs/integration.md +++ b/site/pages/docs/integration.md @@ -4,40 +4,15 @@ title: 代码集成 type: 快速入门 --- -安装配置完成后,确定应用编译顺利通过,下面我们来进行代码集成。 - -## 极简快速集成 - -我们从 v8.x 版本开始提供极简的三行式集成(老版本只能使用自定义集成方式): - -```js -import { Platform } from "react-native"; -import { simpleUpdate } from "react-native-update"; -import _updateConfig from "./update.json"; -const { appKey } = _updateConfig[Platform.OS]; - -// 整个应用的根组件,class 或函数组件都可以 -class App extends Component { - // 这是个空的示例,请替换为你自己的根组件 -} - -// 对根组件使用simpleUpdate方法封装后导出 -export default simpleUpdate(App, { - appKey, - onPushyEvents: ({ type, data }) => { - // 热更成功或报错的事件回调 - // 可上报自有或第三方数据统计服务 - }, -}); -``` + + 请注意,当前版本的api经过了完全重构,与之前的版本(v10.0以下)不兼容。如果你需要查看之前版本的文档,请点击[这里](https://v9--pushy-site.netlify.app/) + -此方式默认在 App 启动,以及从后台切换到前台时触发更新检查,弹出提示的内容也固定。如需自定义触发时机,以及修改界面提示等,请参考下面的自定义集成方式。 - -## 自定义集成 +安装配置完成后,确定应用编译顺利通过,下面我们来进行代码集成。 ### 获取 appKey -检查更新时必须提供你的`appKey`,这个值保存在`update.json`中,并且根据平台不同而不同。你可以用如下的代码获取: +检查更新时必须提供你的`appKey`,这个值保存在`update.json`中(使用`pushy createApp`或`pushy selectApp`命令后会自动生成),并且根据平台不同而不同。你可以用如下的代码获取`appKey`: ```javascript import { Platform } from "react-native"; @@ -48,235 +23,123 @@ const { appKey } = _updateConfig[Platform.OS]; 如果你不使用 pushy 命令行,也可以从网页端查看到两个应用 appKey,并根据平台的不同来选择。 -### 检查更新、下载更新 +### 初始化服务 -异步函数[`checkUpdate`](api#async-function-checkupdateappkey)可以检查当前版本是否需要更新: +```js +import { PushyProvider, Pushy } from "react-native-update"; -```javascript -const info = await checkUpdate(appKey); -``` +// 唯一必填参数是appKey,其他选项请参阅 api 文档 +const pushyClient = new Pushy({ + appKey, +}); -返回的[`info`](api#async-function-checkupdateappkey)有三种情况: +// 在根组件外加上PushyProvider后导出 +export default function Root() { + return ( + + {/* ↓ 整个应用的根组件放到PushyProvider中 */} + + + ); +} +``` -1. `{expired: true}`:该应用原生包已过期(三种情况:1. 主动设置为过期状态,2. 主动删除,3. 从未上传),开发者应该在 pushy 控制台添加一个更新下载链接,并自行提示用户下载。 +如没有特别的自定义需求,那么到此热更新已经可以开始正常运作。默认配置下,在 App 启动,以及从后台切换到前台时会触发更新检查,弹出提示的内容也固定。如需自定义触发时机,以及修改界面提示等,请参考下面的自定义更新界面。 -2. `{upToDate: true}`:当前已经更新到最新,无需进行更新。 +### 自定义更新界面 -3. `{update: true}`:当前有新版本可以更新。info 的`name`、`description`字段可以用于提示用户,而`metaInfo`字段则可以根据你的需求自定义其它属性(如是否静默更新、是否强制更新等等),具体用法可参考[场景实践](bestpractice#%E5%85%83%E4%BF%A1%E6%81%AFmeta-info%E7%9A%84%E4%BD%BF%E7%94%A8)。另外还有几个字段,包含了补丁包的下载地址等。 pushy 会首先尝试耗费流量更少的更新方式。将`info`对象传递给`downloadUpdate`方法作为参数即可。 +默认配置下,pushy会以系统alert的形式来弹出更新提示,如需自定义更新界面,首先请关闭默认的 alert 弹窗: -```javascript -const hash = await downloadUpdate( - info, - // 下载回调为可选参数,从v5.8.3版本开始加入 - { - onDownloadProgress: ({ received, total }) => { - // 已下载的字节数, 总字节数 - console.log(received, total); - }, - } -); +```diff +const pushyClient = new Pushy({ + appKey, ++ showAlert: false, +}); ``` -`downloadUpdate`方法从`v5.8.3`版本开始新增接受第二个可选参数,为下载进度的回调函数(`onDownloadProgress`)。可根据回调参数自行设计进度的展示。 - -### 切换版本 +所有更新相关的数据可以通过一个单一的[`usePushy()`](/docs/api#usepushy)hook函数来获取,然后可以根据其提供的数据来自行渲染自定义的界面,如下面的例子: -`downloadUpdate`的返回值是一个 hash 字符串,它是当前热更新版本的唯一标识。 - -你可以使用`switchVersion(hash)`函数立即切换版本(此时应用会立即重新加载),或者选择调用 `switchVersionLater(hash)`,让应用在下一次启动的时候再加载新的版本。 +```js +import {Icon, PaperProvider, Snackbar, Banner} from 'react-native-paper'; +function App() { + const { + checkUpdate, + downloadUpdate, + switchVersionLater, + switchVersion, + updateInfo, + progress: {received, total} = {}, + } = usePushy(); + const [showUpdateBanner, setShowUpdateBanner] = useState(false); + const [showUpdateSnackbar, setShowUpdateSnackbar] = useState(false); + const snackbarVisible = + showUpdateSnackbar && updateInfo?.update && !useDefaultAlert; + return ( + + + 更新下载进度:{received} / {total} + + + 点击这里检查更新 + + {snackbarVisible && ( + { + setShowUpdateSnackbar(false); + }} + action={{ + label: '更新', + onPress: async () => { + setShowUpdateSnackbar(false); + await downloadUpdate(); + setShowUpdateBanner(true); + }, + }}> + 有新版本({updateInfo.name})可用,是否更新? + + )} + { + switchVersionLater(); + setShowUpdateBanner(false); + }, + }, + ]} + icon={({size}) => ( + + )}> + 更新已完成,是否立即重启? + + + ); +} -### 首次启动、回滚 +``` -在每次更新完毕后的首次启动时,`isFirstTime`常量会为`true`。你必须在应用退出前合适的任何时机,调用`markSuccess`,否则应用下一次启动的时候将会进行回滚操作。这一机制称作“反触发”,这样当你应用启动初期即遭遇问题的时候,也能在下一次启动时恢复运作。 +其中`checkUpdate`方法可以用来手动触发更新检查。检查后返回的[`updateInfo`](api#async-function-checkupdateappkey)有三种情况: -你可以通过`isFirstTime`来获知这是当前版本的首次启动,也可以通过`isRolledBack`来获知应用刚刚经历了一次回滚操作。你可以在此时给予用户合理的提示。 +1. `{expired: true}`:该应用原生包已过期(三种情况:1. 主动设置为过期状态,2. 主动删除,3. 从未上传),开发者应该在 pushy 的管理后台添加一个更新下载链接,并自行提示用户下载。 -以上提及的所有 api 的说明文档可在[这里](api)查看。 +2. `{upToDate: true}`:当前已经更新到最新,无需进行更新。 -### 完整的示例 +3. `{update: true}`:当前有新版本可以更新。info 的`name`、`description`字段可以用于提示用户,而`metaInfo`字段则可以根据你的需求自定义其它属性(如是否静默更新、是否强制更新等等),具体用法可参考[场景实践](bestpractice#%E5%85%83%E4%BF%A1%E6%81%AFmeta-info%E7%9A%84%E4%BD%BF%E7%94%A8)。另外还有几个字段,包含了补丁包的下载地址等。 pushy 会首先尝试耗费流量更少的更新方式。 -```javascript -import React, { Component } from "react"; +当返回的`updateInfo`中`update`字段为true时,即可调用`downloadUpdate`方法来下载更新,此时可以获取到下载的进度数据`progress`。下载完成后可以调用`switchVersion`来立即重启更新,也可以使用`switchVersionLater`来标记下次启动时更新。 -import { - StyleSheet, - Platform, - Text, - View, - Alert, - TouchableOpacity, - Linking, -} from "react-native"; +### 统计数据 -import { - isFirstTime, - isRolledBack, - packageVersion, - currentVersion, - checkUpdate, - downloadUpdate, - switchVersion, - switchVersionLater, - markSuccess, - downloadAndInstallApk, - onPushyEvents, -} from "react-native-update"; -import _updateConfig from "./update.json"; -const { appKey } = _updateConfig[Platform.OS]; -onPushyEvents(({ type, data }) => { - // 热更成功或报错的事件回调 - // 可上报自有或第三方数据统计服务 -}); -export default class MyProject extends Component { - state = { - received: 0, - total: 0, - }; - componentDidMount() { - if (isFirstTime) { - // 必须调用此更新成功标记方法 - // 否则默认更新失败,下一次启动会自动回滚 - markSuccess(); - console.log("更新完成"); - } else if (isRolledBack) { - console.log("刚刚更新失败了,版本被回滚."); - } - } - doUpdate = async (info) => { - try { - const hash = await downloadUpdate(info, { - onDownloadProgress: ({ received, total }) => { - this.setState({ - received, - total, - }); - }, - }); - if (!hash) { - return; - } - Alert.alert("提示", "下载完毕,是否重启应用?", [ - { - text: "是", - onPress: () => { - switchVersion(hash); - }, - }, - { text: "否" }, - { - text: "下次启动时", - onPress: () => { - switchVersionLater(hash); - }, - }, - ]); - } catch (err) { - Alert.alert("更新失败", err.message); - } - }; - checkUpdate = async () => { - if (__DEV__) { - // 开发模式不支持热更新,跳过检查 - return; - } - let info; - try { - info = await checkUpdate(appKey); - } catch (err) { - Alert.alert("更新检查失败", err.message); - return; - } - if (info.expired) { - Alert.alert("提示", "您的应用版本已更新,点击确定下载安装新版本", [ - { - text: "确定", - onPress: () => { - // downloadUrl 需要在后台设置中自行配置 - if (info.downloadUrl) { - // apk可直接下载安装 - if ( - Platform.OS === "android" && - info.downloadUrl.endsWith(".apk") - ) { - // 此方法还需要额外的配置,请参考 - // https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapk-url-ondownloadprogress- - downloadAndInstallApk({ - url: info.downloadUrl, - onDownloadProgress: ({ received, total }) => { - this.setState({ - received, - total, - }); - }, - }); - } else { - Linking.openURL(info.downloadUrl); - } - } - }, - }, - ]); - } else if (info.upToDate) { - Alert.alert("提示", "您的应用版本已是最新."); - } else if (info.update) { - Alert.alert( - "提示", - "检查到新的版本" + info.name + ",是否下载?\n" + info.description, - [ - { - text: "是", - onPress: () => { - this.doUpdate(info); - }, - }, - { text: "否" }, - ] - ); - } - }; - render() { - const { received, total } = this.state; - return ( - - 欢迎使用热更新服务 - - 这是版本一 {"\n"} - 当前原生包版本号: {packageVersion} - {"\n"} - 当前热更新版本Hash: {currentVersion || "(空)"} - {"\n"} - - - 下载进度:{received} / {total} - - - 点击这里检查更新 - - - ); - } -} +以上提及的所有 api 的说明文档可在[这里](api)查看。 -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: "#F5FCFF", - }, - welcome: { - fontSize: 20, - textAlign: "center", - margin: 10, - }, - instructions: { - textAlign: "center", - color: "#333333", - marginBottom: 5, - }, -}); -``` 现在,你的应用已经可以通过 pushy 服务检查版本并进行更新了。下一步,你可以开始尝试发布应用包和版本,请参阅[发布热更新](publish)。