环境安装。
- 关于C++组件
对于 Windows 用户,请确保至少安装了 Win10 SDK(10.0.19041.0) 和 Visual Studio Build Tools 2022(版本 17.2 或更高),此外还需要安装以下组件:
Microsoft Visual C++ 2015-2022 Redistributable (x64)
Microsoft Visual C++ 2015-2022 Redistributable (x86)
Microsoft Visual C++ 2012 Redistributable (x86)(可选)
Microsoft Visual C++ 2013 Redistributable (x86)(可选)
Microsoft Visual C++ 2008 Redistributable (x86)(可选)
- Rust版本,最新稳定版即可,我已经升到1.70了。并且需要包含安卓的所有跨跨平台编译器。参考上面的链接就是需要运行这个命令了。
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
- Nodejs/npm/pnpm安装。nodejs选择最新的lts版本就好了,当前应该是18.12,npm装完nodejs自带就有。pnpm可以用npm安装。例如用这个命令:
npm install -g pnpm
- 需要安卓Android Studio开发工具,安装最新版即可。
- SDK安装:打开Android Studio,选择
Tool
-SDK Manager
,然后安装你想要安装的SDK版本。以我为例,我的手机是安卓12,我想打包后的apk兼容安卓9-13,那就勾选完9-13的所有SDK,然后点击Apply
即可开始下载(或许需要外网环境)。 - NDK安装:打开Android Studio,选择
Tool
-SDK Manager
,还是上面哪个界面,点击SDK Tools
,需要安装Android SDK Build-Tools
,NDK (Side by Side)
,Android SDK Command Tools (Latest)
,Cmake
,Android Auto API Simulatros
,Android Emulator
(安卓模拟器),Android Emulator Hypervisor Driver (installer)
,Android SDK Platform-Tools
,Google USB Driver
(谷歌USB驱动,用于adb调试),Google Web Driver
(谷歌wifi驱动,用于adb wifi调试),Intel X86 Emulator Accelerator (HAXM installer)
,然后点击Apply
开始下载。 - 拷贝SDK路径:打开Android Studio,选择
Tool
-SDK Manager
,还是上面哪个界面,将Android SDK Locations
后面的路径拷贝一下,我的显示是:C:\Users\dsz\AppData\Local\Android\Sdk
- 环境设置。对于Win11:打开
Windows设置
-系统
-系统信息
-高级系统设置
-环境变量
。在用户环境,新建用户变量。下面是几个需要构建的变化。
- 变量名:
ANDROID_HOME
,变量值:C:\Users\dsz\AppData\Local\Android\Sdk
(这个路径是从刚刚上一步拷贝而来的) - 变量名:
JAVA_HOME
,变量值:C:\Program Files\Android\Android Studio\jbr
(这个路径需要根据你的Android Studio安装目录决定,我是默认安装位置,所以就是这个了。) - 变量名:
NDK_HOME
,变量值:C:\Users\dsz\AppData\Local\Android\Sdk\ndk\25.2.9519653
(注意这个路径需要你去C:\Users\你的用户名\AppData\Local\Android\Sdk\ndk
找找看,版本号不一定是我这个。 - 然后再找到用户变量的
Path变量
,选择编辑。
- 然后再新建三个路径(需要根据你的用户名找到对应的路径):
C:\Program Files\Android\Android Studio\jbr\bin
这个提供了一些java运行命令以及最后apk签名的工具。C:\Users\dsz\AppData\Local\Android\Sdk\platform-tools
这个下面提供了一些adb工具,可以用来控制你的手机安装软件。C:\Users\dsz\AppData\Local\Android\Sdk\build-tools\34.0.0
这个下面是一些apk查看,编辑的工具,可以用来定位apk错误信息。- 参考截图如下:
- 保存完环境变量后,需要验证一下。打开powershell。输入下面几个命令,如果没有提示找不到xxx,则说明ok。
java --version
rustc --version
cargo --version
adb --version
node --version
npm --version
pnpm --version
aapt
jarsigner --help
keytool --help
构建Demo
- 用pnpm创建Demo
pnpm create tauri-app
1. 我写的项目名是:tauri_demo
? Project Name: tauri_demo
2. 直接回车即可,默认是TypeScript/JavaScript
? Choose which language to use for your frontend
❯ TypeScript / JavaScript (pnpm, yarn, npm)
Rust
3. 直接回车即可,默认是pnpm
? Choose your package manager ›
❯ pnpm
yarn
npm
4. 直接回车即可,默认是Vanilla
? Choose your UI template
❯ Vanilla
Vue
Svelte
React
Solid
Angular
5. 直接回车即可,默认是TypeScript
? Choose your UI flavor ›
❯ TypeScript
JavaScript
- 用Vscode打开
tauri_demo
目录,然后终端运行下面的命令,安装web依赖,
pnpm install
- 打开
tauri_demo/src-tauri/Cargo.toml
文件,可以看到目前该项目依赖是Tauri 1.4,而不是Tauri 2.0。
[dependencies]
tauri = { version = "1.4", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
迁移项目到Tauri 2.0
- 进入到上面构建的tauri_demo目录,运行下面两个命令来升级tauri 2.0
pnpm update @tauri-apps/cli@next @tauri-apps/api@next
Packages: +3 -3
+++---
dependencies:
- @tauri-apps/api 1.4.0
+ @tauri-apps/api 2.0.0-alpha.5
devDependencies:
- @tauri-apps/cli 1.4.0
+ @tauri-apps/cli 2.0.0-alpha.10
Progress: resolved 49, reused 18, downloaded 0, added 3, done
- 可以看到tauri版本从1.4升级到了2.0.0-alpha
- 再进入tauri_demo项目下面的src-tauri目录
cd src-tauri
- 观察tauri github项目主页:https://github.com/tauri-apps/tauri
- 主页下面有一个表格,里面写了最新tauri版本。可以看到tauri最新版是
v2.0.0-alpha.10
,tauri-build最新版是v2.0.0-alpha.6
,tauri-cli最新版是v2.0.0-alpha.10
- 运行下面的命令,来更新rust项目中需要的tauri版本。
cargo add tauri@2.0.0-alpha.10
cargo add tauri-build@2.0.0-alpha.6 --build
cargo install tauri-cli --version "^2.0.0-alpha"
- 第一条命令运行出错了,
error: unrecognized feature for crate tauri: shell-open
- 需要将
src-tauri/Cargo.toml
中的features = ["shell-open"]
去掉,然后重新运行第一条命令。 - 最后测试一下是否ok,如果没报错,说明是ok的。
cargo tauri android --help
Android commands
Usage: cargo tauri android [OPTIONS] <COMMAND>
Commands:
init Initializes a Tauri Android project
open Open project in Android Studio
dev Android dev
build Android build
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose... Enables verbose logging
-h, --help Print help
-V, --version Print version
- 升级完工具后,还需要升级一下代码。用Vscode打开项目
tauri_demo
。 - 修改一下端口和服务。打开项目根目录的
vite.config.ts
,里面有一段代码定义了端口:
server: {
port: 1420,
strictPort: true,
},
- 但是我测试发现1420太小了,普通用户不能用这个端口,会报错,于是我改成了14200,顺便加上了host:
0.0.0.0
,改完后配置如下:
server: {
port: 14200,
host: "0.0.0.0",
strictPort: true,
},
- 顺便将
src-tauri/tauri.config/.json
下面的devPath的1420改成14200。改完长这样:
"devPath": "http://localhost:14200",
- 然后发现
src-tauri/tauri.config/.json
中allowlist
有波浪线提示,说这个属性无法解析,所以allow_list以及对应值都需要干掉。顺便将identityfier改成你的用户名,改完后长这样:
{
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:14200",
"distDir": "../dist",
"withGlobalTauri": true
},
"package": {
"productName": "tauri_demo",
"version": "0.0.0"
},
"tauri": {
"bundle": {
"active": true,
"targets": "all",
"identifier": "com.tauri.tlntin",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
},
"security": {
"csp": null
},
"windows": [
{
"fullscreen": false,
"resizable": true,
"title": "tauri_demo",
"width": 800,
"height": 600
}
]
}
}
- 根据这个链接:https://next--tauri.netlify.app/next/mobile/development/integrate, 还需要做一些代码层面修改。
- 修改:
src-tauri/Cargo.toml
目录,末尾新增下面这段代码,让安卓可以使用静态/动态库。
[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
- 新增
src-tauri/src/lib.rs
内容如下:
use tauri::App;
#[cfg(mobile)]
mod mobile;
#[cfg(mobile)]
pub use mobile::*;
pub type SetupHook = Box<dyn FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send>;
#[derive(Default)]
pub struct AppBuilder {
setup: Option<SetupHook>,
}
impl AppBuilder {
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn setup<F>(mut self, setup: F) -> Self
where
F: FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send + 'static,
{
self.setup.replace(Box::new(setup));
self
}
pub fn run(self) {
let setup = self.setup;
tauri::Builder::default()
.setup(move |app| {
if let Some(setup) = setup {
(setup)(app)?;
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
}
- 新增
src-tauri/src/mobile.rs
内容如下:
#[tauri::mobile_entry_point]
fn main() {
super::AppBuilder::new().run();
}
- 覆盖
src-tauri/src/main.rs
内容如下:
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
pub fn main() {
app::AppBuilder::new().run();
}
编译安卓APK
- 需要打开Android Studio的安卓模拟器或者adb命令连接你的手机,建议后者会更好一些。
- 可以用下面的adb命令查看当前电脑已经连接的设备。如果没有,则会运行项目时会自动打开虚拟机中的模拟器。
adb devices
- 你也可以去Android Studio,打开
Tool
-Device Manager
查看你的虚拟机。如果虚拟机也么有,那就需要去Device Manage,点击Create
创建一个了。
- 回到项目根路径,用tauri 2.0生成安卓代码。参考链接:https://next--tauri.netlify.app/next/mobile/development/mobile_workflow
pnpm tauri android init
- 以dev环境运行安卓项目。(运行后会依次编译web,tauri,安卓),此时手机/虚拟机会自动安装apk。你点击手机屏幕会电脑终端可以看到对应的调试信息。
pnpm tauri android dev
- 你可以在
src-tauri\gen\android\app\build\outputs\apk\arm64\debug
路径看到这个apk,它的命名为app-arm64-debug.apk
,大小为148M。
- 正式使用时,一般不需要那么多调试信息,而且也要缩减安装包大小。所以需要编译一下正式版应用。运行下面的命令即可编译正式版应用,可能需要2-5分钟。
pnpm tauri android build
See https://docs.gradle.org/8.0/userguide/command_line_interface.html#sec:command_line_warnings
Finished 1 APK at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk
Finished 1 AAB at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/bundle/universalRelease/app-universal-release.aab
- 可以看到生成了apk和aab两个安装包。
- 观察apk命名:
app-universal-release-unsigned.apk
有两个关键信息,universal
代表多架构,unsigned
代表未包含签名。 - 尝试将这个apk放到安卓手机安装,提示没有签名无法安装。
- 多架构说明还能精简一下,像手机一般用arm64就行了,多余的目前用不上。
- 目前要做的事情是先给apk签名。
- 生成签名。参考链接:https://next--tauri.netlify.app/next/guides/distribution/sign-android/ 根据这个链接,我们需要先生成一个签名。对于windows,使用下面这个命令来生成(注意keystore里面的用户名改成你的,最好是全英语)。
keytool -genkey -v -keystore C:\Users\dsz\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
- 注意口令千万记牢固了,否则要重新生成了,会影响到后期的上架应用商店问题。
- 参考输入
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: Tlntin Deng
您的组织单位名称是什么?
[Unknown]: MyCompany
您的组织名称是什么?
[Unknown]: MyOrg
您所在的城市或区域名称是什么?
[Unknown]: GuangZhou
您所在的省/市/自治区名称是什么?
[Unknown]: GuangDong
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=Tlntin Deng, OU=MyCompany, O=MyOrg, L=GuangZhou, ST=GuangDong, C=CN是否正确?
[否]: Y
- 生成完签名后,还需要将签名应用到apk中,还是参考上面的链接。先建一个
src-tauri/gen/android/key.properties
文件。填入你的口令以及签名路径:
storePassword=xxxxxxxxx
keyPassword=xxxxxxxxx
keyAlias=upload
storeFile=C:\\Users\\dsz\\upload-keystore.jks
- 修改
src-tauri/gen/android/app/build.gradle.kts
文件。基本修改内容就是参考链接里面说的。我这里不再废话了。修改完长这样:
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("rust")
}
val keyPropertiesFile = rootProject.file("key.properties")
val keyProperties = Properties()
keyProperties.load(FileInputStream(keyPropertiesFile))
android {
compileSdk = 33
namespace = "com.tauri.tauri_demo"
defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.tauri_demo"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
signingConfigs {
create("release") {
keyAlias = keyProperties["keyAlias"] as String
keyPassword = keyProperties["keyPassword"] as String
storeFile = file(keyProperties["storeFile"] as String)
storePassword = keyProperties["storePassword"] as String
}
}
buildTypes {
getByName("debug") {
manifestPlaceholders["usesCleartextTraffic"] = "true"
isDebuggable = true
isJniDebuggable = true
isMinifyEnabled = false
packaging { jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
jniLibs.keepDebugSymbols.add("*/x86/*.so")
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
}
}
getByName("release") {
isMinifyEnabled = true
signingConfig = signingConfigs.getByName("release")
proguardFiles(
*fileTree(".") { include("**/*.pro") }
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
.toList().toTypedArray()
)
}
}
kotlinOptions {
jvmTarget = "1.8"
}
}
rust {
rootDirRel = "../../../"
}
dependencies {
implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
}
apply(from = "tauri.build.gradle.kts")
pnpm tauri android build
See https://docs.gradle.org/8.0/userguide/command_line_interface.html#sec:command_line_warnings
Finished 1 APK at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/apk/universal/release/app-universal-release.apk
Finished 1 AAB at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/bundle/universalRelease/app-universal-release.aab
- 可以看到文件没有提示未签名(unsigned)了。
- 精简架构(可选),观察一下目前apk的信息(注意路径改成你的)。
aapt dump badging C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/apk/universal/release/app-universal-release.apk
native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64
- 可以看到目前有4种架构,分别是arm 64位/arm 32位,x86 32位,x86 64位,一般来说,我们手机都是arm架构,除非用电脑模拟器,否则只需要arm64就行。
- 获取编译安卓时的帮助信息
cargo tauri android build --help
Android build
Usage: cargo tauri android build [OPTIONS]
Options:
-d, --debug Builds with the debug flag
-v, --verbose... Enables verbose logging
-t, --target [<TARGETS>...] Which targets to build (all by default) [possible values: aarch64, armv7, i686, x86_64]
-f, --features [<FEATURES>...] List of cargo features to activate
-c, --config <CONFIG> JSON string or path to JSON file to merge with tauri.conf.json
--split-per-abi Whether to split the APKs and AABs per ABIs
--apk Build APKs
--aab Build AABs
-o, --open Open Android Studio
-h, --help Print help
-V, --version Print version
- 注意:
-t, --target [<TARGETS>...] Which targets to build (all by default) [possible values: aarch64, armv7, i686, x86_64]
这里说all by default
,默认是4种架构都支持,我们需要arm64,所以就选aarch64
即可。 - 于是下面编译正式版时,指定一下架构aarch64。在项目根目录,终端环境下,重新运行一次编译命令。
pnpm tauri android build --target aarch64
- 观察输出结果,命名好像没有变化,还是通用架构,已签名。
See https://docs.gradle.org/8.0/userguide/command_line_interface.html#sec:command_line_warnings
Finished 1 APK at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/apk/universal/release/app-universal-release.apk
Finished 1 AAB at:
C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/bundle/universalRelease/app-universal-release.aab
aapt dump badging C:\Users\dsz\Documents\rust_web\tauri_demo\src-tauri/gen/android\app/build/outputs/apk/universal/release/app-universal-release.apk
native-code: 'arm64-v8a
- 目前只支持单一架构了。文件名大小从38M到11M,减少了70%多。
- 然后把这个安装包发到手机上,就可以安装了。如果提示签名不一致,那就卸载一下旧版。
- 安装后打开长这样: