app_update.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import React, {Component} from 'react';
  2. import {
  3. StyleSheet,
  4. Platform,
  5. Text,
  6. View,
  7. Alert,
  8. TouchableOpacity,
  9. Linking,
  10. } from 'react-native';
  11. import {Button, Progress, WhiteSpace, Modal, Provider} from '@ant-design/react-native';
  12. import {
  13. isFirstTime,
  14. isRolledBack,
  15. packageVersion,
  16. currentVersion,
  17. checkUpdate,
  18. downloadUpdate,
  19. switchVersion,
  20. switchVersionLater,
  21. markSuccess,
  22. downloadAndInstallApk,
  23. } from 'react-native-update';
  24. import _updateConfig from '../../update.json';
  25. const {appKey} = _updateConfig[Platform.OS];
  26. export default class app_update extends Component {
  27. constructor(props) {
  28. super(props);
  29. this.state = {
  30. received: 0,
  31. total: 0,
  32. };
  33. }
  34. render() {
  35. const {received, total} = this.state;
  36. const footerButtons = [{text: '确认', onPress: () => console.log('ok')}];
  37. return (
  38. <Provider>
  39. <View style={styles.container}>
  40. <Modal
  41. title="更新"
  42. transparent
  43. onClose={this.onClose}
  44. maskClosable
  45. visible={false}
  46. closable={true}
  47. footer={footerButtons}>
  48. <View style={{paddingVertical: 20}}>
  49. <View
  50. style={{
  51. flexDirection: 'row',
  52. justifyContent: 'space-between',
  53. alignItems: 'center',
  54. }}>
  55. <View style={{marginRight: 10, height: 4, flex: 1}}>
  56. <Progress percent={50} />
  57. </View>
  58. <Text>{50}%</Text>
  59. </View>
  60. </View>
  61. </Modal>
  62. <Text style={styles.welcome}>欢迎使用热更新服务</Text>
  63. <Text style={styles.instructions}>
  64. 这是版本一 {'\n'}
  65. 当前原生包版本号: {packageVersion}
  66. {'\n'}
  67. 当前热更新版本Hash: {currentVersion || '(空)'}
  68. {'\n'}
  69. </Text>
  70. <Text>
  71. 下载进度:{received} / {total}
  72. </Text>
  73. <TouchableOpacity onPress={this.checkUpdate}>
  74. <Text style={styles.instructions}>点击这里检查更新</Text>
  75. </TouchableOpacity>
  76. </View>
  77. </Provider>
  78. );
  79. }
  80. componentDidMount() {
  81. if (isFirstTime) {
  82. // 必须调用此更新成功标记方法
  83. // 否则默认更新失败,下一次启动会自动回滚
  84. markSuccess();
  85. console.log('更新完成');
  86. } else if (isRolledBack) {
  87. console.log('刚刚更新失败了,版本被回滚.');
  88. }
  89. }
  90. doUpdate = async (info) => {
  91. try {
  92. const hash = await downloadUpdate(info, {
  93. onDownloadProgress: ({received, total}) => {
  94. this.setState({
  95. received,
  96. total,
  97. });
  98. },
  99. });
  100. Alert.alert('提示', '下载完毕,是否重启应用?', [
  101. {
  102. text: '是',
  103. onPress: () => {
  104. switchVersion(hash);
  105. },
  106. },
  107. {text: '否'},
  108. {
  109. text: '下次启动时',
  110. onPress: () => {
  111. switchVersionLater(hash);
  112. },
  113. },
  114. ]);
  115. } catch (err) {
  116. Alert.alert('更新失败', err.message);
  117. }
  118. };
  119. checkUpdate = async () => {
  120. if (__DEV__) {
  121. // 开发模式不支持热更新,跳过检查
  122. return;
  123. }
  124. let info;
  125. try {
  126. info = await checkUpdate(appKey);
  127. } catch (err) {
  128. Alert.alert('更新检查失败', err.message);
  129. return;
  130. }
  131. if (info.expired) {
  132. Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [
  133. {
  134. text: '确定',
  135. onPress: () => {
  136. if (info.downloadUrl) {
  137. // apk可直接下载安装
  138. if (
  139. Platform.OS === 'android' &&
  140. info.downloadUrl.endsWith('.apk')
  141. ) {
  142. downloadAndInstallApk({
  143. url: info.downloadUrl,
  144. onDownloadProgress: ({received, total}) => {
  145. this.setState({
  146. received,
  147. total,
  148. });
  149. },
  150. });
  151. } else {
  152. Linking.openURL(info.downloadUrl);
  153. }
  154. }
  155. },
  156. },
  157. ]);
  158. } else if (info.upToDate) {
  159. Alert.alert('提示', '您的应用版本已是最新.');
  160. } else {
  161. Alert.alert(
  162. '提示',
  163. '检查到新的版本' + info.name + ',是否下载?\n' + info.description,
  164. [
  165. {
  166. text: '是',
  167. onPress: () => {
  168. this.doUpdate(info);
  169. },
  170. },
  171. {text: '否'},
  172. ],
  173. );
  174. }
  175. };
  176. }
  177. const styles = StyleSheet.create({
  178. container: {
  179. flex: 1,
  180. justifyContent: 'center',
  181. alignItems: 'center',
  182. backgroundColor: '#F5FCFF',
  183. },
  184. welcome: {
  185. fontSize: 20,
  186. textAlign: 'center',
  187. margin: 10,
  188. },
  189. instructions: {
  190. textAlign: 'center',
  191. color: '#333333',
  192. marginBottom: 5,
  193. },
  194. });