# 原生集成 (PlatformUtils、JNI、crossfly-lib)

> 中立的 Java 代码如何触达操作系统——单一入口 PlatformUtils 与 fallback 模式。

Source: https://crossfly.dev/zh/docs/platforms/native-integration — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 原生集成 🤖🍎🖥️

**中立**的 Java 代码（位于 `core`）如何触达因平台而异的操作系统功能。

## `PlatformUtils`——单一抽象入口
`PlatformUtils.instance` 是平台门面（facade）。**每个 launcher 都会安装自己的实现**
（web 安装 `PlatformUtilsWeb`）。关键方法：
```java
IWebView wv = PlatformUtils.instance.createWebView();   // 无 webview 处为 null（web）
PlatformUtils.instance.view(url);                        // 打开外部 URL
PlatformUtils.instance.dial(numero);                     // 拨号
```

## 原生库 `crossfly-lib`
在启动时由 `Main.create()` 内部的 `SharedLibraryLoader.load("crossfly-lib")` 加载——
**在所有目标平台上，WebGL 除外**：
```java
if (Gdx.app.getType() != Application.ApplicationType.WebGL)
   new SharedLibraryLoader().load("crossfly-lib");
```
因此，所有依赖它的东西（例如：通过 JNI 的 `NativeImage`）**在 web 上并不存在**——在那里适用的是
纯 Java 实现（`JavaImageOps`）或 *stub*。

## “带 fallback 的原生功能”模式
在使用一个可能不存在的功能之前，务必先**检查**：
```java
if (PlatformUtils.instance.createWebView() != null) {
   WebContainer c = new WebContainer();     // Android/iOS/Desktop
   painel.add(LAY_FILL, c);
   c.show(url);
} else {
   PlatformUtils.instance.view(url);        // Web：在外部打开
}
```
同样适用于相机/地图返回的 `null` 以及 `Device.platform`：
```java
if (Device.platform.isDesktop()) { /* 桌面端路径 */ }
```

## 编写你自己的原生实现
具体的服务（webview、GPS 等）位于 **`core` 之外**，在每个 launcher 中。对于一个
新功能，在 `core` 中定义接口，并按 launcher 实现它，在启动时将其安装到 `PlatformUtils`/服务
字段中。图像抽象就遵循这个模型：`ImageOps` → `JavaImageOps` (JVM) vs
`NativeImage` (JNI)。

## 最佳实践
- **永远不要**假设某个设备功能存在——检查 `!= null`/`Device.platform`。
- 将操作系统相关的代码放在 **launcher** 中，而不是 `core` 中。

## 常见错误
- 调用一个没有 fallback 的原生功能（在 web 上崩溃）。
- 期望在 web 上有 `crossfly-lib`/JNI（它在 WebGL 上不会被加载）。

## 另请参阅
- [Web (TeaVM)](/docs/platforms/web-teavm) · [WebContainer](/docs/ui/widgets/webcontainer)
