Подтвердить что ты не робот

Как запустить JavaFX на Android

Я пытаюсь запустить простое приложение JavaFX на Android. Поэтому я прочитал javafxports Руководство по началу работы, используя gradle для создания приложения, но где-то я застрял. Я могу создать и установить приложение на устройстве Android, используя задачу installDebug gradle в Eclipse, однако при запуске приложения я получаю черный экран. Когда я извлекаю файл .apk, он не содержит файл jar приложения JavaFX. Я предполагаю, что apk должен содержать jar файл приложения JavaFX, но я не знаю, как включить его в .apk.

Я также попытался использовать gradle для создания самого приложения JavaFX (jar-file), который отлично работает. Однако я не знаю, куда положить этот 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 - для создания флага

// 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? Где бы я поместил jar файл моего приложения JavaFX, чтобы он был включен в apk файл?

4b9b3361

Ответ 1

Теперь отвечая на мой вопрос. Конфигурация установки 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();
    }
}

Запустите JavaFX на Android, используя макеты fxml

Если вы хотите использовать файлы .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

Я не проверял, если папка assets, содержащая javafx.platform.properties и javafx.properties (как из dalvikVM sdk), по-прежнему требуется. Если я проверю содержимое файла .apk, apk содержит оба файла дважды. Похоже, библиотека dalvikVM автоматически копирует эти файлы.

Примечание. Если вам нужно проверить содержимое вашего apk, извлеките файл apk, а затем извлеките classes.dex, который является частью apk (см. это сообщение для получения более подробной информации)

Вот пример использования файлов .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="&lt;output-placeholder&gt;">
               <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>

Надеюсь, что все остальные начнут работать с JavaFX на Android.

Ответ 2

Как запустить javafx на Android:

  • Загрузите dalvik sdk.
  • Перейдите к samples\HelloWorld\javafx - it gradle project
  • Изменить местоположение dalvik-sdk и android-sdk в local.properties
    Пример моей системы Windows:
    sdk.dir=C\:\\dev\\android-sdk javafx.dir=C\:\\dev\\dalvik-sdk
  • Запустите gradlew installDebug для создания и установки apk на устройстве. Вы также можете найти выходы в папке build
  • Запустить приложение на устройстве (я видел черный экран за 10 секунд до первого запуска).
  • Открыть проект в Eclipse или Idea в качестве стандартного проекта gradle