- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我尝试在 Android 上运行一个简单的 JavaFX 应用程序。因此我读了javafxports Getting Started Guide使用 gradle 构建应用程序,但我被困在某个地方。我可以在 Eclipse 中使用 gradle 的 installDebug
任务在 Android 设备上构建和安装该应用程序,但是,当我启动该应用程序时,出现黑屏。当我提取 .apk
文件时,它不包含 JavaFX 应用程序的 jar 文件。我假设 apk 应该包含 JavaFX 应用程序 jar 文件,但我不知道如何将它包含到 .apk
中。
我还尝试使用 gradle 构建 JavaFX 应用程序本身(jar 文件),效果很好。但是,我不知道把这个 jar 文件放在哪里,它可以包含在 apk 文件中。我读到我必须将它放入 dist
目录,但我认为这只会在 Netbeans 中使用,对吗?我正在使用 Eclipse gradle 集成来构建项目。
这是我尝试过的。由于 JavaFX 应用程序与 HelloWorld 示例应用程序一样简单,并且运行起来非常棒,我希望我的 gradle 构建文件中存在配置错误。
build.gradle - 构建 apk
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'android'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:2.5.0'
classpath 'com.android.tools.build:gradle:1.0.1'
}
}
repositories {
jcenter()
}
ext {
dalvikSdkHome = getProjectProperty('dalvikSDK')
dalvikSdkLib = dalvikSdkHome + '/rt/lib'
}
android {
compileSdkVersion 21
buildToolsVersion "21.1.1"
dexOptions {
preDexLibraries = false
}
sourceSets {
main {
jniLibs.srcDir file("${dalvikSdkLib}/")
assets.srcDirs = ['assets']
}
}
lintOptions {
abortOnError false
}
}
dependencies {
compile files ("${dalvikSdkLib}/ext/jfxrt.jar",
"${dalvikSdkLib}/ext/jfxdvk.jar",
"${dalvikSdkLib}/ext/compat-1.0.0.jar")
}
project.tasks.withType(com.android.build.gradle.tasks.Dex) {
additionalParameters=['--core-library']
}
String getProjectProperty(String propertyName) {
project.hasProperty(propertyName) ? project.property(propertyName) : null
}
build.gradle - 构建 jar
// Declares binary plugin and its required JavaFX classpath
apply from: "http://dl.bintray.com/content/shemnon/javafx-gradle/0.4.0/javafx.plugin"
// Configures plugin
javafx {
// Points to JDK and its JavaFX libraries, also declares target runtime JDK
javaRuntime = getProjectProperty('javaJDKPath')
// Application name and ID presented by target OS
appID 'HelloWorldApp'
appName 'Hello World Application'
// Main class of application
mainClass 'helloworld.HelloWorld'
// JVM arguments, system properties, application command line arguments
jvmArgs = ['-XX:+AggressiveOpts', '-XX:CompileThreshold=1']
systemProperties = ['prism.disableRegionCaching':'true']
arguments = ['-l', '--fast']
// Keystore credentials for signing JAR
// Generate key: keytool -genkey -alias release -keyalg RSA -keystore keystore.jks -keysize 2048
releaseKey {
alias = 'release'
keyStore = file(getProjectProperty('keystoreJKSFile')) // keyStore = file("${System.properties['user.home']}/keystore/keystore.jks")
keyPass = getProjectProperty('keyStorePassword')
storePass = getProjectProperty('storePassword')
}
signingMode 'release'
// ...
}
String getProjectProperty(String propertyName) {
project.hasProperty(propertyName) ? project.property(propertyName) : null
}
gradle.properties
javaJDKPath=D:/Java/jdk1.8.0_20
dalvikSDK=D:/Java/dalvik-sdk-8u20b3/dalvik-sdk
keystoreJKSFile=D:/Java/jre1.8.0_20/bin/keystore.jks
keyStorePassword=password
storePassword=password
local.properties
sdk.dir=D:/programme/Android/adt-bundle-windows-x86_64-20130917/sdk
这是我的项目结构
HelloWorld
-- src\main
-- java\helloworld\HelloWorld.java
-- res\
-- AndroidManifest.xml
-- assets\
-- javafx.platform.properties
-- javafx.properties
-- build.gradle
-- gradle.properties
-- local.properties
我需要使用 dist
目录吗?我应该将我的 JavaFX 应用程序的 jar 文件放在哪里,它将包含在 apk 文件中?
最佳答案
现在回答我自己的问题。如我的问题中所述,gradle 设置的配置已经在运行。在我的问题中,我没有向您展示我正在使用 .fxml 文件进行布局。所以我没有让它运行的原因是因为 .fxml 布局没有放在正确的位置以与 apk 文件一起打包(LogCat 显示错误 Location Not Found
并且我有一个我的设备出现黑屏)。
首先,这是 HelloWorld.java 的工作示例(请参阅我的问题中的结构和 gradle 设置等):
package helloworld;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
如果您想使用.fxml
文件,您需要稍微更改项目的结构。所有.fxml
文件、.css
文件、图形等都属于resources\assets
目录或子目录。这样可以确保 .fxml 文件等将被打包到 apk 中。
HelloWorld
-- src\main
-- java\helloworld\
-- HelloWorld.java
-- MyController.java
-- resources\assets\
-- sample_layout.fxml
-- AndroidManifest.xml
-- assets\
-- javafx.platform.properties
-- javafx.properties
-- build.gradle
-- gradle.properties
-- local.properties
我没有检查是否包含 javafx.platform.properties
和 javafx.properties
的 assets
文件夹(均来自dalvikVM sdk) 仍然是必需的。如果我检查 .apk 文件的内容,apk 包含这两个文件两次。似乎 dalvikVM 库会自动复制这些文件。
注意:如果您需要检查 apk 的内容,请提取 apk 文件,然后提取作为 apk 一部分的 classes.dex (see this post for more details)
这是一个使用 .fxml 文件的示例:
HelloWorld.java
package helloworld;
import java.io.IOException;
import java.net.URL;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
try {
URL fxmlFile = getClass().getResource("/assets/sample_layout.fxml");
FXMLLoader loader = new FXMLLoader(fxmlFile);
AnchorPane page = (AnchorPane) loader.load();
MyController controller = (MyController) loader.getController();
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("JavaFX Sample");
primaryStage.show();
} catch(IOException e) {
e.printStackTrace();
}
}
}
MyController.java
package helloworld;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
public class MyController {
@FXML
private ResourceBundle resources;
@FXML
private URL location;
@FXML
private Label label_Counter;
@FXML
private Button button_IncrementCounter;
@FXML
private Button button_DecrementCounter;
private static final String OUTPUT_PREFIX = "Counter: ";
private static int counter = 0;
@FXML
void onIncrementButtonPressed(ActionEvent event) {
label_Counter.setText(OUTPUT_PREFIX + ++counter);
}
@FXML
void onDecrementButtonPressed(ActionEvent event) {
label_Counter.setText(OUTPUT_PREFIX + --counter);
}
@FXML
void initialize() {
assert label_Counter != null : "fx:id=\"label_Counter\" was not injected: check your FXML file 'sample_layout.fxml'.";
assert button_IncrementCounter != null : "fx:id=\"button_IncrementCounter\" was not injected: check your FXML file 'sample_layout.fxml'.";
assert button_DecrementCounter != null : "fx:id=\"button_DecrementCounter\" was not injected: check your FXML file 'sample_layout.fxml'.";
label_Counter.setText(OUTPUT_PREFIX + 0);
}
}
sample_layout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="helloworld.MyController">
<children>
<VBox layoutX="332.0" layoutY="71.0" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label text="Please click on the buttons to increment or decrement the counter:" />
<Button fx:id="button_IncrementCounter" mnemonicParsing="false" onAction="#onIncrementButtonPressed" text="Increment Counter">
<VBox.margin>
<Insets top="10.0" />
</VBox.margin>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</Button>
<Button fx:id="button_DecrementCounter" mnemonicParsing="false" onAction="#onDecrementButtonPressed" text="Decrement Counter">
<VBox.margin>
<Insets top="10.0" />
</VBox.margin>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</Button>
<Label fx:id="label_Counter" text="<output-placeholder>">
<VBox.margin>
<Insets top="20.0" />
</VBox.margin>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
</children>
</AnchorPane>
希望能帮助其他人在 Android 上开始使用 JavaFX。
关于android - 如何在 Android 上运行 JavaFX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27794717/
我是一名优秀的程序员,十分优秀!