u
This commit is contained in:
1 parent
785cc946d2
commit
94983ed1ea
8 files changed
+1432
-1086
No files matched your search
@@ -20,14 +20,14 @@
|
||||
},
|
||||
"edgeToEdgeEnabled": true,
|
||||
"predictiveBackGestureEnabled": false,
|
||||
"package": "com.anonymous.myapp"
|
||||
"package": "com.oneao.myapp"
|
||||
},
|
||||
"web": {
|
||||
"output": "static",
|
||||
"favicon": "./assets/images/favicon.png"
|
||||
},
|
||||
"plugins": [
|
||||
"./plugins/withAndroidSignature",
|
||||
"./plugins/withAndroidSignature",
|
||||
"expo-router",
|
||||
[
|
||||
"expo-splash-screen",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"keystore": {
|
||||
"keystorePath": "credentials/android-release.keystore",
|
||||
"keystorePassword": "123456",
|
||||
"keyAlias": "my-key-alias",
|
||||
"keyAlias": " my-key-alias",
|
||||
"keyPassword": "123456"
|
||||
}
|
||||
},
|
||||
|
||||
Binary file not shown.
Generated
+1054
-1054
File diff suppressed because it is too large.
Load diff
@@ -15,8 +15,8 @@
|
||||
"@react-navigation/bottom-tabs": "^7.4.0",
|
||||
"@react-navigation/elements": "^2.6.3",
|
||||
"@react-navigation/native": "^7.1.8",
|
||||
"expo": "~54.0.15",
|
||||
"expo-constants": "~18.0.9",
|
||||
"expo": "~54.0.18",
|
||||
"expo-constants": "~18.0.10",
|
||||
"expo-font": "~14.0.9",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-image": "~3.0.10",
|
||||
@@ -25,23 +25,23 @@
|
||||
"expo-splash-screen": "~31.0.10",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
"expo-system-ui": "~6.0.7",
|
||||
"expo-system-ui": "~6.0.8",
|
||||
"expo-web-browser": "~15.0.8",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-native": "0.81.4",
|
||||
"react-native": "0.81.5",
|
||||
"react-native-gesture-handler": "~2.28.0",
|
||||
"react-native-worklets": "0.5.1",
|
||||
"react-native-reanimated": "~4.1.1",
|
||||
"react-native-safe-area-context": "^5.6.1",
|
||||
"react-native-safe-area-context": "~5.6.0",
|
||||
"react-native-screens": "~4.16.0",
|
||||
"react-native-web": "~0.21.0",
|
||||
"react-native-worklets": "0.5.1"
|
||||
"react-native-web": "~0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "~19.1.0",
|
||||
"typescript": "~5.9.2",
|
||||
"eslint": "^9.25.0",
|
||||
"eslint-config-expo": "~10.0.0",
|
||||
"typescript": "~5.9.2"
|
||||
"eslint-config-expo": "~10.0.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// plugins/withAndroidSignature.js
|
||||
|
||||
const { withAppBuildGradle } = require("@expo/config-plugins");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>App TabBar</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Arial', sans-serif;
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
justify-content: flex-end; /* 保证TabBar在底部 */
|
||||
}
|
||||
|
||||
/* TabBar 容器 */
|
||||
.tabbar {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background: #fff;
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 15px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.05); /* 轻微阴影 */
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
/* Tab 按钮 */
|
||||
.tab {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
flex: 1; /* 平均分布 */
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.tab svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-bottom: 3px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 高亮效果 */
|
||||
.tab.active {
|
||||
color: #2575fc; /* 选中颜色 */
|
||||
}
|
||||
|
||||
.tab.active svg {
|
||||
transform: scale(1.2);
|
||||
fill: #2575fc;
|
||||
}
|
||||
|
||||
/* 可选:添加底部小圆点高亮 */
|
||||
.tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #2575fc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="tabbar">
|
||||
<a href="#" class="tab active">
|
||||
<svg fill="currentColor" viewBox="0 0 24 24"><path d="M12 2L2 12h3v8h6v-6h2v6h6v-8h3z"/></svg>
|
||||
首页
|
||||
</a>
|
||||
<a href="#" class="tab">
|
||||
<svg fill="currentColor" viewBox="0 0 24 24"><path d="M12 12c2.21 0 4-1.79 4-4S14.21 4 12 4 8 5.79 8 8s1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
|
||||
我的
|
||||
</a>
|
||||
<a href="#" class="tab">
|
||||
<svg fill="currentColor" viewBox="0 0 24 24"><path d="M3 6h18v2H3zM3 12h18v2H3zM3 18h18v2H3z"/></svg>
|
||||
菜单
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+270
-20
@@ -12,42 +12,292 @@
|
||||
|
||||
1. 安装 EAS CLI
|
||||
|
||||
```bash
|
||||
npm install -g eas-cli
|
||||
```
|
||||
```bash
|
||||
npm install -g eas-cli
|
||||
```
|
||||
|
||||
2. 注册并登录 Expo 账户
|
||||
|
||||
访问 https://expo.dev/ 注册账户,然后命令行登录:
|
||||
- 访问 https://expo.dev/ 注册账户,然后命令行登录:
|
||||
|
||||
```bash
|
||||
expo login
|
||||
```
|
||||
```bash
|
||||
expo login
|
||||
```
|
||||
|
||||
3. 配置项目构建
|
||||
|
||||
```bash
|
||||
eas build:configure
|
||||
```
|
||||
- 输入以下命令,选择 Android 平台即可。
|
||||
|
||||
选择 Android 平台即可。
|
||||
```bash
|
||||
eas build:configure
|
||||
```
|
||||
|
||||
4. 构建 Android 包
|
||||
|
||||
默认构建 AAB 包(上传 Google Play):
|
||||
- 默认构建 AAB 包(上传 Google Play):
|
||||
|
||||
```bash
|
||||
eas build --platform android
|
||||
```
|
||||
|
||||
- 构建 APK(可直接安装):
|
||||
|
||||
```bash
|
||||
eas build -p android --profile preview
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 本地打包(EAS方式)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 本地打包(原生方式)
|
||||
|
||||
### 1. 安装 [Android Studio]( https://developer.android.com/?hl=zh-cn)
|
||||
|
||||
1. 下载安装
|
||||
|
||||
- 按照官网提示依次安装 SDK 工具和必要组件。
|
||||
|
||||
- 安装完成后,记住 SDK 的安装路径(例如:`D:\data\sdk`,默认位置是:`C:\Users\<你的用户名>\AppData\Local\Android\Sdk`),后续需要用到。
|
||||
|
||||
2. 配置环境变量
|
||||
|
||||
- 打开 **系统属性 → 高级 → 环境变量**。
|
||||
|
||||
- 在 **系统变量** 中新增:
|
||||
|
||||
```
|
||||
变量名:ANDROID_HOME
|
||||
变量值:D:\data\sdk
|
||||
```
|
||||
|
||||
- 在 **Path** 中新增:
|
||||
|
||||
```bash
|
||||
%ANDROID_HOME%\platform-tools
|
||||
%ANDROID_HOME%\tools
|
||||
%ANDROID_HOME%\tools\bin
|
||||
```
|
||||
|
||||
- 保存设置。
|
||||
|
||||
3. 验证安装
|
||||
|
||||
- 打开命令行,执行:
|
||||
|
||||
```
|
||||
echo %ANDROID_HOME%
|
||||
```
|
||||
|
||||
- 如果输出 SDK 路径,则说明配置成功。
|
||||
|
||||
|
||||
|
||||
### 2. 安装 [jdk17](https://adoptium.net/zh-CN/temurin/releases?version=8&os=any&arch=any)
|
||||
|
||||
1. 下载安装
|
||||
|
||||
- 下载对应版本解压即可。
|
||||
- 安装成功后,记住 jdk 的安装路径,后续需要用到。
|
||||
|
||||
2. 配置环境变量
|
||||
|
||||
- 打开 **系统属性 → 高级 → 环境变量**。
|
||||
|
||||
- 在 **系统变量** 中新增:
|
||||
|
||||
```bash
|
||||
变量名:JAVA_HOME
|
||||
变量值:D:\devtool\jdk\jdk-17.0.16+8
|
||||
```
|
||||
|
||||
- 在 **Path** 中新增:
|
||||
|
||||
```bash
|
||||
%JAVA_HOME%\bin
|
||||
```
|
||||
|
||||
- 保存设置。
|
||||
|
||||
3. 验证安装
|
||||
|
||||
- 打开命令行,执行:
|
||||
|
||||
```bash
|
||||
java --version
|
||||
```
|
||||
|
||||
- 如果输出 jdk 的信息,则说明配置成功。
|
||||
|
||||
|
||||
|
||||
### 3. Expo 项目启用 [Prebuild](https://docs.expo.dev/workflow/prebuild/)
|
||||
|
||||
1. 生成原生项目
|
||||
|
||||
```bash
|
||||
npx expo prebuild
|
||||
```
|
||||
|
||||
然后执行完毕后,会生成 `android` 目录。
|
||||
|
||||
2. 清除并重新生成原生项目
|
||||
|
||||
```bash
|
||||
npx expo prebuild --clean
|
||||
```
|
||||
|
||||
会删除已有的 `android` 和 `ios` 目录,然后重新生成。
|
||||
|
||||
|
||||
|
||||
### 4. 配置 Keystore
|
||||
|
||||
#### 4.1 生成密钥
|
||||
|
||||
```bash
|
||||
eas build --platform android
|
||||
keytool -genkey -v -keystore android-release.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
|
||||
```
|
||||
|
||||
构建 APK(可直接安装):
|
||||
说明:
|
||||
|
||||
```bash
|
||||
eas build -p android --profile preview
|
||||
```
|
||||
- `my-release-key.keystore`:生成的密钥文件名,可自定义路径
|
||||
- `my-key-alias`:密钥别名
|
||||
- `RSA`:加密算法
|
||||
- `2048`:密钥长度
|
||||
- `10000`:有效期(天)
|
||||
|
||||
## 本地打包
|
||||
#### 4.2 手动配置
|
||||
|
||||
### EAS方式
|
||||
修改 `android/app/build.gradle` 文件
|
||||
|
||||
### 原生方式
|
||||
1. 修改 `signingConfigs`
|
||||
|
||||
```bash
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file('android-release.keystore') // keystore 文件路径
|
||||
storePassword '你的Keystore密码' // keystore 密码
|
||||
keyAlias '你的KeyAlias' // 密钥别名
|
||||
keyPassword '你的Key密码' // key 密码
|
||||
}
|
||||
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
storePassword 'android'
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. 在 `buildTypes` 中设置 release 使用 release 签名
|
||||
|
||||
```bash
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 4.3 脚本配置(推荐)
|
||||
|
||||
1. 在 expo 项目根目录下新增 `plugins\withAndroidSignature.js` 文件,内容如下:
|
||||
|
||||
```js
|
||||
// plugins/withAndroidSignature.js
|
||||
|
||||
const { withAppBuildGradle } = require("@expo/config-plugins");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = function withAndroidSignature(config) {
|
||||
return withAppBuildGradle(config, config => {
|
||||
if (config.modResults.language === "groovy") {
|
||||
config.modResults.contents = setAndroidSignature(config.modResults.contents);
|
||||
} else {
|
||||
throw new Error("如果不是 groovy,则无法在 app/build.gradle 中设置 signingConfigs");
|
||||
}
|
||||
return config;
|
||||
});
|
||||
};
|
||||
|
||||
function setAndroidSignature(appBuildGradle) {
|
||||
if (!fs.existsSync(path.resolve(__dirname, "../credentials.json"))) {
|
||||
console.warn("警告:没有设置正式版本的 Android Keystore 文件,因为 credentials.json 不存在。");
|
||||
return appBuildGradle;
|
||||
}
|
||||
const info = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../credentials.json"), { encoding: "utf8" }));
|
||||
|
||||
// 使用正则表达式插入签名信息
|
||||
let output = appBuildGradle.replace(
|
||||
/(signingConfigs\s*\{)/,
|
||||
`$1
|
||||
release {
|
||||
storeFile file(${JSON.stringify(path.resolve(__dirname, "../credentials/android-release.keystore"))})
|
||||
storePassword ${JSON.stringify(info.android.keystore.keystorePassword)}
|
||||
keyAlias ${JSON.stringify(info.android.keystore.keyAlias)}
|
||||
keyPassword ${JSON.stringify(info.android.keystore.keyPassword)}
|
||||
}`,
|
||||
);
|
||||
|
||||
// 使用正则表达式替换 signingConfig
|
||||
output = output.replace(
|
||||
/(release\s*\{)[^}]*?signingConfig\s+signingConfigs\.debug/s,
|
||||
`$1
|
||||
signingConfig signingConfigs.release
|
||||
`,
|
||||
);
|
||||
|
||||
return output;
|
||||
}
|
||||
```
|
||||
|
||||
2. 在 expo 项目根目录下新增 `credentials.json` 文件(该文件主要是 Keystore 的信息):
|
||||
|
||||
```json
|
||||
{
|
||||
"android": {
|
||||
"keystore": {
|
||||
"keystorePath": "credentials/android-release.keystore", // Android keystore 文件路径
|
||||
"keystorePassword": "123456", // keystore 密码
|
||||
"keyAlias": "my-key-alias", // Key 别名
|
||||
"keyPassword": "123456" // Key 密码
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"provisioningProfilePath": "ios/certs/profile.mobileprovision", // iOS 描述文件路径
|
||||
"distributionCertificate": {
|
||||
"path": "ios/certs/dist-cert.p12", // iOS 分发证书路径
|
||||
"password": "password" // 证书密码
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. 在 `app.json` 中指定这个项目级插件:
|
||||
|
||||
```json
|
||||
{
|
||||
"expo": {
|
||||
"plugins": [
|
||||
"./plugins/withAndroidSignature"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 5. 编译
|
||||
Reference in new issue
Block a user