diff --git a/.gitignore b/.gitignore index 07ed026..819d856 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ Example/testHotUpdate/.yarn android/bin Example/testHotUpdate/harmony Example/testHotUpdate/android/app/.cxx +Example/harmony_use_pushy/libs diff --git a/.gitmodules b/.gitmodules index 1bcca5b..51168f3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "android/jni/HDiffPatch"] path = android/jni/HDiffPatch url = https://github.com/sisong/HDiffPatch.git +[submodule "harmony/src/main/cpp/HDiffPatch"] + path = harmony/src/main/cpp/HDiffPatch + url = https://github.com/sisong/HDiffPatch.git +[submodule "harmony/src/main/cpp/lzma"] + path = harmony/src/main/cpp/lzma + url = https://github.com/sisong/lzma.git diff --git a/Example/harmony_use_pushy/.bundle/config b/Example/harmony_use_pushy/.bundle/config new file mode 100644 index 0000000..848943b --- /dev/null +++ b/Example/harmony_use_pushy/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/Example/harmony_use_pushy/.eslintrc.js b/Example/harmony_use_pushy/.eslintrc.js new file mode 100644 index 0000000..187894b --- /dev/null +++ b/Example/harmony_use_pushy/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/Example/harmony_use_pushy/.prettierrc.js b/Example/harmony_use_pushy/.prettierrc.js new file mode 100644 index 0000000..2b54074 --- /dev/null +++ b/Example/harmony_use_pushy/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, + bracketSpacing: false, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/Example/harmony_use_pushy/.watchmanconfig b/Example/harmony_use_pushy/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/Example/harmony_use_pushy/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/Example/harmony_use_pushy/App.tsx b/Example/harmony_use_pushy/App.tsx new file mode 100644 index 0000000..85fdf8c --- /dev/null +++ b/Example/harmony_use_pushy/App.tsx @@ -0,0 +1,221 @@ +/* eslint-disable react/no-unstable-nested-components */ +/* eslint-disable react-native/no-inline-styles */ +import React, {useState} from 'react'; +import {StyleSheet, Text, View, TouchableOpacity, Image} from 'react-native'; + +import TestConsole from './TestConsole'; + +import _updateConfig from './update.json'; +import {PushyProvider, Pushy, usePushy} from 'react-native-update'; +const {appKey} = _updateConfig.harmony; + +function App() { + const { + client, + checkUpdate, + downloadUpdate, + switchVersionLater, + switchVersion, + updateInfo, + packageVersion, + currentHash, + progress: {received, total} = {}, + } = usePushy(); + const [useDefaultAlert, setUseDefaultAlert] = useState(false); + const [showTestConsole, setShowTestConsole] = useState(false); + const [showUpdateBanner, setShowUpdateBanner] = useState(false); + const [showUpdateSnackbar, setShowUpdateSnackbar] = useState(false); + // if (updateInfo) { + // updateInfo!.name = 'name'; + // updateInfo!.update = true; + // } + const snackbarVisible = + !useDefaultAlert && showUpdateSnackbar && updateInfo?.update; + + if (showTestConsole) { + return ( + setShowTestConsole(false)} /> + ); + } + + return ( + + 欢迎使用Pushy热更新服务 + {/* 😁hdiffFromAPP更新成功!!! */} + {/* 😁hdiffFromPPk更新成功!!! */} + + { + client?.setOptions({ + updateStrategy: !useDefaultAlert ? null : 'alwaysAlert', + }); + setShowUpdateSnackbar(useDefaultAlert); + setUseDefaultAlert(!useDefaultAlert); + }} + style={{ + flexDirection: 'row', + alignItems: 'center', + }}> + + {useDefaultAlert && } + + + {' '} + {useDefaultAlert ? '当前使用' : '当前不使用'}默认的alert更新提示 + + + + + + 这是版本一 {'\n'} + 当前原生包版本号: {packageVersion} + {'\n'} + 当前热更新版本Hash: {currentHash || '(空)'} + {'\n'} + + + 下载进度:{received} / {total} + + { + checkUpdate(); + setShowUpdateSnackbar(true); + }}> + 点击这里检查更新 + + + { + setShowTestConsole(true); + }}> + + react-native-update版本:{client?.version} + + + {snackbarVisible && ( + + + + 有新版本({updateInfo.name})可用,是否更新? + + + setShowUpdateSnackbar(false)} + style={{marginRight: 10}}> + 取消 + + { + setShowUpdateSnackbar(false); + await downloadUpdate(); + setShowUpdateBanner(true); + }}> + 更新 + + + + + )} + {showUpdateBanner && ( + + + + 更新已完成,是否立即重启? + + + { + switchVersionLater(); + setShowUpdateBanner(false); + }} + style={{marginRight: 20}}> + 下次再说 + + + 立即重启 + + + + + )} + + ); +} + +const styles = StyleSheet.create({ + overlay: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'center', + alignItems: 'center', + }, + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, + image: {}, +}); + +const pushyClient = new Pushy({ + appKey, + debug: true, +}); + +export default function Root() { + return ( + + + + ); +} diff --git a/Example/harmony_use_pushy/Gemfile b/Example/harmony_use_pushy/Gemfile new file mode 100644 index 0000000..1fa2c2e --- /dev/null +++ b/Example/harmony_use_pushy/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +gem 'cocoapods', '~> 1.12' diff --git a/Example/harmony_use_pushy/README.md b/Example/harmony_use_pushy/README.md new file mode 100644 index 0000000..c243fdf --- /dev/null +++ b/Example/harmony_use_pushy/README.md @@ -0,0 +1,34 @@ +## 运行harmony_use_pushy项目步骤 + +### 1.将项目克隆到本地后在项目根目录创建libs文件夹。 + +### 2.然后将[`rnoh`](https://github.com/bozaigao/rnoh)克隆到libs文件夹中。 + +说明:rnoh项目基于react-native 0.72.5版本适配,如果使用最新的RN版本可能会报错,项目适配RN新版本请关注[`gitee仓库`](https://gitee.com/openharmony-sig/ohos_react_native/tree/0.72.5-ohos-5.0-release/tester/harmony/react_native_openharmony/src/main) + +### 3.进入rnoh项目执行下面命令对rnoh项目依赖的C++库进行初始化; +``` +git submodule update --init --recursive +``` + +### 4. 确保在react-native-update根目录已经执行过yarn submodule命令。 +说明:这个命令会在harmony/src/main/cpp目录生成HDiffPatch和lzma的C++模块依赖。 + +### 5. 在项目根目录执行下面命令安装第三方依赖。 +``` +yarn install +``` + +### 6. 在项目根目录执行下面命令生成bundle包文件。 +``` +yarn build +``` +说明:这个命令会在harmony/entry/src/main/resources/rawfile目录生成Hbundle.harmony.js和assets文件,同时会基于该内容在.pushy/output目录生成ppk包。 + +**注意⚠️**:在使用pushy bundle --platform harmony命令进行打包的默认bundle包名是Hbundle.harmony.js,不要随意修改包名,因为diff是匹配该包名进行生成的。 + +### 7. 使用DevEco Studio IDE打开harmony目录然后执行sync运行项目 +![image](./sync.png) + +### 8 运行效果图 +![image](./demo.png) \ No newline at end of file diff --git a/Example/harmony_use_pushy/TestConsole.js b/Example/harmony_use_pushy/TestConsole.js new file mode 100644 index 0000000..c05fa5d --- /dev/null +++ b/Example/harmony_use_pushy/TestConsole.js @@ -0,0 +1,274 @@ +/* eslint-disable react-native/no-inline-styles */ +/* eslint-disable react/react-in-jsx-scope */ +import {useCallback, useMemo, useState} from 'react'; +import { + ActivityIndicator, + TextInput, + Button, + StyleSheet, + SafeAreaView, + Text, + View, + TouchableOpacity, +} from 'react-native'; + +import {PushyModule} from 'react-native-update'; +const Hash = '9D5CE6EBA420717BE7E7D308B11F8207681B066C951D68F3994D19828F342474'; +const UUID = '00000000-0000-0000-0000-000000000000'; +const DownloadUrl = 'https://localhost:3000/diff.ppk-patch'; +const AppPatchDownloadUrl = 'https://github.com/bozaigao/test_pushy_server/raw/refs/heads/main/hdiff.app-patch'; +const AppPatchHash = 'f5ba92c7c04250d4b8a446c8267ef459'; +const PPKDownloadUrl = 'https://github.com/bozaigao/test_pushy_server/raw/refs/heads/main/hdiff.ppk-patch'; +const PPKPatchHash = '6b3d26b7d868d1f67aedadb7f0b342d9'; +const OriginHash = 'f5ba92c7c04250d4b8a446c8267ef459'; + + +const CustomDialog = ({title, visible, onConfirm}) => { + if (!visible) { + return null; + } + + return ( + + + {title} + + 确认 + + + + ); +}; +export default function TestConsole({visible, onClose}) { + const [text, setText] = useState(''); + const [running, setRunning] = useState(false); + const [options, setOptions] = useState(); + const [alertVisible, setAlertVisible] = useState(false); + const [alertMsg, setAlertMsg] = useState(''); + const NativeTestMethod = useMemo(() => { + return [ + { + name: 'setLocalHashInfo', + invoke: () => { + setText( + `setLocalHashInfo\n${Hash}\n{\"version\":\"1.0.0\",\"size\":\"19M\"}`, + ); + }, + }, + { + name: 'getLocalHashInfo', + invoke: () => { + setText(`getLocalHashInfo\n${Hash}`); + }, + }, + { + name: 'setUuid', + invoke: () => { + setText(`setUuid\n${UUID}`); + }, + }, + { + name: 'reloadUpdate', + invoke: () => { + setText('reloadUpdate'); + setOptions({hash: Hash}); + }, + }, + { + name: 'setNeedUpdateForApp', + invoke: () => { + setText('setNeedUpdate'); + setOptions({hash: AppPatchHash}); + }, + }, + { + name: 'setNeedUpdateForPPK', + invoke: () => { + setText('setNeedUpdate'); + setOptions({hash: PPKPatchHash}); + }, + }, + { + name: 'markSuccess', + invoke: () => { + setText('markSuccess'); + setOptions(undefined); + }, + }, + { + name: 'downloadPatchFromPpk', + invoke: () => { + setText('downloadPatchFromPpk'); + setOptions({updateUrl: PPKDownloadUrl, hash: PPKPatchHash, originHash: OriginHash}); + }, + }, + { + name: 'downloadPatchFromPackage', + invoke: () => { + setText('downloadPatchFromPackage'); + setOptions({updateUrl: AppPatchDownloadUrl, hash: AppPatchHash}); + }, + }, + { + name: 'downloadFullUpdate', + invoke: () => { + setText('downloadFullUpdate'); + setOptions({updateUrl: DownloadUrl, hash: Hash}); + }, + }, + { + name: 'downloadAndInstallApk', + invoke: () => { + setText('downloadAndInstallApk'); + setOptions({url: DownloadUrl, target: Hash, hash: Hash}); + }, + }, + ]; + }, []); + + const renderTestView = useCallback(() => { + const views = []; + for (let i = 0; i < NativeTestMethod.length; i++) { + views.push( + { + NativeTestMethod[i].invoke(); + }}> + {NativeTestMethod[i].name} + , + ); + } + return {views}; + }, [NativeTestMethod]); + if (!visible) { + return null; + } + + return ( + + + 调试Pushy方法(方法名,参数,值换行) +