普通视图

发现新文章,点击刷新页面。
昨天以前iOS

X未提前通知,突然停用twitter授权登录域名,大量X三方登录异常!

作者 CocoaKier
2026年5月26日 11:23

昨天(5月25日)我们收到不少客诉反馈X授权登录异常,具体表现是:X授权登录过期后(网页登录态没过期不受影响),会弹下面页面“若要使用此应用程序,你必须登录X”,用户输入账号密码登录登录后又会回到此页面,无限循环。

iShot_2026-05-26_11.01.25.png

解决方案
(必须)修改 客户端\前端 X授权域名
https://twitter.com/i/oauth2/authorize => https://x.com/i/oauth2/authorize

(可选)修改服务端鉴权域名
https://api.twitter.com/2/oauth2/token => https://api.x.com/2/oauth2/token
——建议一起改一下,避免夜长梦多。这个我们测过了,换了没影响

请检查 客户端、Web站点、PC端、服务端,是否包含上述域名地址,请全部替换

如果上面地址是客户端写死的,哭吧,要更包,我昨晚已经加班更了4个包了😭

Tips: iOS清理X登录态方法:系统设置 - Safari - 清理所有历史记录(只清twitter.com、x.com也行)


问题原因分析
上面这个页面之前没见过,怀疑是X的程序员最近新加的,加出bug了,callback回调时忘记兼容老的twitter域名了。说不定后面他们发现后会修复,就不用更包了,但我们等不起也赌不起,万一人家懒得修呢?

参考资料:
docs.x.com/fundamental…

Android Studio 新版本与 Gradle 7.x 构建报错解决方案

作者 wyanassert
2026年5月11日 17:39

问题现象

在 Android Studio 中 Build / Sync 报错:

1
2
3
4
5
6
7
8
Could not compile initialization script '.../ijMapper1.gradle'.
> startup failed:
General error during conversion: Unsupported class file major version 65

java.lang.IllegalArgumentException: Unsupported class file major version 65
at groovyjarjarasm.asm.ClassReader.<init>(ClassReader.java:199)
...
at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction...

从命令行直接执行 ./gradlew tasks 完全正常,只有通过 Android Studio 触发构建时才报错。


根本原因

这是一个 Android Studio 版本 × Gradle 版本 的二进制不兼容问题,与项目代码无关。

层级 说明
class file major version 65 Java 21 编译产物的标识(Java 11 = 55,Java 17 = 61,Java 21 = 65)
Android Studio Koala(2024.1)及更新版本 自带 JDK 21,其 Tooling Extension JARs(如 GradleOpenTelemetryGradleModelFetchAction)使用 Java 21 编译
Gradle 7.4.2 内置 Groovy 3.0.9 / ASM 9.1 ASM 9.1 最高只能解析 Java 17(class version 61)的 class 文件,无法读取 Java 21 产物

Android Studio 每次构建会向 Gradle 注入一个临时 init script(ijMapper1.gradle),Groovy 编译这个脚本时需要解析 classpath 上的 Android Studio Tooling JARs。新版 AS 的这些 JAR 是 Java 21 编译的,Gradle 7.x 内置的 ASM 读不了,直接崩溃。

命令行不受影响的原因:直接执行 ./gradlew 不经过 Android Studio 的 Tooling API,不会注入这个 init script。


解决方案

✅ 方案一:在 Android Studio 中指定 Gradle JDK 为 JDK 11(本文实际采用,推荐)

修改项目的 .idea/gradle.xml,将 gradleJvm 改为 JDK 11 的路径(路径需已在 Android Studio 的 JDK Table 中注册):

1
2
<option name="gradleJvm"
value="$USER_HOME$/Library/Java/JavaVirtualMachines/corretto-11.0.19/Contents/Home" />

注意:这里必须使用 $USER_HOME$ 变量形式,而非绝对路径,否则 Android Studio 在 jdk.table.xml 中匹配不到对应条目,报 “Undefined jdk.table.xml entry” 错误。

配置完成后,Android Studio 会:

  1. 用 JDK 11 启动 Gradle daemon
  2. 选用与 JDK 11 兼容的 Tooling Extension JARs(class version ≤ 61),避免 ASM 解析失败

此方案不影响其他同事(.idea/gradle.xml 中的路径是各自机器上注册过的条目,不同机器只要都注册了 JDK 11 即可)。


方案二:升级 Gradle 到 8.4+(需团队协调)

Gradle 8.x 采用 Groovy 4.x / ASM 9.5+,原生支持 Java 21 class 文件,从根本上消除兼容问题。

1
2
# gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip

代价:AGP 7.x 不兼容 Gradle 8.x,需同步将 AGP 升级到 8.x,改动较大,需要团队统一升级。


方案三:降级 Android Studio(临时方案)

降回 Android Studio Jellyfish(2023.3.1) 或更早版本,其 Tooling Extension JARs 基于 Java 17 编译(class version 61),Gradle 7.x 的 ASM 9.1 可以正常解析。


排查思路总结

遇到此类问题时,快速定位的关键线索:

  1. 只在 IDE 内报错,命令行正常 → 问题出在 IDE 注入的 init script,而非项目构建脚本本身
  2. Unsupported class file major version 65 → 某个依赖/工具 JAR 用 Java 21 编译,运行时的 ASM/JVM 版本不支持
  3. 错误堆栈含 com.intellij.gradle.toolingExtension → 确认是 Android Studio Tooling Extension 和 Gradle 的版本兼容性问题

兼容性速查表

Android Studio 版本 内置 JDK Tooling JAR class version 最低兼容 Gradle
Jellyfish 2023.3.1 及以前 JDK 17 61(Java 17) Gradle 7.x 可用
Koala 2024.1.1 及以后 JDK 21 65(Java 21) 需 Gradle 8.4+ 或手动指定 Gradle JDK 为 17/11

Swift 杀进 Android,Google 和 Apple 都要失眠了?

作者 黄林晴
2026年3月31日 08:49

本文同步自微信公众号 “Android技术圈”

Swift 终于正式杀进 Android 了。 不是社区 Demo,不是民间魔改,而是 Swift 官方第一次亲自发布 Android SDK。 这件事现在看起来像一条技术新闻,再往后看,很可能会变成移动开发格局变化的起点。

先别急着喊 “Kotlin 要完了”。 但也别把它轻飘飘理解成 “Swift 又做了个跨平台实验”。 因为这次最狠的地方在于:Swift 官方第一次给出了进入 Android 工程体系的真实路径。

cover.png

官方到底宣布了什么

比“Apple 要不要抢 Android 地盘”更值得看的,其实是官方这次到底把支持范围推进到了哪一步。

Swift 官方博客对这件事的表述,其实非常克制,但也非常明确。核心就三点:

  • Swift 6.3 包含首个官方 Android Swift SDK
  • 可以开始用 Swift 开发原生 Android 程序
  • 可以通过 Swift JavaSwift Java JNI Core,把 Swift 代码集成进现有 Kotlin / Java Android 应用

这三句话加起来,真正说明的是:

Swift on Android,已经从社区探索,进入官方支持阶段。

这一步为什么重要?

因为过去你看到的很多 “Swift 跑 Android”,本质上都还是社区项目、实验性方案,或者少数团队自己打补丁维护的链路。

而这次不一样。 这次是 Swift 官方把 SDK、文档、安装方式、交叉编译路径和互操作方案一起摆上台面。

对开发者来说,差别非常大。

社区方案是“能折腾出来”。 官方方案才是“值得认真观察是否能进生产”。

02_ecosystem_bridge.png

别高估,也别低估

这类新闻最容易出现两个极端判断。

第一种是:
“Kotlin 要凉了,Android 以后可以全用 Swift 写。”

第二种是:
“没意义,不就是把命令行程序编到 Android 上吗?”

这两种都不准确。

从 Swift 官方文档来看,今天已经明确成立的是:

  • 你可以把 Swift 代码交叉编译到 Android
  • 你可以在 Android 设备或模拟器上运行 Swift 程序
  • 你可以把 Swift 模块构建成共享库
  • 你可以让现有 Kotlin / Java Android 应用去调用这些 Swift 代码

这意味着什么?

意味着 Swift 现在已经不是“只能在 Apple 生态里玩”的语言了。 但它也还远远没到“Android 主流团队明天集体切语言”的程度。

它真正有价值的地方,不是在口号层。 而是在工程层。

它第一次让 Swift 有机会进入 Android 的真实项目结构里。

真正值得关注的,是这条工程路径

Swift 官方的 Android 入门文档其实很务实,没有画大饼。

要跑起来,你得准备 3 样东西:

  • Swift 6.3 toolchain
  • Swift SDK for Android
  • Android NDK 27d 或更高版本

然后通过 swift build --swift-sdk ... 做 Android 目标的交叉编译。

官方演示的第一步,也不是完整 App,而是先把一个 Swift 可执行程序编译到 Android 上运行。

很多人看到这里会下意识地说:

“那不还是离真正 Android App 很远?”

但官方文档后面紧接着补了一句特别关键的话:

Swift 模块可以构建为共享库,并被打进 Android 应用,再由 Java / Kotlin 代码调用。

这句话,才是整件事的核心。

因为这说明 Swift on Android 的第一落点,并不是 UI 层,也不是整项目重写。 而是更现实、更符合团队采纳路径的地方:

  • 共享业务逻辑
  • 数据模型
  • 网络层
  • 算法模块
  • 某些性能敏感代码

说白了,Swift 现在不是先来抢 Compose 的饭碗。 它更像是先从“共享模块语言”这个位置切进去。

03_shared_logic_path.png

这件事为什么会让很多 iOS 团队心动

对纯 Android 团队来说,这条新闻现在更像观察项。 但对已经重度使用 Swift 的团队,这个信号就完全不一样了。

过去很多团队都会面临一个老问题:

“iOS 侧已经有一套成熟的 Swift 代码资产了,Android 还要不要重写一遍?”

如果这些资产只是 UI,那没办法,平台差异太大。 但如果是业务规则、网络协议、加解密逻辑、通用数据处理,重写本身就是重复劳动。

Swift 官方 Android SDK 的出现,至少让这类团队开始有了一个新的选项:

把 Swift 资产往 Android 端延伸,而不是永远困在 Apple 生态内部。

这点其实很关键。

因为它改变的不是某个 API,而是开发者对 Swift 的心理预期。

过去大家默认 Swift 是: “写 iPhone、写 Mac、写 Apple 设备。”

现在这个认知边界开始松了。

Swift 正在从 Apple 平台语言,继续往真正的跨平台语言走。

Kotlin 会不会被威胁

短期答案很直接:不会。

Kotlin 在 Android 的位置,不是一两条技术新闻能撼动的。 它背后是 Android 官方支持、Jetpack 生态、Android Studio、社区实践、招聘市场和海量线上项目。

Swift 6.3 现在拿出来的是“首个官方 Android SDK”。 这离大规模生产落地,中间还隔着很多现实问题:

  • 工具链稳定性怎么样
  • 桥接 Kotlin / Java 的成本高不高
  • 调试链路顺不顺
  • CI 能不能稳定接入
  • 团队愿不愿意为它付出学习和维护成本

所以更合理的判断不是“Swift 替代 Kotlin”。

而是:

  • Kotlin 仍然会是 Android 主语言
  • Swift 可能成为共享逻辑和多端模块的新候选
  • 真正决定它能不能站稳的,是工程成熟度,不是新闻热度

04_adoption_stages.png

这一步对 Swift 自己更重要

从更大的角度看,这次最受益的,也许不是 Android,而是 Swift 本身。

一门语言如果长期绑定单平台,它再强,外界对它的认知上限也很明确。

只有当它开始稳定支持更多平台,开发者才会真正把它当成一门独立的软件工程语言,而不是某家平台公司的附属工具。

Swift 6.3 这次最值得玩味的地方就在这里。

它不是一句空泛的“我们支持跨平台”。 而是给出了 SDK、文档、安装方式、构建路径、互操作方案。

这说明 Swift 官方现在回答的问题,已经不再只是:

“Swift 能不能把 Apple 生态服务好?”

而是:

Swift 能不能成为一门覆盖更多平台的软件工程语言?

Android,就是这个问题里最关键的一块拼图。

开发者现在该怎么看

如果你是 Android 开发者,不需要焦虑,也没必要跟风重写任何项目。

你更应该做的是持续观察这几个点:

  • Swift Android SDK 后续更新速度快不快
  • Swift Java 的接入体验到底顺不顺
  • 有没有团队先把 Swift 用到 Android 共享模块里
  • 工具链能不能稳定进入 CI 和生产流程

如果你是 iOS / Swift 开发者,这件事反而更值得持续盯住。

因为这可能是 Swift 在未来两三年里,最有战略意义的一次边界扩张。

它未必马上改变你的项目。 但它很可能会慢慢改变未来的技术选型。

写在最后

Swift 6.3 的重点,不是简单一句“Swift 能写安卓了”。

更准确的说法应该是:

Swift 官方第一次正式发布 Android SDK,并给出了进入现有 Android 工程的可执行路径。

这一步还远远谈不上改写 Android 生态。 但它已经足够说明一件事:

平台边界,还在继续变薄。

你看好 Swift 在 Android 上的发展吗? 你觉得它会先成为共享逻辑工具,还是最终走到更完整的 Android 开发场景?

欢迎评论区聊聊。 如果你身边正好有做 iOS、Android、跨平台架构的朋友,也欢迎把这篇文章转给他们,一起讨论。

参考资料:

  • Swift 官方博客:Swift 6.3 Released
  • Swift 官方文档:Getting Started with the Swift SDK for Android

Swift 6.3 正式发布支持 Android ,它能在跨平台发挥什么优势?

2026年3月30日 11:23

最近 Swift 发布了 6.3 版本,而这个版本最特殊的地方在于:把 Android SDK 作为首个官方发布版本给加了进来,其实这个话题在去年的 《Swift 官方正式支持 Android》我们就已经聊过,而这两天正式版的发布,也是广大 Swift 开发者最高涨的时刻,iOSer 终于也有了自己的原生跨平台基础了:

那 Swfit for Android 到底是什么?其实和之前我们聊的一样,目前并不是在 Android 上原生跑 SwiftUI ,这个能力目前是一个 SKIP 的第三方项目在做, Swfit for Android 主要完成了「Swift 官方支持把 Swift 代码交叉编译到 Android」。

所以 Swfit for Android 目前主要由三个部分组成:

  • Swift Toolchain:目标平台上的 Swift 编译器、标准库、LLVM 后端

  • Swift SDK for Android:给 Android 目标平台准备的 Swift 库、头文件、配置

  • Android NDK:提供 Android 的系统头文件、链接器、目标架构工具链等

也就是说,它的核心原理是「交叉编译」:

  • 需要 macOS / Linux 上装 Swift 工具链
  • 需要 Android target 的 Swift SDK artifact bundle
  • 需要 Android NDK 的 sysroot、linker、headers
  • 由 Swift 编译器把代码交叉编译成 Android 可执行文件或本地库(.so
swift build --swift-sdk x86_64-unknown-linux-android28 --static-swift-stdlib

最终结果来看,就是把代码的构建产物变成 Android 上可运行的 ELF 二进制。

其实这也是在 iOS 的 LLVM 的技术领域,比如 KMP 目前大多也是利用 iOS 分支的 LLVM 交叉编译还到鸿蒙 ,所以 Swift 编译器本身还是走在自己的前端和 LLVM 后端,只是 target 换成 Android,例如:

  • x86_64-unknown-linux-android28
  • aarch64-unknown-linux-android28

这里的 android28 可以看出来,是明确绑定到特定 Android API Level ,而 Swift runtime / Foundation 依赖的一些能力也需要较新的 Android API,所以会用 API 28 为基础。

当然,Swift 与 Android 的 Java/Kotlin 的协调桥梁不出意外是 JNI,当然这里不会让你手写 JNI,而是用自动桥接工具来完成。

而在实际应用层面,Swift 官方现在推荐的不是 “整 App 全 Swift”,而是“Swift 库 + Kotlin/Java 壳” ,比如官方 examples 仓库里推荐方案 `hello-swift-java,它的结构是:

  • 一个 Swift package / Swift library
  • 一个 Kotlin Android app(Jetpack Compose UI)
  • Kotlin 调 Swift,不需要你手写 JNI,交给 swift-java 自动生成 Java wrapper 和 JNI bindings

也就目前而言,推荐的是 business logic / algorithms / libraries 写成 Swift ,而前端仍然保持标准 Kotlin/Java Android app 形态 ,简单来说就是:

  • UI:Kotlin / Jetpack Compose
  • 共享逻辑:Swift
  • 桥接层:swift-java / JNI

这强烈的即视感,不就是最初的 KMP 那会么,CMP 还没支持 UI 的时候,KMP 也是这样的路线

比如 Swift 官方提供的例子:一个 Android ( weather-app )和 Swift 库( weather-lib ),用于获取当前位置的天气信息,weather-lib 内部使用 swift-openapi-generator 调用 OpenMeteo 天气 API ,并公开LocationFetcher protocol , 然后 swift-java 和 JNI 自动生成 Java Wrapper ,从而让 Kotlin 可以直接调用 Swift Library。

而在这次 Swift 官方开源的项目里,核心的项目就是:swift-javaswift-java-jni-core ,他们分别作为“上层桥接工具”与“底层 JNI 基建”支撑起整个 Swfit for Android 的生态。

其实也很有趣,Kotlin 在 Android 跑 JVM ,在 iOS 跑 KN 二进制;而现在反过来 Swift 跑 Android ,也是跑二进制。

swift-java-jni-core

swift-java-jni-core 是一个 Swift-friendly 的 JNI 低层封装,本质上是 jni.h 上的一层薄封装,加上一些预打包的类型转换能力,用来和 JVM / Android Runtime(ART)交互,也就是:

  • 负责 JVM/ART 句柄
  • 找类、找方法
  • 处理线程、锁、引用
  • 做 Java/Swift 类型桥接

它的整个结构大概为:

Sources/  
├── CSwiftJavaJNI/          // C 模块:纯 JNI 头文件 ABI  
└── SwiftJavaJNICore/       // Swift 模块:所有上层封装  
    ├── VirtualMachine/     // JVM 句柄、线程、锁  
    ├── BridgedValues/      // 类型桥接  
    └── *.swift             // 类型系统、签名、Mangling  

整个链路从 Swift 应用代码开始,通过 JavaValue 协议进行类型转换,然后通过 JavaVirtualMachine 管理 JVM 交互,最终利用 CSwiftJavaJNI 的 C 接口调用实际的 JVM 实现:

swift-java

swift-java 是更高一层的互操作工具平台,大致可以分为:

  • Swift 调 Java
  • Java 调 Swift
  • 自动生成绑定代码
  • Android 上支持 jextract --mode=jni,因为 Android/ART 没有服务端 Java 那套 FFM 路线的前提条件

在实现上主要有两个代码生成管道:

1、Swift 调用 Java

  • 通过反射分析 Java 类文件,生成 Swift Wrapper
  • 使用 Swift 宏(@JavaClass@JavaMethod)在编译时展开为 JNI 调用

更具体的就是通过 swift-java wrap-java 命令,工具在运行时利用 Java 反射读取 Java 类(包括 .jar 文件),给每个 Java 类生成对应的 Swift 类型,生成的 Swift 类型使用 @JavaClass@JavaMethod@JavaField 等宏进行标注

用途
@JavaClass 声明一个 Swift 类型是 Java 类的包装
@JavaInterface 声明一个 Swift 类型是 Java 接口的包装
@JavaMethod 将 Swift 方法变为调用 Java 方法的桥接
@JavaField 访问 Java 实例字段
@JavaStaticField 访问 Java 静态字段
@JavaImplementation 在 Swift 中实现 Java native 方法

例如,可以将HelloSwiftMain类型扩展为符合ParsableCommand接口,并使用 Swift 参数解析器来处理 Java 提供的参数:

import ArgumentParser
import SwiftJNI

@JavaClass("org.swift.jni.HelloSwiftMain")
struct HelloSwiftMain: ParsableCommand {
  @Option(name: .shortAndLong, help: "Enable verbose output")
  var verbose: Bool = false

  @JavaImplementation
  static func main(arguments: [String], environment: JNIEnvironment? = nil) {
    let command = Self.parseOrExit(arguments)
    command.run(environment: environment)
  }
  
  func run(environment: JNIEnvironment? = nil) {
    print("Verbose = \(verbose)")
  }
}

所以,对应也存在类型映射的需求:

Java type Swift type
boolean Bool
byte Int8
char UInt16
short Int16
int Int32
long Int64
float Float
double Double
void Void (rare)
T[] [T]
String String
Java class Swift class Swift module
java.lang.Object JavaObject SwiftJava
java.lang.Class<T> JavaClass<T> SwiftJava
java.lang.Throwable Throwable SwiftJava
java.net.URL URL JavaNet

2、Java 调用 Swift(jextract)

主要是让 Java 程序调用 Swift 库 ,生成 Java 绑定和 Swift thunk 文件,支持 FFM 和 JNI 两种生成模式。

比如 jextract 这个流程会分两步:

  • Swift Thunk:用 @_cdecl 暴露 C 符号入口
  • Java 绑定:生成 Java 代码,通过 JNI 或 FFM 调用这些 C 入口

所以,整个 swift-java 主要就是提供自动化方式生成 Swift/Java 绑定,其中:

  • jni 模式兼容性最广,主要支持 Android
  • FFM 模式更偏 Java 22+/25+ 服务端场景,不是 Android 主战场

也就是,swift-java 不只是支持 Android ,它还可以支持 Java Web 场景,野心还是有的。

而整个链路上其实是「Swift - 编译成本地库 - 通过生成的 JNI/Java wrapper 暴露给 Kotlin/Java 调用」 这样一个实现:

image-20260330104416812

那聊到这里,目前局限性也很明显了,它没有一个「 Swift UI for Android 」的支持,它能够让 iOS 的同学把自己的业务逻辑或者纯 Swift 代码共享给 Android ,但是 UI 还是得 Android 自己写。

另外,Swift 社区官方论坛里也有人提到:目前的 Swift Android SDK 下,二进制体积过大,其中一个原因是 Foundation 依赖的 ICU 很重,因为你需要把 Swift runtime、Foundation、ICU 这些东西都带到 Android app 。

同时,在系统 API 上还是差了点意思,比如你需要调用 Andorid 的系统 API 时,大概需要:

Swift ↔ JNI ↔ Java/Kotlin ↔ Android 系统 API

目前这个链路还没有全套完整的官方实现,大概需要后续社区和官方继续补齐,所以当前更多是逻辑和算法等场景的复用,直接调用系统 API 还是会麻烦一些

当然,最终使用过程里,也可以把 Swfit 打包成独立的 Lib,比如在官方例子里的 hello-swift-raw-jni-library ,通过就可以构建出 hello-swift-raw-jni-library-release.aar

./gradlew :hello-swift-raw-jni-library:bundleReleaseAar

所以对于 Swift for Android 来说,目前还是处于起步阶段,作为第一个正式版的起步。

最后,不得不说,语言的最终归宿就是跨平台,UI 的最终归宿也是,现在的 Swift for Android 就像是当年的 KMP ,从语言的跨平台开始切入,未来要发展, Swift UI for Android 的路径看起来也不是不可能,至于最终能否发展起来,这就考验 Swift 社区的运营水平了。

image.png

链接

github.com/swiftlang/s…

github.com/swiftlang/s…

www.swift.org/documentati…

【Flutter×鸿蒙】通关手册(二):FVM 不认鸿蒙 SDK?4步手动塞进去

作者 TT_Close
2026年3月5日 18:26

系列导航:

我第一次让 FVM 管理鸿蒙版 Flutter SDK 时,前后踩了 4 个坑,花了大半天才跑通。事后复盘发现,每个坑都不难,只是没人提前告诉我"为什么要这样做"。这篇把整个过程拆成 5 关,每关讲清「为什么」和「怎么做」,争取让你 20 分钟一次通关。

前置条件:请先完成第一篇的全部内容——DevEco Studio 已安装,ohpm、node、hvigorw 在终端里都能正常调用。


🗺️ 通关路线图

关卡 任务 预计耗时
第1关 安装 FVM 2 min
第2关 克隆鸿蒙版 SDK 5 min(取决于网速)
第3关 修复版本"身份证" 3 min
第4关 指定鸿蒙 SDK 路径 1 min
第5关 全绿验证 2 min

🎯 第 1 关:安装 FVM

目标

让终端认识 fvm 命令。

为什么需要 FVM

一句话——让不同项目用不同版本的 Flutter,互不干扰。比如项目 A 用官方 3.24 跑 Android/iOS,项目 B 用鸿蒙版 3.35.8。FVM 就是 Flutter 的"版本档案柜",每个抽屉放一个版本。

📋 操作

# macOS(在终端里执行,这是用 Homebrew 包管理器安装 FVM)
brew install fvm
# Windows(在 cmd 或 PowerShell 中执行,这是用 Chocolatey 包管理器安装 FVM)
choco install fvm

安装完后,配置 FVM 缓存路径。把以下两行写入 ~/.zshrc(上一篇介绍过,这是 Mac 终端的配置文件):

# FVM 存放所有 Flutter 版本的目录
export FVM_CACHE_PATH=$HOME/fvm
# 让 FVM 的默认版本可以直接用 flutter 命令调用
export PATH="$HOME/fvm/default/bin:$PATH"

保存后执行下面这条命令,让刚才的配置立即生效(否则要关掉终端重新打开):

source ~/.zshrc

✅ 验证

# 查看 FVM 版本号,确认安装成功
fvm --version

看到版本号(如 3.1.4)就过关了。

⚠️ 如果报 command not found:Mac 用户确认已安装 Homebrew(执行 brew --version 看有没有输出);Windows 用户确认已安装 Chocolatey(执行 choco --version)。如果包管理器本身都没装,请先去官网安装。


🎯 第 2 关:克隆鸿蒙版 SDK

目标

把华为的鸿蒙版 Flutter 放进 FVM 管辖。

为什么不能直接 fvm install

正常装 Flutter 只需要 fvm install 3.24.0,FVM 会自动去 GitHub 下载。但鸿蒙版是华为团队在 AtomGit(国内代码托管平台)上单独维护的,FVM 的世界里它根本不存在。所以我们要"手动入库"——自己下载代码,放到 FVM 的档案柜里,假装它一直在那。

⚠️ 本关最大的坑:分支名和版本号是两回事!

仓库的分支叫 oh-3.35.7-dev,看到 3.35.7 你会以为版本就是 3.35.7。但实际上代码里的版本已经迭代到了 3.35.8-ohos-0.0.2

类比:Git 分支叫 feature/login-v1,但代码早就改到 v3 了。分支名是创建时起的,不会跟着版本号自动更新。

千万别拿分支名当版本号用,团队必须统一用 3.35.8-ohos-0.0.2 这个真实版本号。

📋 操作

# --depth 1 只取最新代码,省空间(省去几个 GB 的历史记录)
git clone -b oh-3.35.7-dev --depth 1 
https://atomgit.com/openharmony-tpc/flutter_flutter.git 
~/fvm/versions/3.35.8-ohos-0.0.2

注意看:clone 命令里分支名是 oh-3.35.7-dev,但目标文件夹名是 3.35.8-ohos-0.0.2——这不是写错了,上面已经解释了为什么不一样。

💡 怎么确认真实版本号? clone 完后执行 ~/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter --version 看输出。如果加入已有团队,直接看项目的 .fvmrc 文件(命令:cat .fvmrc)。

✅ 验证

# 确认文件下载成功(ls = 列出目录内容)
ls ~/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter

文件存在就过关。

⚠️ 如果报 No such file or directory:回去检查 clone 命令是否执行成功。常见原因是网络超时(AtomGit 在国内,通常不需要梯子,但公司内网可能有限制)。重新执行 clone 前,先删掉残留目录:rm -rf ~/fvm/versions/3.35.8-ohos-0.0.2,再重试。


🎯 第 3 关:修复版本"身份证"

目标

让 FVM 正确识别这个 SDK 的版本号。

为什么要做这步

clone 下来的 SDK 有两张"证件":

  1. version 文件——相当于身份证,一行文本写着版本号
  2. bin/cache/flutter.version.json——相当于内部档案,JSON 格式的详细版本信息

问题是,这两张证件上都写着 0.0.0-unknown(因为鸿蒙团队是从开发分支构建的,没有打标准标签)。但我们的文件夹名叫 3.35.8-ohos-0.0.2。FVM 一查——名字对不上,直接翻脸。

⚠️ 不做这步的后果:FVM 会弹出 "Version mismatch" 并试图删掉你的 SDK 重装。如果看到了这个弹窗,千万不要选任何选项,按 Ctrl+C(Mac 也是 Ctrl 不是 Cmd)退出,回来做这步。

📋 操作

macOS / Linux:

cd ~/fvm/versions/3.35.8-ohos-0.0.2

# 第一步:改"身份证"
echo -n "3.35.8-ohos-0.0.2" > version

# 第二步:初始化 Flutter 引擎(首次运行会下载 Dart SDK,需要等 1-3 分钟)
bin/flutter --version

# 第三步:改"内部档案"(把所有 0.0.0-unknown 替换成正确的版本号)
sed -i '' 's/0.0.0-unknown/3.35.8-ohos-0.0.2/g' bin/cache/flutter.version.json

Windows PowerShell:

# 进入 SDK 所在目录
cd $env:USERPROFILE\fvm\versions\3.35.8-ohos-0.0.2

# 第一步:改"身份证"
"3.35.8-ohos-0.0.2" | Set-Content version -NoNewline

# 第二步:初始化引擎
bin\flutter --version

# 第三步:改"内部档案"(PowerShell 的查找替换写法)
(Get-Content bin\cache\flutter.version.json) -replace '0.0.0-unknown', '3.35.8-ohos-0.0.2' | Set-Content bin\cache\flutter.version.json

⚠️ 三步的顺序不能乱——第二步会生成 flutter.version.json 文件,第三步才有东西可改。如果你先执行了第三步,会报文件不存在。

✅ 验证

# 回到任意目录都可以执行(fvm list = 列出 FVM 管理的所有 Flutter 版本)
fvm list

看到 Version 列显示 3.35.8-ohos-0.0.2(不是空白、不是 Need setup、不是 0.0.0-unknown),这关就过了。

02_fvm_list.png ⚠️ 如果还是显示异常,逐一排查两张"证件":

# 检查"身份证"内容
cat ~/fvm/versions/3.35.8-ohos-0.0.2/version
# 应该输出:3.35.8-ohos-0.0.2(没有多余空行)

# 检查"内部档案"有没有残留的 0.0.0-unknown
cat ~/fvm/versions/3.35.8-ohos-0.0.2/bin/cache/flutter.version.json
# 里面所有 version 字段应该都是 3.35.8-ohos-0.0.2

如果 version 文件内容不对,重新执行第一步;如果 JSON 里还有 0.0.0-unknown,重新执行第三步。


🎯 第 4 关:指定鸿蒙 SDK 路径

目标

让 Flutter 知道鸿蒙的 SDK(OpenHarmony SDK)装在哪。

为什么不用环境变量

我试过 HOS_SDK_HOMEOHOS_SDK_HOME 等环境变量,时灵时不灵。原因是不同方式打开的终端(VS Code 内置终端 vs 系统终端 vs CI 环境)加载配置文件的顺序不一样,变量可能没被读到。flutter config 会把路径写入 Flutter 自己的配置文件,不管从哪里启动都能读到,最稳。

📋 操作

# 把鸿蒙 SDK 的位置"写死"到 Flutter 的配置里(一次性操作)
~/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter config \
--ohos-sdk="/Applications/DevEco-Studio.app/Contents/sdk"

⚠️ Windows 用户路径改为:--ohos-sdk="C:\Program Files\Huawei\DevEco Studio\sdk"

请根据 DevEco Studio 实际安装路径调整。不确定装在哪?打开 DevEco Studio → Settings → SDK 页面可以看到路径。

终端输出 Setting "ohos-sdk" value to "..." 就成功了。

✅ 验证

不急,下一关一起验收。


🎯 第 5 关:全绿验证

目标

flutter doctor 中 HarmonyOS toolchain 一栏显示绿色对勾。

📋 操作

# 运行 Flutter 的环境诊断工具(-v 表示显示详细信息)
~/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter doctor -v

✅ 验证

关注输出中的 HarmonyOS 那一栏:

[✓] HarmonyOS toolchain - develop for HarmonyOS devices
    • OpenHarmony Sdk at /Applications/DevEco-Studio.app/Contents/sdk,
      available api versions has [22:default]
    • Ohpm version 6.0.1
    • Node version v18.20.1
    • Hvigorw binary at .../hvigor/bin/hvigorw

看到 [✓] 加上 4 个子项都有值 = 通关!

02_flutter_doctor.png 💡 你可能会看到 Flutter 那栏有几个 ! 警告(channel 不标准、upstream 不是官方地址)。这是鸿蒙版的正常现象,完全不影响开发和打包,放心忽略。

⚠️ 如果 HarmonyOS 那栏还是红叉,按优先级排查:

  1. SDK not found → 回第 4 关检查 config 路径是否正确
  2. ohpm/hvigorw missing → 回第一篇检查环境变量
  3. Version mismatch → 回第 3 关检查两张"证件"

🔧 附加关:FVM 的"碎碎念"

通关后你会发现,每次用 fvm flutter xxx 时 FVM 都会弹 "not a valid version" 的警告让你确认。这不是报错,只是 FVM 在说:"这个版本号我在官方列表里查不到,你确定要用吗?"

三种应对方式:

  1. 手动按 y——每次弹出输入 y 回车
  2. 自动确认——命令前加 yes |
yes | fvm flutter doctor
  1. 绕过 FVM——直接用绝对路径调用,完全不弹警告:
~/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter doctor

我推荐第三种,路径虽长但最省心。可以设个快捷方式(alias)缩短它:

# 把这行加到 ~/.zshrc 里(alias = 给一条长命令起个短名字)
alias hflutter="$HOME/fvm/versions/3.35.8-ohos-0.0.2/bin/flutter"

保存后 source ~/.zshrc,之后直接 hflutter runhflutter doctor 就行。


🏆 通关总结

项目 状态
FVM ✅ 已安装
鸿蒙版 Flutter SDK ✅ ~/fvm/versions/3.35.8-ohos-0.0.2
version 文件 ✅ 已修复
flutter.version.json ✅ 已修复
flutter config --ohos-sdk ✅ 已配置
flutter doctor HarmonyOS ✅ 全绿

回顾核心逻辑:FVM 只管官方 Flutter,鸿蒙版要我们手动塞进去(第 2 关);塞进去后"证件"信息对不上,需要手动修正(第 3 关);最后告诉 Flutter 鸿蒙 SDK 在哪(第 4 关)。理解了这条线,以后鸿蒙版 SDK 升级换版本号,你也能照样搞定。

如果中途卡住,大概率是版本号写错了——检查文件夹名、version 文件内容、flutter.version.json 里的版本号,三者必须完全一致


下一篇预告:SDK 准备好了,接下来要把你的老 Flutter 项目跑到鸿蒙上——听起来就是敲几行命令的事?没那么简单。→ 【Flutter×鸿蒙】通关手册(三):debug 包也要签名,这点和 Android 差远了

iOS + AI ,国外一个叫 Rork Max 的项目打算替换掉 Xcode

2026年2月21日 17:34

最近看到一个很有意思的项目,它是一个由国外 Rork 团队推出的 AI 移动应用开发平台,宣称是“全球首个在浏览器中构建原生 Swift 应用的 AI 工具”,也就是,你可以不需要 Mac 和 Xcode ,同时一次性完成 iPhone、手表、iPad、电视和 Vision Pro 的应用,甚至还有 AR 和 3D 支持。

所以它的产品逻辑是:用户只需在浏览器中输入自然语言描述,AI 就会自动生成 SwiftUI 代码,然后编译并在云端模拟器中运行,最后支持一键发布到 App Store。

什么 swift 版本 uniapp ?

听起来有点玄乎,但是实际上其实就是 Rork 在后端部署了大量的物理 Mac 节点或 Mac 云实例,当你开始一个项目时,系统就会动态分配一台运行着 XcodeiOS SDK 的 Mac 给对应会话。

也就是所有的编译、链接、资产打包过程都在真实的 macOS 环境下完成,生成的是 100% 的原生 Swift/SwiftUI 代码。

所以实际上就是:Cloud 版本的 Xcode/Mac ,然后搭配 Claude Code 和 Opus 4.6 ,然后生成对应的 iOS App 并提交 Apple Store 审核。

而 Rork 在这里也是采用了类似于云游戏的实时视频流协议(低延迟传输),所以你在浏览器里的每一次点击都会传回云端 Mac 的模拟器,画面变化再实时推送到前端

实际上就是一个远程主机,本质和 AI Studio 类似。

当然,Rork Max 的核心肯定还是他们的 Agent 管理和产品流程,这里的 AI Agent 除了利用 Opus 4.6 写代码之外,还要管理它的所有报错,测试运行和工程管理,同时 Rork 内置了 App Store Connect 的自动化流程,用户登录 Apple ID 后,AI 可以代理证书配置、App 打包和提审等流程。

从这里看,Rork Max 的客户更多的可能是非开发者,所以它的目标是将复杂的工程基座(Mac 硬件 + Xcode SDK + 苹果证书体系)完全抽象化,让开发者只需要关注逻辑和创意

另外,这里 Rork 自己强调了“非模版化”。它不是通过预设模版拼凑应用,而是通过大模型实时推理,通过自己实现的“持续上下文注入”的技术,让 AI 记住你之前所有对 UI 的微调,确保跨平台迁移时风格的一致性。

实际上它更多是一个从零构建、测试、安装并上架的 Apple 体系生产平台。它直接把“idea → 上架 App Store 的原生 Swift 应用”压缩成一个网页操作,从而大幅度降低了门槛。

官方演示视频中,从零到可玩的游戏原型大概 30–60 分钟:

另外 Rork 也表示后续会支持直接导入老项目的功能,不过对于这种场景,基本都是已经有开发者维护的项目场景,我比较怀疑是否会有受众,虽然貌似真的有:

目前已经有一些 Rork max 用户开始体验,反馈褒贬不一,但是我是没真实体验的,因为 Rork Max 的价格还是挺感人:

为什么不体验其他的?因为我看到所有说不好用的回复里,官方都是问:你是否打开了 Rork Max

当然,觉得它有意思的原因,也是它这个产品形态或者是未来的代表之一,开发者不再需要装什么 IDE 或者 SDK ,甚至都不需要纠结是 win 还是 mac 甚至 linux ,只需要一个入口,就可以完成需要开发,当然,那时候如果真的到来的话,也许开发者也不是开发者了,可能更多只是 token 账单的消费者。

❌
❌