SOUI安卓:一套C++代码,实现真正的跨平台``UI
这里介绍SOUI框架的安卓适配方案,展示如何用C++开发高性能,安全,跨平台的移动应用,同时与安卓``本地系统无缝整合.
为什么选择SOUI安卓?
在移动开发领域,跨平台方案层出不穷,但真正能完成"一套代码全平台运行"的寥寥无几.SOUI安卓方案凭借其独特的设计理念,为你带来了全新的选择.
核心优势
| 特性 | 说明 |
|---|---|
零改动跨平台 |
基于Win32,API仿真层,窗口端C++业务代码几乎零改动即可运行在安卓 |
单一UI线程 |
C++和Java共享安卓``主线程,无需跨线程分发,JNI调用零延迟 |
本地无缝整合 |
与AndroidView系统深度混合,可与本地控件混合布局 |
C++``高性能 |
编译型语言,运行效率远超解释型语言,适合复杂计算场景 |
| 代码安全 | 按本地代码编译,反编译难度极高,保护核心逻辑 |
| 无方法数限制 | 不受Android64K方法数限制,项目规模无上限 |
全平台规划 |
桌面端Windows,Linux,Macos全兼容,移动端安卓首发,后续支持iOS,真正实现一套代码跑遍全平台 |
架构设计:Win32模拟层方案
SOUI安卓的核心设计理念是:在安卓之上模拟一整套Win32``子系统.
cpp
┌------------------┐
│ 业务层(C++ SHostWnd 子类) │
│ CMainDlg::OnInitDialog / OnButtonClick / OnTimer / OnClose │
└--------┬------------┘
│ SendMessage / SetTimer / InvalidateRect
▼
┌------------------┐
│ SOUI 框架(SWindow 树 / RenderTarget) │
│ <- Skia 后端 Win/Android 共享 │
└-------┬-------------┘
│ ::CreateWindowEx / ::SetCapture / ::ShowWindow
▼
┌------------------┐
│ swinx(`跨平台` Win32 API 仿真层) │
│ WndMgr::fromHwnd(nativeId) -> WndObj -> AndroidPlatformAPI │
└-------┬-------------┘
│ JNI 桥接调用
▼
┌------------------┐
│ Android Java 层(View / Handler / Clipboard) │
│ SouiScreen / SouiSurface / SouiPlatformBridge / NativeEditView │
└------------------┘
三层架构详解
1,C++Native层:你的业务代码,基于Win32,API编写,与窗口端完全一致
2,JNI桥接层:实现C++与Java的双向通信,所有方法ID在初化时一次缓存
3,JavaUI层:安卓本地视图系统,保存SOUI窗口的渲染和交互
单一UI线程:SOUI的核心设计优势
SOUI安卓的一个革命性设计策略:C++业务代码完全运行在安卓``主线程,不创建独立的渲染线程或工作线程.
这与主流跨平台方案构成鲜明对比:
线程模型对比
| 方案 | 线程模型 |
复杂度 |
|---|---|---|
SOUI安卓 |
C+++Java共享主线程 |
最简单 |
Flutter |
UI线程+Raster线程+IO线程 |
复杂 |
Qt |
QtThread+RenderThread |
中等 |
单一UI线程的三大好处
1.JNI调用零延迟,无需跨线程分发
cpp
//`SouiPlatformBridge.cpp`直接在`主线程`调用`Java`方法
jboolean result = env->CallBooleanMethod(m_javaBridge, m_clipboardSetDataMethod, (jint)uFormat, jText);
因为C++和Java运行在同一线程:
1,无需Handler.post/runOnUiThread:直接调用``Java方法,零切换线程成本
2,无需PlatformChannel:不像Flutter需要异步消息队列传递数据
3,无需Future/Promise:同步调用,代码更直观,调试更简单
2.View操作直接同步,避免条件竞争
cpp
//直接操作`视图`,无需线安顾虑
env->CallVoidMethod((jobject)hWnd, midShow, SW_SHOW);
env->CallVoidMethod((jobject)hWnd, midMoveWindow, x, y, width, height);
在Flutter和Qt中,你需要:
Flutter:PlatformChannel``发送消息,等待回调
Qt:使用QMetaObject::invokeMethod或信号槽机制
这些机制不仅增加了代码复杂度,还引入了条件竞争和延迟.
3.生命期天然对齐,管理内存简单
cpp
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//`直接调用``C++`启动函数,无需同步线程
mSouiMainHwnd = SouiPlatformBridge.getInstance().souiStartup(mScreenId, getSurfaceHwnd(), mSouiLayout);
}
@Override
protected void onDetachedFromWindow() {
//`直接调用``C++``析构器`,资源立即释放
SouiPlatformBridge.getInstance().souiShutdown(mScreenId);
super.onDetachedFromWindow();
}
因为所有代码在同一线程执行:
1,无生命期同步问题:活动析构时立即析构``C++资源
2,无泄漏内存风险:无需担心线程间资源引用导致的泄漏
3,无悬垂指针问题:C++指针和Java对象生命期一致
性能对比:单一线程vs``多线程
cpp
┌-----------------┐
│ 用户操作(点击按钮) │
└---------┬----------┘
│
┌-------┼-------┐
▼ ▼ ▼
┌------┐ ┌-----┐ ┌-----┐
│ SOUI for │ │ Flutter │ │ Qt │
│ Android │ │ │ │ │
│ │ │ │ │ │
│ C++ 处理 │ │ Dart 处理 │ │ C++ 处理 │
│ (`主线程`) │ │ (UI 线程) │ │ (QtThread) │
│ │ │ │ │ │
│ JNI 调用 │ │ Platform │ │ QMetaObject │
│ (`主线程`) │ │ Channel │ │ ::invokeMethod │
│ │ │ (异步消息) │ │ (`跨线程`) │
│ │ │ │ │ │
│ Java View │ │ Android │ │ Java View │
│ 更新(`主线程`) │ │ View 更新 │ │ 更新 │
│ │ │ (平台线程) │ │ │
└------┘ └-----┘ └-----┘
│ │ │
▼ ▼ ▼
~0ms 延迟 ~16ms+ 延迟 ~8ms+ 延迟
SOUI的单一线程模型避免了切换线程的成本,响应速度更快,代码更简单.
无缝本地整合:与安卓系统深度混合
SOUI安卓不是一个独立的渲染引擎,而是与安卓``本地系统``深度混合的方案.
本地控件作为SOUI``子窗口
cpp
//注册本地`视图`工厂
SouiPlatformBridge.registerViewFactory("edit", NativeEditView::new);
registerViewFactory,可按SOUI的子控件使用安卓本地控件(如EditText或Button),享受本地控件的所有特性(如输入法支持,无障碍支持等).
SOUI嵌入本地布局
xml
<!-- activity_xml_host.xml -->
<LinearLayout ...>
<androidx.appcompat.widget.Toolbar ... />
<com.soui.SouiScreen
app:screenId="0x0000_D001"
app:souiLayout="layout:dlg_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton ... />
</LinearLayout>
SOUI的SouiScreen可按普通AndroidView嵌入任意本地布局,与Toolbar,FloatingActionButton等本地控件共存.
生命期完美对齐
cpp
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mScreenId != 0L) {
mSouiMainHwnd = SouiPlatformBridge.getInstance().souiStartup(mScreenId, getSurfaceHwnd(), mSouiLayout);
}
}
@Override
protected void onDetachedFromWindow() {
SouiPlatformBridge.getInstance().souiShutdown(mScreenId);
super.onDetachedFromWindow();
}
SOUI``窗口系统的生命期与AndroidActivity完美对齐,onAttachedToWindow时启动,onDetachedFromWindow时析构,避免泄漏内存.
C++``高性能:超越本地的运行效率
编译型语言优势
1,C++作为编译型语言,相比解释型语言(如Java,Kotlin,Dart)有明显的性能优势:
2,立即执行:按本地代码编译代码,无需运行时解释
3,内存控制:手动管理内存,避免GC停顿
4,SIMD优化:支持NEON/AArch64/SSSE3等SIMD指令,大幅提升计算密集型任务性能
代码安全:反编译难度极高
本地代码保护
1,按.so``动态库编译C++代码,相比Java/Kotlin代码有更高的安全性:
2,无源暴露:即使反编译也只能得到汇编代码,难以恢复业务逻辑
3,混淆支持:可使用ProGuard+LLVM混淆进一步增加逆向难度
4,加密支持:支持加密保护.so文件
无64K方法数限制
1,安卓平台对单个DEX文件有65536个方法的限制,这对大型项是一个严重的瓶颈.使用C++开发:
2,方法数零压力:C++代码不占用DEX方法数
3,项目规模无上限:可无限扩展业务代码,无需担心方法数超限
多Activity/多屏幕支持
screenId机制,SOUI安卓支持在多个活动中独立保存不同SOUI``窗口系统.
cpp
//`DefaultHostActivity.java`
public class DefaultHostActivity extends AppCompatActivity {
private static final long SCREEN_ID = 0x0000_D001L;
private static final String LAYOUT_DEMO = "layout:dlg_main";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SouiScreen mScreen = new SouiScreen(this,SCREEN_ID,LAYOUT_DEMO);
setContentView(mScreen);
}
}
每个活动拥有独立的screenId,窗口系统间互不干扰,支持多任务场景.
完整功能支持
处理输入事件
1,触摸事件->Win32``鼠标消息(WM_LBUTTONDOWN/UP/MOUSEMOVE)
2,双击检测->WM_LBUTTONDBLCLK
3,右键菜单->WM_RBUTTONDOWN
4,滚轮事件->WM_MOUSEWHEEL/WM_MOUSEHWHEEL
5,键盘事件->WM_KEYDOWN/WM_SYSKEYDOWN
6,SetCapture/ReleaseCapture``完全对齐``Win32语义
窗口管理
1,CreateWindowEx/DestroyWindow
2,MoveWindow/SetWindowPos
3,ShowWindow/UpdateWindow
HWND_MESSAGE消息占位窗口
计时器
1,SetTimer/KillTimer,完全对齐``Win32语义
2,支持非窗口``计时器(hWnd==0)
3,支持回调函数(TIMERPROC)
剪切板
1,clipboardOpen/clipboardClose
2,clipboardGetData/clipboardSetData
3,clipboardEmpty/clipboardIsFormatAvailable
IME输入
1,软键盘弹/保存监听
2,键盘高度同步
3,输入连接管理
4,光标位置查询(EM_GETSEL)
与其他跨平台方案对比
| 特性 | SOUI安卓 |
Flutter |
Qt |
|---|---|---|---|
| 语言 | C++ |
Dart |
C++/QML |
渲染方式 |
AndroidView+Skia |
自绘引擎+`Skia | QPA+OpenGL` |
线程模型 |
单一线程(C+++Java共享主线程) |
多线程(UI+Raster+IO) |
多线程(QtThread+RenderThread) |
| 线程复杂度 | 最简单 |
复杂 | 中等 |
JNI调用延迟 |
~0ms(同步调用) |
~16ms+(PlatformChannel) |
~8ms+(跨线程分发) |
本地整合 |
无缝 | PlatformChannel |
JNI |
| 性能 | |||
| 代码安全 | |||
| 方法数限制 | 无 | 有限 | 无 |
| 开发效率 | 需要C++技能 |
||
| 热重载 | (QML) |
开发环境要求
| 组件 | 版本要求 |
|---|---|
AndroidStudio |
Hedgehog(2023.1)及以上 |
AndroidSDK |
compileSdk34,minSdk28 |
AndroidNDK |
21.x/25.x/26.x |
CMake |
>=3.18.1 |
JDK |
17 |
快速开始
1.克隆代码
cpp
git clone https://github.com/soui4/soui.git soui4
cd soui4
git submodule update -init -recursive
2.打开项
使用AndroidStudio打开demos/androiddemo目录,GradleSync会自动下载依赖并配置CMake.
3.编译运行
调试构建:./gradlew.batassembleDebug
运行:点击运行按钮,选择安卓设备或模拟器
未来规划
SOUI安卓只是SOUI移动端适配的第一步,期望将很快实现IOS支持,到时候真正实现一套C++代码,全平台运行.
适合场景
| 场景 | 是否适合 |
|---|---|
已有大量SOUI(Windows)C++业务代码,需要低成本上Android |
强烈推荐 |
需要高性能,代码安全的移动应用 |
推荐 |
跨平台需求:Windows+Android+iOS |
推荐(未来支持iOS) |
| 新团队,新项,追求开发效率 | 不推荐(建议Flutter) |
| 需要大量动效,手势交互 | 不推荐(建议Flutter/本地) |
参考
1,SOUI4官方仓库(https://gitee.com/setoutsoft/soui4),这里
2,SOUI安卓技术文档,这里
3,SOUIAndroidvsFluttervsQt对比,这里