Skip to content

Commit

Permalink
feat: v10
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnylqm committed Feb 8, 2024
1 parent d2db00f commit ecf59c0
Showing 1 changed file with 102 additions and 239 deletions.
341 changes: 102 additions & 239 deletions site/pages/docs/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => {
// 热更成功或报错的事件回调
// 可上报自有或第三方数据统计服务
},
});
```
<Callout type="info">
请注意,当前版本的api经过了完全重构,与之前的版本(v10.0以下)不兼容。如果你需要查看之前版本的文档,请点击[这里](https://v9--pushy-site.netlify.app/)
</Callout>

此方式默认在 App 启动,以及从后台切换到前台时触发更新检查,弹出提示的内容也固定。如需自定义触发时机,以及修改界面提示等,请参考下面的自定义集成方式。

## 自定义集成
安装配置完成后,确定应用编译顺利通过,下面我们来进行代码集成。

### 获取 appKey

检查更新时必须提供你的`appKey`,这个值保存在`update.json`中,并且根据平台不同而不同。你可以用如下的代码获取:
检查更新时必须提供你的`appKey`,这个值保存在`update.json`(使用`pushy createApp``pushy selectApp`命令后会自动生成),并且根据平台不同而不同。你可以用如下的代码获取`appKey`

```javascript
import { Platform } from "react-native";
Expand All @@ -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 client={pushyClient}>
{/* ↓ 整个应用的根组件放到PushyProvider中 */}
<App />
</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 (
<View style={styles.container}>
<Text>
更新下载进度:{received} / {total}
</Text>
<Pressable onPress={checkUpdate}>
<Text>点击这里检查更新</Text>
</Pressable>
{snackbarVisible && (
<Snackbar
visible={true}
onDismiss={() => {
setShowUpdateSnackbar(false);
}}
action={{
label: '更新',
onPress: async () => {
setShowUpdateSnackbar(false);
await downloadUpdate();
setShowUpdateBanner(true);
},
}}>
<Text>有新版本({updateInfo.name})可用,是否更新?</Text>
</Snackbar>
)}
<Banner
visible={showUpdateBanner}
actions={[
{
label: '立即重启',
onPress: switchVersion,
},
{
label: '下次再说',
onPress: () => {
switchVersionLater();
setShowUpdateBanner(false);
},
},
]}
icon={({size}) => (
<Icon name="checkcircleo" size={size} color="#00f" />
)}>
更新已完成,是否立即重启?
</Banner>
</View>
);
}

### 首次启动、回滚
```
在每次更新完毕后的首次启动时,`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 (
<View style={styles.container}>
<Text style={styles.welcome}>欢迎使用热更新服务</Text>
<Text style={styles.instructions}>
这是版本一 {"\n"}
当前原生包版本号: {packageVersion}
{"\n"}
当前热更新版本Hash: {currentVersion || "(空)"}
{"\n"}
</Text>
<Text>
下载进度:{received} / {total}
</Text>
<TouchableOpacity onPress={this.checkUpdate}>
<Text style={styles.instructions}>点击这里检查更新</Text>
</TouchableOpacity>
</View>
);
}
}
以上提及的所有 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)。

0 comments on commit ecf59c0

Please sign in to comment.