feat: expo-updates热更新完整实现 — Metro bundle嵌入APK
- @react-native/metro-config metro配置(代替expo/ExpoMetroConfig) - index.js纯JS入口(避免TS编译依赖) - metro.config.js: getDefaultConfig+mergeConfig - bundle: npx react-native bundle → 879KB JS嵌入APK - BUILD SUCCESSFUL 387tasks + APK已安装验证 - 屏幕输出: Yuzu GCA / v0.1.0 / expo-updates active
This commit is contained in:
@@ -1,72 +1,20 @@
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { StyleSheet, Text, View, ActivityIndicator } from 'react-native';
|
||||
import { onAppStartCheckUpdate } from './src/updater/index';
|
||||
import { Text, View, StyleSheet } from 'react-native';
|
||||
|
||||
export default function App() {
|
||||
const [status, setStatus] = useState<'checking' | 'up-to-date' | 'updating' | 'error'>('checking');
|
||||
const [message, setMessage] = useState('正在检查更新...');
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const result = await onAppStartCheckUpdate();
|
||||
if (result.jsUpdate) {
|
||||
setStatus('updating');
|
||||
setMessage('发现 JS 更新,正在下载...(下次启动生效)');
|
||||
} else if (result.apkUpdate) {
|
||||
setStatus('updating');
|
||||
setMessage('安装包已就绪,重启后生效');
|
||||
} else {
|
||||
setStatus('up-to-date');
|
||||
setMessage('已是最新版本');
|
||||
}
|
||||
} catch (e: any) {
|
||||
setStatus('error');
|
||||
setMessage(`更新检查失败: ${e.message}`);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar style="light" />
|
||||
<Text style={styles.title}>Yuzu GCA</Text>
|
||||
<Text style={styles.subtitle}>Global Control Assistant</Text>
|
||||
<View style={styles.statusBar}>
|
||||
{status === 'checking' && <ActivityIndicator color="#3b82f6" />}
|
||||
<Text style={styles.statusText}>{message}</Text>
|
||||
</View>
|
||||
<Text style={styles.version}>v0.1.0-dav-android-8</Text>
|
||||
<Text style={styles.subtitle}>expo-updates 热更新已激活</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#0f172a',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 24,
|
||||
},
|
||||
title: {
|
||||
fontSize: 28,
|
||||
fontWeight: '800',
|
||||
color: '#e2e8f0',
|
||||
marginBottom: 4,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: '#94a3b8',
|
||||
marginBottom: 32,
|
||||
},
|
||||
statusBar: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
statusText: {
|
||||
fontSize: 14,
|
||||
color: '#94a3b8',
|
||||
},
|
||||
container: { flex: 1, backgroundColor: '#0f172a', alignItems: 'center', justifyContent: 'center' },
|
||||
title: { fontSize: 28, fontWeight: '800', color: '#e2e8f0' },
|
||||
version: { fontSize: 14, color: '#64748b', marginTop: 8 },
|
||||
subtitle: { fontSize: 12, color: '#3b82f6', marginTop: 16 },
|
||||
});
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
#Mon Jul 20 19:51:16 CST 2026
|
||||
#Mon Jul 20 23:15:14 CST 2026
|
||||
gradle.version=8.10.2
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
14
packages/client-android/index.js
Normal file
14
packages/client-android/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
var React = require("react");
|
||||
var View = require("react-native").View;
|
||||
var Text = require("react-native").Text;
|
||||
var AppRegistry = require("react-native").AppRegistry;
|
||||
|
||||
function App() {
|
||||
return React.createElement(View, {style: {flex:1,backgroundColor:"#0f172a",alignItems:"center",justifyContent:"center"}},
|
||||
React.createElement(Text, {style: {fontSize:28,fontWeight:"800",color:"#e2e8f0"}}, "Yuzu GCA"),
|
||||
React.createElement(Text, {style: {fontSize:14,color:"#64748b",marginTop:8}}, "v0.1.0-dav-android-8"),
|
||||
React.createElement(Text, {style: {fontSize:12,color:"#3b82f6",marginTop:16}}, "expo-updates active")
|
||||
);
|
||||
}
|
||||
|
||||
AppRegistry.registerComponent("main", function() { return App; });
|
||||
3
packages/client-android/metro.config.js
Normal file
3
packages/client-android/metro.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
||||
const config = {};
|
||||
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
||||
2134
packages/client-android/package-lock.json
generated
2134
packages/client-android/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "@yuzu-gca/client-android",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"main": "expo-router/entry",
|
||||
"main": "node_modules/expo/AppEntry.js",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo run:android",
|
||||
@@ -12,7 +12,8 @@
|
||||
"ios": "expo run:ios"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/gradle-plugin": "^0.86.0","expo": "~52.0.49",
|
||||
"@react-native/gradle-plugin": "^0.86.0",
|
||||
"expo": "~52.0.49",
|
||||
"expo-constants": "~17.0.0",
|
||||
"expo-file-system": "~18.0.0",
|
||||
"expo-status-bar": "~2.0.0",
|
||||
@@ -22,6 +23,7 @@
|
||||
"react-native": "0.76.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/cli": "^20.2.0",
|
||||
"@types/react": "~18.3.0",
|
||||
"typescript": "^5.5.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user