移动端开发技术知识库
一、技术分类总览
按渲染方式和技术架构,分为四大阵营:
| 阵营 | 代表技术 | 渲染方式 | 性能 |
|---|---|---|---|
| 自绘引擎 | Flutter | 自带渲染引擎,直接绘制像素 | ⭐⭐⭐⭐⭐ |
| 原生组件映射 | React Native | 映射到原生组件 | ⭐⭐⭐⭐ |
| WebView + 原生桥接 | Ionic / Cordova / PhoneGap | WebView 渲染 HTML/CSS/JS | ⭐⭐ |
| WebView 套壳 | H5 套壳 | 纯 WebView,无桥接 | ⭐ |
二、各技术详解
2.1 Flutter(自绘引擎)
- 原理:自带 Skia 渲染引擎,不依赖平台原生组件,直接在 Canvas 上绘制像素
- 优点:性能最接近原生,UI 一致性极好(各平台看起来完全一样)
- 缺点:包体积大(引擎约 5-10MB),Dart 语言生态相对小,无法直接使用原生组件
- 适用:对性能和 UI 一致性要求高的应用
2.2 React Native(原生组件映射)
- 原理:JS 写 UI → 通过 Bridge 转换 → 调用平台原生组件渲染
- 优点:使用原生组件,体验接近原生;JS 生态丰富;新架构 Fabric + TurboModules 大幅提升性能
- 缺点:Bridge 通信有开销;复杂动画性能不如 Flutter;需要了解原生开发知识
- 适用:已有 JS/React 技术栈的团队
2.3 Ionic / Taro / UniApp(跨端框架)
Ionic
- 本质:WebView 渲染 + Capacitor/Cordova 提供原生 API 桥接
- 技术栈:Angular/React/Vue + HTML/CSS/JS
- 特点:本质还是 WebView 渲染,但通过桥接可以调用原生 API
Taro(京东出品)
- 本质:一套代码编译到多端(小程序、H5、RN)
- 技术栈:React/Vue 语法 → 编译到各端
- 特点:核心优势是跨小程序端(微信/支付宝/百度等),不是追求原生性能
UniApp(DCloud 出品)
- 本质:类似 Taro,一套代码编译到多端
- 技术栈:Vue 语法 → 编译到各端
- 特点:生态更完善,插件市场丰富;App 端底层用 WebView + weex(部分原生渲染)
Taro 和 UniApp 的核心价值:不是"高性能 App",而是"一套代码跑小程序 + H5 + App",解决的是多端维护成本问题。
2.4 Cordova / PhoneGap(WebView + 原生桥接)
-
原理 :
arduinoHTML/CSS/JS(WebView 渲染) ↕ JavaScript Bridge 原生 API(相机、GPS、文件系统等) -
Cordova:Apache 开源项目,提供原生 API 插件机制
-
PhoneGap:Adobe 出品,本质是 Cordova 的发行版(已停止维护)
-
核心机制 :通过
cordova.exec()调用原生插件,插件用 Java/ObjC 写,JS 端通过 Bridge 调用
2.5 H5 套壳(纯 WebView 包装)
-
原理 :
css原生 App(壳)→ 只有一个 WebView 组件 → 加载远程/本地 HTML -
本质:就是一个原生 App 里放了一个全屏浏览器,加载你的网页
-
实现方式 :
- Android:一个
Activity+WebView - iOS:一个
UIViewController+WKWebView
- Android:一个
三、H5 套壳 vs Cordova 的区别
| 对比项 | H5 套壳 | Cordova |
|---|---|---|
| 渲染方式 | WebView | WebView(一样) |
| 渲染性能 | 一样慢 | 一样慢 |
| 原生 API 访问 | ❌ 默认不能 | ✅ 通过插件桥接 |
| JS 调原生能力 | 无桥接机制 | 有 cordova.exec() Bridge |
| 插件生态 | 无 | 丰富的插件市场 |
| 开发复杂度 | 极低(10行代码) | 低(需配置 Cordova 项目) |
| 本质区别 | 纯壳,无通信 | 壳 + 通信桥接 |
H5 套壳能使用原生 API 吗?
默认不能。纯 H5 套壳就是:
- WebView 里的 JS 只能调用浏览器标准 API(
navigator.geolocation等) - 无法调用相机、推送、蓝牙、通讯录等原生能力
- 除非自己写桥接(类似自己实现一个简化版 Cordova)
如果想在 H5 套壳里调用原生 API,有两条路:
- 自己写 JS Bridge:原生端注册 handler,JS 端通过
window.webkit.messageHandlers(iOS)或WebView.addJavascriptInterface(Android)通信 - 直接用 Cordova:它已经帮你做好了这件事
Cordova 本质上 = H5 套壳 + 原生 API 桥接 + 插件生态
四、WebView、Bridge、桥接能力
4.1 WebView 是什么?
WebView 就是移动端操作系统内嵌的一个"浏览器内核组件"。
ini
Chrome 浏览器 = 地址栏 + 标签页 + 书签 + 前进后退按钮 + 渲染引擎
WebView = 只有渲染引擎(去掉浏览器外壳)
各平台的 WebView:
| 平台 | WebView 组件 | 底层内核 |
|---|---|---|
| Android | android.webkit.WebView |
Chromium(4.4+) |
| iOS | WKWebView |
WebKit(Safari 同内核) |
| 鸿蒙 | Web 组件 |
Chromium 内核 |
代码层面的理解(Android):
xml
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
java
WebView webView = findViewById(R.id.webview);
webView.loadUrl("https://www.baidu.com");
webView.loadUrl("file:///android_asset/index.html");
iOS 端:
swift
let webView = WKWebView(frame: view.bounds)
webView.load(URLRequest(url: URL(string: "https://www.baidu.com")!))
view.addSubview(webView)
WebView 能做什么:
- ✅ 渲染 HTML/CSS/JS(和浏览器一模一样)
- ✅ 加载远程 URL 或本地 HTML 文件
- ✅ 执行 JavaScript 代码
- ❌ 默认不能调用原生 API(相机、GPS、推送等)
- ❌ 没有浏览器地址栏、导航栏等 UI
4.2 Bridge 是什么?
Bridge(桥)是 WebView 里的 JS 和原生代码之间通信的通道。
为什么需要 Bridge:
diff
你的 H5 页面里有一个按钮:"拍照上传"
JS 想做的事:调用手机摄像头 → 拍照 → 拿到照片 → 上传
问题:
- JS 运行在 WebView 里(浏览器环境)
- 浏览器环境没有"调用摄像头"这个原生 API
- 摄像头 API 只存在于原生代码中(Java/Kotlin/Swift)
JS 和原生代码,就像隔了一条河的两个岛,互不相通
arduino
┌─────────────────┐ ┌─────────────────┐
│ WebView 岛 │ 河 │ 原生岛 │
│ │ ←无法通信→ │ │
│ JS 代码 │ │ Java/Swift 代码 │
│ 想调摄像头 ❌ │ │ 有摄像头 API ✅ │
└─────────────────┘ └─────────────────┘
↓ 加 Bridge ↓
┌─────────────────┐ ┌─────────────────┐
│ WebView 岛 │ │ 原生岛 │
│ │ Bridge │ │
│ JS 代码 │ ════════ │ Java/Swift 代码 │
│ 调用摄像头 ✅ │ 通信通道 │ 有摄像头 API ✅ │
└─────────────────┘ └─────────────────┘
Bridge 支持双向通信:
arduino
方向1:JS → 原生(JS 调用原生能力)
JS: "帮我打开摄像头"
→ Bridge 传递消息 →
原生: 打开摄像头,返回照片
方向2:原生 → JS(原生通知 JS)
原生: "收到一条推送通知"
→ Bridge 传递消息 →
JS: 在页面上显示通知
Bridge 的底层实现:
Android 端(方式1:addJavascriptInterface):
java
webView.addJavascriptInterface(new Object() {
@JavascriptInterface
public void openCamera() {
// 调用原生摄像头
}
}, "NativeBridge");
// JS 端:window.NativeBridge.openCamera()
Android 端(方式2:prompt 拦截):
java
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result) {
if (message.equals("openCamera")) {
openCamera();
result.confirm("success");
return true;
}
return false;
}
});
// JS 端:prompt("openCamera")
iOS 端:
swift
// 原生 → JS 调用
let contentController = WKUserContentController()
contentController.add(self, name: "NativeBridge")
// JS 端:window.webkit.messageHandlers.NativeBridge.postMessage("openCamera")
// 原生调 JS
webView.evaluateJavaScript("onPhotoReceived('photo_base64')")
Bridge 通信的数据格式(通常使用 JSON):
json
{
"method": "openCamera",
"params": { "quality": "high", "maxSize": 1024 },
"callbackId": "cb_001"
}
json
{
"callbackId": "cb_001",
"status": "success",
"data": { "photoPath": "/path/to/photo.jpg" }
}
4.3 桥接能力是什么?
桥接能力 = 通过 Bridge 暴露给 JS 调用的原生功能的集合。
| 能力分类 | 具体功能 | JS 原生能做吗 | 需要桥接吗 |
|---|---|---|---|
| 设备信息 | 获取设备型号、系统版本 | ❌ | ✅ |
| 相机 | 拍照、录像、扫码 | ❌ | ✅ |
| 地理位置 | GPS 定位 | 部分(精度低) | ✅ |
| 文件系统 | 读写本地文件 | ❌ | ✅ |
| 推送通知 | 发送/接收通知 | ❌ | ✅ |
| 蓝牙 | 连接蓝牙设备 | ❌ | ✅ |
| 通讯录 | 读取联系人 | ❌ | ✅ |
| 生物识别 | 指纹/面容识别 | ❌ | ✅ |
不同框架的桥接能力:
arduino
H5 套壳: 无桥接能力(除非自己写)
Cordova: 丰富的插件生态(1000+ 插件)
Ionic: 使用 Capacitor(Cordova 的现代替代)
React Native:自有 Bridge + TurboModules
Flutter: Platform Channel(自研桥接机制)
4.4 完整调用流程示例(拍照上传)
arduino
用户点击 H5 页面的"拍照"按钮
│
▼
JS 调用:window.NativeBridge.call('openCamera', {quality: 'high'})
│
▼ Bridge 传递
│
原生端收到消息:解析 method = "openCamera"
│
▼
原生调用系统 API:Camera.open() → 拍照 → 获取照片
│
▼ Bridge 回传
│
JS 收到回调:callback({photoPath: "/path/to/photo.jpg"})
│
▼
JS 将照片显示在页面上 / 上传到服务器
三者关系:WebView(载体)+ Bridge(通道)+ 桥接能力(功能)= 混合开发 App
五、Swift 原生 vs Flutter vs React Native
5.1 本质区别
arduino
Swift 原生开发: 代码 → 直接编译为机器码 → 运行在 iOS 设备上
Flutter: Dart 代码 → 编译为 ARM 机器码 → 自绘引擎渲染 UI
React Native: JS 代码 → Bridge → 调用 iOS 原生组件渲染
| 维度 | Swift 原生 | Flutter | React Native |
|---|---|---|---|
| 语言 | Swift | Dart | JavaScript |
| UI 渲染 | iOS 原生组件 | 自绘引擎(Skia) | 映射到原生组件 |
| 编译产物 | 原生机器码 | 原生机器码 | JS Bundle + 原生壳 |
| 平台支持 | 仅 iOS/macOS | iOS + Android + Web + 桌面 | iOS + Android |
| 运行性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐½ | ⭐⭐⭐⭐ |
5.2 UI 渲染机制的区别
Swift 原生 ------ 直接使用系统组件
objectivec
Swift 代码 → 直接调用 iOS UIKit/SwiftUI 组件 → 系统渲染(UILabel, UIView 等)
- 用的是 Apple 自己的组件,外观、动画、交互 100% 符合 iOS 规范
- 系统更新组件样式,App 自动跟着变
Flutter ------ 自己画一切
css
Dart 代码 → Flutter Framework(Widget 树)→ Skia 渲染引擎 → 直接在 Canvas 上画像素
- 完全不使用 iOS 原生组件,Flutter 自己用 Skia 画了一个"Text"、一个"Button"
- iOS 和 Android 上看起来一模一样(都是画出来的)
- 代价:和系统原生风格有细微差异,系统更新 UI 风格时 Flutter 不会自动跟随
React Native ------ 映射到原生组件
objectivec
JSX 代码 → React Native 解析 → Bridge 传递指令 → iOS 端创建真正的 UIView/UILabel → 系统渲染
<Text>在 iOS 上真的创建了一个UILabel- 渲染出来的是真正的 iOS 原生组件,外观和原生一致
- 代价:JS 和原生之间 Bridge 通信有延迟
5.3 性能对比
| 场景 | Swift | Flutter | RN |
|---|---|---|---|
| 简单页面 | 极快 | 极快 | 快 |
| 复杂列表 | 极快 | 很快 | 较快(需优化) |
| 复杂动画 | 极快 | 很快 | 一般 |
| 频繁交互 | 极快 | 很快 | Bridge 可能卡顿 |
RN 的性能瓶颈(旧架构):
arduino
JS 线程 Bridge(序列化/反序列化) 原生线程
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ JS 逻辑 │ ──JSON消息──→ │ Bridge │ ──解析消息──→ │ 原生组件 │
│ 虚拟 DOM │ ←─JSON消息── │ (异步队列) │ ←─回传结果── │ 渲染执行 │
└──────────┘ └──────────────┘ └──────────┘
问题:每次交互都要跨 Bridge → 序列化 → 反序列化 → 异步等待
RN 新架构(Fabric + TurboModules):
scss
JS 线程 JSI(直接引用) 原生线程
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ JS 逻辑 │ ──C++直接调用─→ │ JSI │ ──同步调用──→ │ 原生组件 │
│ 虚拟 DOM │ ←──直接返回─── │ (同步桥接) │ ←─直接返回─── │ 渲染执行 │
└──────────┘ └──────────────┘ └──────────┘
改进:JSI 允许 JS 直接持有 C++ 对象引用,无需序列化
5.4 开发体验对比
| Swift | Dart/Flutter | JavaScript/RN | |
|---|---|---|---|
| 学习曲线 | 中等 | 低(类似 JS + Java) | 低(前端开发者熟悉) |
| 类型系统 | 强类型,优秀 | 强类型,优秀 | 弱类型(TS 可弥补) |
| 生态规模 | Apple 生态,丰富 | Flutter 生态,够用 | npm 最大生态 |
| 热重载 | ❌ 需重新编译 | ✅ 秒级热重载 | ✅ 秒级热重载 |
5.5 平台能力访问
erlang
Swift: 100% 能力,直接调用,零成本
Flutter: 90% 能力有现成插件,10% 需自己写原生代码桥接
RN: 90% 能力有现成库,10% 需自己写原生代码桥接
常用能力(相机、定位、推送)→ 三个方案都能轻松搞定
冷门能力(ARKit、HealthKit、HomeKit)→ Swift 直接用,Flutter/RN 要自己写桥接
新出的 iOS API → Swift 立刻能用,Flutter/RN 要等插件或自己实现
5.6 App 体积对比
Swift 原生 App: ~2-5 MB(空项目)
Flutter App: ~15-20 MB(含 Skia 引擎 + Dart 运行时)
React Native App: ~8-12 MB(含 JSC/Hermes 引擎 + JS Bundle)
5.7 选型建议
选 Swift 原生:
✅ 只做 iOS 平台,不需要 Android
✅ 深度依赖 iOS 专有功能(ARKit、HealthKit、SiriKit 等)
✅ 对性能要求极致(游戏、视频编辑、实时音频处理)
✅ 追求最完美的 iOS 体验和系统一致性
选 Flutter:
✅ 需要 iOS + Android 双端,且追求高性能
✅ UI 复杂、动画多、自定义程度高
✅ 未来可能扩展到 Web / 桌面
✅ 对 UI 一致性要求高(双端看起来一样)
选 React Native:
✅ 需要 iOS + Android 双端
✅ 团队已有 React/JS 技术栈
✅ 内容展示类 App(电商、社交、资讯)
✅ 希望复用 Web 端的 JS 逻辑/状态管理
✅ 需要热更新(App Store 不用重新审核)
六、最小启动步骤
6.1 Swift(iOS 原生)
bash
# 前置:安装 Xcode(App Store 下载)
# 方式1:命令行创建
mkdir MySwiftApp && cd MySwiftApp
# 用 Xcode 打开:File → New → Project → iOS → App → SwiftUI
open -a Xcode .
# 方式2:命令行直接创建(Xcode 14+)
# 在 Xcode 中:Product → Run(⌘R)
最小 SwiftUI 代码:
swift
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
Text("Hello, iOS!")
}
}
}
6.1b Kotlin(Android 原生)
bash
# 前置:安装 Android Studio
# 创建项目
# Android Studio → New Project → Empty Activity → Kotlin
# 包名:com.example.myapp
# 最低 SDK:API 24: Android 7.0
最小 Kotlin 代码(MainActivity.kt):
kotlin
package com.example.myapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello, Android!")
}
}
}
Gradle 依赖(build.gradle.kts):
kotlin
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.activity:activity-compose:1.8.0")
implementation(platform("androidx.compose:compose-bom:2024.02.00"))
implementation("androidx.compose.material3:material3")
}
6.2 Flutter
bash
# 前置:安装 Flutter SDK
# https://docs.flutter.dev/get-started/install/macos
# 创建项目
flutter create my_app
cd my_app
# 运行(连接设备或启动模拟器)
flutter run
最小 Flutter 代码(已自动生成在 lib/main.dart):
dart
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Scaffold(body: Center(child: Text('Hello, Flutter!'))),
));
6.3 React Native
bash
# 方式1:Expo(推荐新手,零配置)
npx create-expo-app my_app
cd my_app
npx expo start
# 方式2:React Native CLI(完整原生访问)
npx react-native init MyApp
cd MyApp
npx react-native run-ios
最小 RN 代码(App.tsx):
tsx
import { Text, View } from 'react-native';
export default function App() {
return <View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
<Text>Hello, RN!</Text>
</View>;
}
6.4 Ionic
bash
# 前置:Node.js >= 16
npm install -g @ionic/cli
# 创建项目(选 Vue/React/Angular)
ionic start myApp tabs --type=vue
cd myApp
# 浏览器预览
ionic serve
# 添加平台并运行
ionic cap add ios
ionic cap run ios
6.5 UniApp
bash
# 方式1:CLI 创建(Vue3)
npx degit dcloudio/uni-preset-vue#vite myApp
cd myApp
npm install
npm run dev:h5 # H5 预览
npm run dev:mp-weixin # 微信小程序预览
# 方式2:HBuilderX(官方 IDE,可视化创建)
# 下载 HBuilderX → 新建项目 → uni-app → 运行
6.6 Taro
bash
# 创建项目
npx @tarojs/cli init myApp
cd myApp
npm install
# 运行到不同端
npm run dev:h5 # H5
npm run dev:weapp # 微信小程序
npm run dev:rn # React Native
6.7 Cordova
bash
# 前置:Node.js + Android SDK / Xcode
npm install -g cordova
# 创建项目
cordova create myApp com.example.myapp MyApp
cd myApp
# 添加平台
cordova platform add ios
cordova platform add android
# 运行
cordova run ios
cordova run android
6.8 H5 套壳(最小实现)
iOS 端(SwiftUI):
swift
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.load(URLRequest(url: URL(string: "https://your-h5-site.com")!))
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}
@main
struct ShellApp: App {
var body: some Scene {
WindowGroup { WebView() }
}
}
Android 端(Kotlin):
kotlin
// MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val webView = WebView(this)
webView.settings.javaScriptEnabled = true
webView.loadUrl("https://your-h5-site.com")
setContentView(webView)
}
}
七、快速选型速查
css
追求性能 → Flutter > React Native > Ionic/Cordova > H5套壳
追求跨端(含小程序)→ UniApp / Taro
追求开发速度(已有H5)→ H5套壳(但功能受限)
需要原生API + 已有H5 → Ionic / Cordova
团队已有React → React Native
团队已有Vue → UniApp
只做 iOS → Swift
只做 Android → Kotlin
八、打包与发布
8.1 各技术打包产物概览
| 技术 | iOS 产物 | Android 产物 | 打包工具 |
|---|---|---|---|
| Swift 原生 | .ipa |
--- | Xcode |
| Kotlin 原生 | --- | .apk / .aab |
Android Studio / Gradle |
| Flutter | .ipa |
.apk / .aab |
flutter build |
| React Native | .ipa |
.apk / .aab |
Xcode / Gradle / Expo |
| Ionic | .ipa |
.apk / .aab |
ionic cap build / Xcode / Gradle |
| Cordova | .ipa |
.apk / .aab |
cordova build / Xcode / Gradle |
| UniApp | .ipa |
.apk / .aab |
HBuilderX 云打包 / 本地打包 |
| Taro | .ipa(RN端) |
.apk / .aab(RN端) |
依赖 RN 打包流程 |
| H5 套壳 | .ipa |
.apk / .aab |
取决于壳的编写方式 |
APK vs AAB:Google Play 自 2021 年 8 月起要求新应用必须使用 AAB(Android App Bundle)格式上传,AAB 会根据用户设备动态分发所需资源,体积更小。APK 仍可用于侧载或国内应用市场。
8.2 iOS 打包流程(所有技术通用)
前置条件
markdown
1. Apple Developer 账号($99/年,个人或公司)
2. Mac 电脑(Xcode 仅限 macOS)
3. 真机设备(用于测试,模拟器无法测试推送、相机等)
完整流程
bash
# Step 1: 申请 Apple Developer 账号
# https://developer.apple.com → 注册 → 支付 $99/年
# Step 2: 创建证书和描述文件(Xcode 自动管理或手动)
# 方式A:Xcode 自动签名(推荐新手)
# Xcode → Target → Signing & Capabilities → Team → 选择你的 Apple ID
# 勾选 "Automatically manage signing"
# 方式B:手动管理(企业/多人协作)
# Apple Developer Portal → Certificates → 创建 Distribution 证书
# → Identifiers → 创建 App ID(Bundle ID 如 com.example.myapp)
# → Profiles → 创建 Ad Hoc / App Store 描述文件
# Step 3: 配置应用信息
# Info.plist:应用名称、Bundle ID、权限描述(相机、定位等)
# Assets.xcassets:App Icon(1024x1024)、Launch Screen
# Step 4: 构建 Release 版本
# Xcode → Product → Scheme → Edit Scheme → Run → Build Configuration → Release
# Product → Archive(⌘+Shift+U)
# Step 5: 导出或上传
# Organizer(Window → Organizer)→ 选择 Archive → Distribute App
# → App Store Connect → Upload 或 Export
# Step 6: App Store Connect 提交
# https://appstoreconnect.apple.com
# → 我的 App → 新建 App → 填写元数据(名称、描述、截图、关键词)
# → 选择构建版本 → 提交审核
# 审核时间:通常 1-3 个工作日
各技术的 iOS 打包命令
bash
# Flutter
flutter build ios --release
# 然后 Xcode → Product → Archive
# React Native(CLI)
cd ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release archive
# React Native(Expo)
npx expo prebuild
npx expo run:ios --configuration Release
# 或 EAS Build(云端打包)
npx eas build --platform ios
# Ionic
cd ios && xcodebuild -workspace App.xcworkspace -scheme App -configuration Release archive
# Cordova
cordova build ios --release --device
# 然后 Xcode → Product → Archive
# UniApp
# HBuilderX → 发行 → 原生 App-云打包 → 选择 iOS 证书 → 打包
8.3 Android 打包流程(所有技术通用)
前置条件
markdown
1. Android Studio
2. JDK 17+
3. 签名密钥(Release 版本必须)
完整流程
bash
# Step 1: 生成签名密钥(只需做一次,妥善保管)
keytool -genkey -v \
-keystore my-release-key.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias my-alias
# 会要求输入:
# - 密钥库密码
# - 密钥密码(可与库密码相同)
# - 姓名、组织、城市等信息
# Step 2: 配置签名(各技术配置位置不同,原理相同)
Gradle 签名配置(android/app/build.gradle 或 android/build.gradle):
gradle
android {
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "your-store-password"
keyAlias "my-alias"
keyPassword "your-key-password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true // 代码混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
生产环境不要把密码写死在代码里,使用环境变量或
local.properties:
properties
# local.properties(不提交到 Git)
STORE_FILE=my-release-key.jks
STORE_PASSWORD=your-password
KEY_ALIAS=my-alias
KEY_PASSWORD=your-password
gradle
// build.gradle 中读取
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
signingConfigs {
release {
storeFile file(properties.getProperty('STORE_FILE'))
storePassword properties.getProperty('STORE_PASSWORD')
keyAlias properties.getProperty('KEY_ALIAS')
keyPassword properties.getProperty('KEY_PASSWORD')
}
}
bash
# Step 3: 构建 Release
# APK(国内应用市场、侧载)
./gradlew assembleRelease
# 产物:android/app/build/outputs/apk/release/app-release.apk
# AAB(Google Play 必需)
./gradlew bundleRelease
# 产物:android/app/build/outputs/bundle/release/app-release.aab
# Step 4: 上传应用市场
# Google Play Console: https://play.google.com/console
# 国内:华为、小米、OPPO、vivo、应用宝等各自开发者后台
各技术的 Android 打包命令
bash
# Flutter
flutter build apk --release # APK
flutter build appbundle --release # AAB
# React Native(CLI)
cd android && ./gradlew assembleRelease # APK
cd android && ./gradlew bundleRelease # AAB
# React Native(Expo)
npx eas build --platform android # EAS 云端打包
# Ionic
cd android && ./gradlew assembleRelease
# Cordova
cordova build android --release
# UniApp
# HBuilderX → 发行 → 原生 App-云打包 → 选择 Android 证书 → 打包
8.4 小程序打包(UniApp / Taro)
bash
# UniApp
npm run build:mp-weixin # 编译到微信小程序
# 然后用微信开发者工具 → 导入 dist/build/mp-weixin → 上传
# Taro
npm run build:weapp # 编译到微信小程序
# 同样用微信开发者工具上传
# 微信小程序发布流程:
# 1. 微信开发者工具 → 上传(填写版本号)
# 2. 微信公众平台 → 版本管理 → 提交审核
# 3. 审核通过 → 发布
8.5 签名与证书管理
| 平台 | 证书类型 | 有效期 | 丢失后果 |
|---|---|---|---|
| iOS | Distribution Certificate | 1 年 | 需重新生成,不影响已上架 App |
| iOS | Provisioning Profile | 1 年 | 需重新生成,不影响已上架 App |
| Android | Keystore (.jks) | 25 年+ | 永久丢失无法更新 App |
Android 的 Keystore 一旦丢失,永远无法用相同包名发布更新,Google Play 和国内市场都要求相同的签名。务必备份到安全位置。
九、热更新方案
9.1 什么是热更新?
热更新 = 不经过应用商店审核,直接下发代码/资源更新到用户设备。
传统更新:发现 Bug → 修复 → 打包 → 提交审核 → 等待 1-3 天 → 用户下载更新
热更新: 发现 Bug → 修复 → 上传补丁 → 秒级生效 → 用户下次打开自动更新
9.2 各技术支持情况
| 技术 | 热更新支持 | 方案 | 限制 |
|---|---|---|---|
| Swift 原生 | ❌ 不支持 | --- | Apple 禁止热更新原生代码 |
| Kotlin 原生 | ❌ 不支持 | --- | Google 限制较少,但原生代码热更新也不推荐 |
| Flutter | ⚠️ 有限支持 | shorebird、flutter_code_push | 社区方案,非官方 |
| React Native | ✅ 支持 | CodePush、Expo Updates | JS Bundle 可热更新,原生模块不行 |
| Ionic / Cordova | ✅ 支持 | CodePush、自定义实现 | Web 资源可热更新 |
| UniApp | ✅ 支持 | DCloud 云打包热更新 | 官方支持,WGT 资源包更新 |
| Taro | ⚠️ 有限支持 | 依赖 RN 端的热更新能力 | H5/小程序端天然支持(就是网页) |
9.3 React Native 热更新(CodePush)
bash
# 安装 App Center CLI
npm install -g appcenter-cli
# 登录
appcenter login
# 发布更新
appcenter codepush release-react -a MyOrg/MyApp -d Production
javascript
// App.js 中集成
import codePush from 'react-native-code-push';
function App() {
// ...
}
export default codePush({
checkFrequency: codePush.CheckFrequency.ON_APP_RESUME
})(App);
9.4 UniApp 热更新
bash
# HBuilderX → 发行 → 制作应用 wgt 包
# 将 wgt 包上传到服务器
# App 中检查更新
uni.request({
url: 'https://your-server.com/check-update',
success: (res) => {
if (res.data.hasUpdate) {
uni.downloadFile({
url: res.data.wgtUrl,
success: (downloadRes) => {
uni.installUpdate({
filePath: downloadRes.tempFilePath
});
}
});
}
}
});
9.5 Apple 对热更新的限制
arduino
Apple App Store 审核指南 2.5.2:
"App 不得下载或安装可执行代码"
允许:
✅ JS 脚本解释执行(RN、WebView 内的 JS)
✅ 资源文件更新(图片、配置)
✅ 使用 Apple 的 JavaScriptCore 框架
禁止:
❌ 下载并执行原生机器码
❌ 使用 dlopen、dlsym 等动态加载
❌ 绕过审核机制更新核心功能
十、调试方式
10.1 各技术调试工具
| 技术 | 调试工具 | 断点调试 | UI 检查 | 性能分析 |
|---|---|---|---|---|
| Swift | Xcode | ✅ LLDB | ✅ View Debugger | ✅ Instruments |
| Kotlin | Android Studio | ✅ | ✅ Layout Inspector | ✅ Profiler |
| Flutter | Flutter DevTools | ✅ | ✅ Widget Inspector | ✅ Performance |
| React Native | Chrome DevTools / Flipper | ✅ | ✅ Element Inspector | ✅ Hermes Profiler |
| Ionic | Chrome DevTools | ✅ | ✅ | ❌(依赖浏览器工具) |
| UniApp | HBuilderX / 微信开发者工具 | ❌ | ✅ | ❌ |
| Taro | 微信开发者工具 / Chrome | ❌ | ✅ | ❌ |
10.2 真机调试
bash
# iOS 真机调试
# 1. 用数据线连接 iPhone
# 2. Xcode → Window → Devices and Simulators → 信任设备
# 3. 选择真机 → Run(⌘R)
# 4. 设置 → 隐私与安全性 → 开发者模式(iOS 16+)
# Android 真机调试
# 1. 开启开发者选项:设置 → 关于手机 → 连点版本号 7 次
# 2. 开启 USB 调试
# 3. adb devices 确认连接
# 4. Android Studio 或命令行运行
10.3 日志查看
bash
# iOS 日志
# Xcode → Window → Devices and Simulators → 选择设备 → Open Console
# 或命令行:
idevicesyslog | grep MyApp
# Android 日志
adb logcat -s "MyApp:D" # 过滤特定 Tag
adb logcat | grep flutter # Flutter 日志
adb logcat | grep ReactNativeJS # RN 日志
十一、鸿蒙 HarmonyOS(补充)
11.1 鸿蒙开发技术
| 技术 | 说明 | 适用场景 |
|---|---|---|
| ArkTS(原生) | 鸿蒙官方语言,TypeScript 超集 | 追求最佳性能和体验 |
| ArkUI(声明式 UI) | 类似 SwiftUI / Flutter 的声明式语法 | 鸿蒙原生 App |
| 元服务(Atomic Service) | 免安装、卡片化 | 轻量服务 |
| 跨平台框架适配 | Flutter、RN 已有鸿蒙适配版本 | 已有跨平台项目迁移 |
11.2 最小启动步骤(ArkTS)
bash
# 前置:安装 DevEco Studio(鸿蒙官方 IDE)
# https://developer.harmonyos.com
# 创建项目
# DevEco Studio → Create Project → Empty Ability → ArkTS
最小 ArkTS 代码(Index.ets):
typescript
@Entry
@Component
struct Index {
build() {
Column() {
Text('Hello, HarmonyOS!')
.fontSize(24)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
11.3 鸿蒙打包
bash
# DevEco Studio → Build → Build Hap(s)/App(s)
# 产物:.hap(HarmonyOS Package)
# 发布:华为 AppGallery Connect