JavaFX 的奇怪 Gluon 项目结构 - Android 移植
Strange Gluon project structure for JavaFX - Android porting
用于将 JavaFX 移植到 Android 的 Gluon 插件的 gradle 构建(在 Netbeans 8.0.2 中)创建了以下目录结构:
- 源包[Java]
- Android/Java 包
- Desktop/Java 包
- Ios/Java 包
这些目录中的每一个都包含 java 个包。通常,Gluon 构建会在 "Source Packages" 目录中的一个 java 包中为我们创建 "main" class [名称为 "Source Packages" 的包可能会产生误导,因为它不是Java 包,它只是一个文件系统目录]。这个 main class 扩展了 Javafx Application class,因此是我们应用程序的入口点。
Android API 只能在 Android/Java Packages 目录中访问其中创建的任何 java 包。比如说,android.Vibrator class 只能在这里引用。
问题是,我们无法将在 Android/Java 目录内的任何 Java 包内创建的 class 引用到在源包 [[=] 内创建的任何 java 包46=]]目录!!如果是这种情况,那么我们如何将应用程序从 javafx.Application 的 start() 方法推进到 android.Vibrator。
gluon 项目结构的快照位于:
如您所知,JavaFXPorts 项目允许在桌面、Android 和 iOS 设备中部署 JavaFX 应用程序。当它只是纯 JavaFX 代码时,项目被添加到 Main 范围,从那里它将在所有这些平台中可见。
只有在您需要一些平台特定代码的情况下,您才应该将其添加到相应的包中。
正如您所提到的,默认情况下,您不会在主包中看到平台包中添加的代码,因此您必须为此提供一种方法。
如果您检查 JavaFXPorts 存储库上的 HelloPlatform sample,您会发现 PlatformService
class 使用 ServiceLoader
加载包。
另一种可能性是使用 Class.forName()
在 运行 时间动态加载 classes,一旦我们知道应用所在的平台 运行ning。
我建议你看一下 Gluon Down 项目,它为你管理几个特定于平台的服务,并为你提供统一的、平台无关的 API。
对于 Down (feel free to contribute), you can implement them like in this simple app created using Gluon Plugin 中尚不可用的那些服务。
源包[Java]
首先,创建一个getPlatform()
方法,并将引用的classes添加到每个特定平台。例如,在 Android 包上添加 org.gluonoss.vibrator.GluonAndroidPlatform.java
。
public class GluonPlatformFactory {
public static GluonPlatform getPlatform() {
try {
String platform = System.getProperty("javafx.platform", "desktop");
String path = "org.gluonoss.vibrator.GluonDesktopPlatform";
if(platform.equals("android")) {
path = "org.gluonoss.vibrator.GluonAndroidPlatform";
} else if(platform.equals("ios")) {
path = "org.gluonoss.vibrator.GluonIosPlatform";
}
return (GluonPlatform) Class.forName(path).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
System.out.println("Platform Error "+e.getMessage());
}
return null;
}
}
现在,创建一个接口,在所有平台上使用您想要的方法:
public interface GluonPlatform {
void vibrate();
}
最后,在您的主 class 检索平台并调用您的方法:
@Override
public void start(Stage stage) {
final Button button = new Button("Click me!");
button.setOnAction(e-> GluonPlatformFactory.getPlatform().vibrate());
StackPane root = new StackPane(button);
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Scene scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(scene);
stage.show();
}
Desktop/Java 套餐
添加振动方法。现在将其留空,但您可以添加一个 Timeline
来移动按钮,例如。
public class GluonDesktopPlatform implements GluonPlatform {
@Override
public void vibrate() {
System.out.println("Vibrating!");
}
}
Android/Java 套餐
添加振动方法。请注意,我们必须使用 FXActivity
,它是 JavaFX 线程和 Android activity.
之间的桥梁
public class GluonAndroidPlatform implements GluonPlatform {
@Override
public void vibrate() {
Vibrator v = (Vibrator) FXActivity.getInstance().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
}
}
不要忘记在您的 AndroidManifest 文件中添加所需的权限(您可以在 src/android/AndroidManifest.xml
.
下找到它
现在您可以部署项目并将其 运行 部署在桌面 (gradlew run
) 上,它会工作,并将其安装在 Android (gradlew androidInstall
) 上,并且它也会起作用。
用于将 JavaFX 移植到 Android 的 Gluon 插件的 gradle 构建(在 Netbeans 8.0.2 中)创建了以下目录结构:
- 源包[Java]
- Android/Java 包
- Desktop/Java 包
- Ios/Java 包
这些目录中的每一个都包含 java 个包。通常,Gluon 构建会在 "Source Packages" 目录中的一个 java 包中为我们创建 "main" class [名称为 "Source Packages" 的包可能会产生误导,因为它不是Java 包,它只是一个文件系统目录]。这个 main class 扩展了 Javafx Application class,因此是我们应用程序的入口点。
Android API 只能在 Android/Java Packages 目录中访问其中创建的任何 java 包。比如说,android.Vibrator class 只能在这里引用。
问题是,我们无法将在 Android/Java 目录内的任何 Java 包内创建的 class 引用到在源包 [[=] 内创建的任何 java 包46=]]目录!!如果是这种情况,那么我们如何将应用程序从 javafx.Application 的 start() 方法推进到 android.Vibrator。
gluon 项目结构的快照位于:
如您所知,JavaFXPorts 项目允许在桌面、Android 和 iOS 设备中部署 JavaFX 应用程序。当它只是纯 JavaFX 代码时,项目被添加到 Main 范围,从那里它将在所有这些平台中可见。
只有在您需要一些平台特定代码的情况下,您才应该将其添加到相应的包中。
正如您所提到的,默认情况下,您不会在主包中看到平台包中添加的代码,因此您必须为此提供一种方法。
如果您检查 JavaFXPorts 存储库上的 HelloPlatform sample,您会发现 PlatformService
class 使用 ServiceLoader
加载包。
另一种可能性是使用 Class.forName()
在 运行 时间动态加载 classes,一旦我们知道应用所在的平台 运行ning。
我建议你看一下 Gluon Down 项目,它为你管理几个特定于平台的服务,并为你提供统一的、平台无关的 API。
对于 Down (feel free to contribute), you can implement them like in this simple app created using Gluon Plugin 中尚不可用的那些服务。
源包[Java]
首先,创建一个getPlatform()
方法,并将引用的classes添加到每个特定平台。例如,在 Android 包上添加 org.gluonoss.vibrator.GluonAndroidPlatform.java
。
public class GluonPlatformFactory {
public static GluonPlatform getPlatform() {
try {
String platform = System.getProperty("javafx.platform", "desktop");
String path = "org.gluonoss.vibrator.GluonDesktopPlatform";
if(platform.equals("android")) {
path = "org.gluonoss.vibrator.GluonAndroidPlatform";
} else if(platform.equals("ios")) {
path = "org.gluonoss.vibrator.GluonIosPlatform";
}
return (GluonPlatform) Class.forName(path).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
System.out.println("Platform Error "+e.getMessage());
}
return null;
}
}
现在,创建一个接口,在所有平台上使用您想要的方法:
public interface GluonPlatform {
void vibrate();
}
最后,在您的主 class 检索平台并调用您的方法:
@Override
public void start(Stage stage) {
final Button button = new Button("Click me!");
button.setOnAction(e-> GluonPlatformFactory.getPlatform().vibrate());
StackPane root = new StackPane(button);
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Scene scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(scene);
stage.show();
}
Desktop/Java 套餐
添加振动方法。现在将其留空,但您可以添加一个 Timeline
来移动按钮,例如。
public class GluonDesktopPlatform implements GluonPlatform {
@Override
public void vibrate() {
System.out.println("Vibrating!");
}
}
Android/Java 套餐
添加振动方法。请注意,我们必须使用 FXActivity
,它是 JavaFX 线程和 Android activity.
public class GluonAndroidPlatform implements GluonPlatform {
@Override
public void vibrate() {
Vibrator v = (Vibrator) FXActivity.getInstance().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
}
}
不要忘记在您的 AndroidManifest 文件中添加所需的权限(您可以在 src/android/AndroidManifest.xml
.
现在您可以部署项目并将其 运行 部署在桌面 (gradlew run
) 上,它会工作,并将其安装在 Android (gradlew androidInstall
) 上,并且它也会起作用。