浅谈.Net For Android

首先讲讲历史吧。
我们都知道.NET
最初是.Net Framwork
,只能在Windows平台上运行(仅限 Windows,闭源,较庞大),直到后面.NET Core
的出现,目标是创建一个轻量级、高性能、跨平台(Windows, Linux, macOS) 的开源框架。2020 年 11 月,微软发布了 .NET 5,.NET 5 是 .NET Core 的直接继承者和进化版本。它包含了 .NET Core
的所有优点(跨平台、开源、高性能、现代化),并开始整合.NET Framework
中一些有价值的特性(比如 WPF/WinForms 的跨平台支持通过 MAUI 的早期形态),以及来自 Xamarin/Mono 的移动开发能力。在写这篇文章的时候,.NET已经来到了最新的.NET 10,主要的.NET
版本都会在每年 11 月发布一次。每个 .NET
版本在发布开始时都定义为标准期限支持(STS)或长期支持(LTS)。 STS 版本以偶数年为单位发布,LTS 版本以奇数年为单位发布。
然后我们看看Xamarin(Mono的母公司)吧。Mono项目始于2001年,由Miguel de Icaza领导,目的是将.NET引入Linux平台。这与微软的.NET Framework
(仅限Windows)形成对比。这说明在微软正式推动跨平台之前,Mono已经是独立的跨平台实现了。Mono提供了独立的运行时、C# 编译器及类库(如 GTK# 替代 WinForms),支持 Linux/macOS/嵌入式系统等,成为 Unity 游戏引擎和 Xamarin 移动开发的基础。由于Mono 并非微软官方产品,所以难免存在兼容性差距(如缺失 WPF/WWF,部分 WCF/ASP.NET 异步支持有限)。虽然Mono也有跨平台特性,微软在 2014 年 宣布开源 .NET Core,目标直指跨平台(Linux/macOS/Windows)和云原生场景,与 Mono 无直接技术关联。微软在2016年才收购了Xamarin,旨在整合移动开发生态(iOS/Android)。2019年.NET 5首次将CoreCLR(.NET Core的运行时)和Mono运行时作为并列选项纳入统一平台。具体来说,Mono的AOT编译能力被用于移动和Wasm场景(如Blazor),而CoreCLR专注服务器端高性能。在 2020 年 11 月,微软发布了 .NET 5。在2024年后微软将原 Mono 代码库移交 WineHQ 维护,专注于传统应用兼容性(如 Wine 中的 .NET 支持)。有趣的是,微软正在将 Mono 的关键能力(如 AOT 编译、移动端支持)逐步重构并整合到 CoreCLR 技术栈中。未来 Mono 将逐渐退化为“兼容层”,而 .NET 的跨平台主力会完全由 CoreCLR 及其衍生技术承担。
graph LR A[Mono时代] --> B[过渡期] B --> C[统一运行时] A -->|Xamarin/iOS| D[Mono AOT] A -->|Blazor WASM| E[Mono解释器] B -->|.NET 5-8| F[CoreCLR+NativeAOT部分整合] C -->|.NET 9+| G[CoreCLR全域覆盖] G --> H[NativeAOT 移动/嵌入式] G --> I[CoreCLR-WASM 浏览器] G --> J[解释器 动态场景]
2024年Mono退居二线,仅支持旧版Unity/Wine兼容层。2025年.NET 9的CoreCLR-WASM预计取代Mono的Blazor方案2。2026年预计Unity完成向CoreCLR SDK迁移,终止Mono运行时。至于Avalonia和Maui,两者也在均在逐步剥离Mono运行时,转向CoreCLR技术栈(含NativeAOT/解释器)。不过就在目前,mono运行时还没有完全被取代(至少在笔者使用的一些.NET版本中仍然可以看到mono的影子)。虽然有mono和CoreCLR两种运行时,但是机制个人认为都差不多,都是将IL 代码通过AOT编译为原生代码(在安卓平台上是so文件,注意.so
文件是 Android 和 Linux 系统中用于共享库的文件,通常由 C 或 C++ 代码编译生成,但 .NET Intermediate Language (IL) 也可以通过 Ahead-of-Time (AOT) 编译生成 .so
文件)。
以安卓为例,简述一下编译流程:
- 将 C# (或 F#/VB.NET) 代码编译成标准的 .NET 中间语言 (IL) 或 .NET 程序集 (DLL)。
- 将 Mono 运行时本身(或者 CoreCLR,但在安卓上 Mono 更常见)编译成一个原生的
libmonosgen-2.0.so
(或类似名称) 库。这个库是用 C/C++ 写的,包含了垃圾回收器、JIT 编译器(或 AOT 编译器)、线程管理、类型系统等核心运行时功能。 - 将编译成的 .NET 程序集 (IL) 打包嵌入到最终生成的 APK 包中(通常放在
assemblies
目录下)。(它们不是被转换成 C 代码再编译进so
) - 可选但常见 (尤其在 Release 模式): 使用 AOT (Ahead-Of-Time) 编译。AOT 编译器 (
mono --aot
或crossgen
/crossgen2
对于 CoreCLR) 会将你的 .NET 程序集 (IL) 预先编译成目标平台(如 ARM)的本地机器码。这些编译好的本地机器码会被打包成一个或多个.so
文件(例如libaot-MyApp.dll.so
)。libaot-*.so
(AOT 编译时生成): 这些是应用代码和依赖库(如 Avalonia/MAUI 框架库)被 AOT 编译成的本地机器码。每个*.so
文件对应一个 .NET 程序集。其它必要的本地库比如 Avalonia 或 MAUI 渲染引擎的本地部分、Skia 图形库、SQLite 等也编译为so文件。 - 编译为so文件后,
.NET SDK
(csc, MSBuild),Mono AOT Compiler
(或 .NET Native AOT 工具链)在这个阶段,.NET 平台的编译(C#/IL -> 本地机器码.so
+ 打包 Mono 运行时.so
+ 保留元数据.dll
)确实已经完成了。 输出的.so
文件已经包含了可以直接在 ARM/ARM64/x86 等 CPU 上执行的指令,后续就是将这些so文件进行整合在安卓平台上运行了,这个时候就少不了java和kotlin了 - 打包阶段(Android SDK + Xamarin.Android/.NET MAUI 工具链主导),个人觉得Xamarin.Android 和 .NET MAUI 的工具链有一部分就是来自 .NET 中的 Android workload,特别是 “maui-android” workload。在这个阶段,Android SDK 的工具链确实被用来处理 Android 特有的打包任务将 .NET 编译输出的所有产物(
.so
,.dll
, 元数据文件)以及必要的 Java/Kotlin 胶水代码、资源文件等,按照 Android APK 的标准格式组织起来,并将自动生成的Java/Kotlin 胶水代码编译成.dex
文件,并生成最终的.apk
或.aab
文件。
.NET生成的Android应用启动流程示例: - 在
MainActivity
的onCreate
或其他早期生命周期方法中,Java 代码调用System.loadLibrary("monosgen-2.0")
。这一步通过 Android 系统的 JNI 接口加载libmonosgen-2.0.so
。 - 加载成功后,Java 代码通过 JNI 调用
libmonosgen-2.0.so
中暴露的 C 函数来初始化 Mono 运行时 (mono_jit_init_version
等)。 - 然后 Java 代码再次通过 JNI 调用 Mono 运行时的函数,指示它加载主应用 .dll (
YourApp.dll
) 并执行其Main
方法。
最后的一些疑问:
为什么打包后的安装包体积比较大?
因为运行时占一定空间libmonosgen-2.0.so
约15-20MB,一些基础依赖库比如Avalonia/MAUI框架本身引入的.NET BCL和UI库也有一定体积,然后还有多 ABI 支持:默认包含多个 CPU 架构(如 armeabi-v7a, arm64-v8a)的库,每个增加约 30 MB。
在移动端全面使用AOT吗?
几乎是,只有在调试的时候会使用到JIT。发布后的 APK 内部全部使用 AOT(提前编译)生成的 SO 文件。
性能问题
Avalonia 和 MAUI 生成的应用在性能上可以通过 AOT 编译、代码裁剪等优化接近原生 Android 应用,尤其在企业应用和常规 UI 场景下。对于高性能场景(如游戏或实时计算),原生 Android 应用因直接访问硬件和平台优化而更具优势。
以上都是本人搜索后整理,结果不一定准确,如有误,可以评论或者联系作者修改~✋
- 标题: 浅谈.Net For Android
- 作者: EliorFoy
- 创建于 : 2025-07-30 19:32:29
- 更新于 : 2025-07-30 21:00:14
- 链接: https://eliorfoy.github.io/2025/07/30/浅谈.Net For Android/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。