javafxports Путь к файлу javafx.scene.media.Media после сборки

Итак, я пытался преобразовать один из моих проектов java fx в приложение для Android, используя gluon. Это сцена, в которой реализован просмотрщик изображений и т. д. Поэтому я ожидал, что все файлы будут доступны, однако при использовании мультимедиа, независимо от того, куда я поместил файл или указал путь, я не могу заставить приложение обнаружить .wav файл в моем проекте. Мне было интересно, могу ли я получить помощь в том, куда поместить мой файл .wav и что использовать в качестве URL-адреса для части кода Media ("").

package com.junhong.faceclickb;

import com.gluonhq.charm.down.Services;
import com.gluonhq.charm.down.plugins.VideoService;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Graphics extends Application {
    BorderPane borderPane = new BorderPane();
    ToolBar toolbar = new ToolBar();
    Group root = new Group();
    Scene scene = new Scene(root);
    Score score = new Score(0);
    Text generation = new Text("Score: " + score.getScore());
    private Animate animate = new Animate();
    private ImageView img = new ImageView();
    Face face;
    Bounds bounds = borderPane.getBoundsInLocal();
    double dx = 5;
    double dy = 5;

    public static void main(String[] args) {

        launch(args);
    }

    public Parent createContent() {
        // // top
        HBox top = new HBox();
        top.getChildren().add(generation);
        borderPane.setTop(top);
        // face
        face = new Face("normalFace.png");
        EventHandler myMouseEvent = new myMouseEvent();
        img.setImage(new Image(face.getImgName()));
        img.setOnMousePressed(myMouseEvent);
        borderPane.setCenter(img);
        return borderPane;
    }

    private void setRandomDx() {
        dx = (int) (Math.random() * 20);
    }

    private void setRandomDy() {
        dy = (int) (Math.random() * 20);
    }

    // private void directionMove(ImageView img, double speed, double direction) {
    // dx = face.getXValue() + Math.cos(direction * (Math.PI / 180)) * speed;
    // dy = face.getYValue() + Math.sin(direction * (Math.PI / 180)) * speed;
    // moveImg(img, dx, dy);
    //
    // }

    private void speedImg(ImageView img, double dx, double dy) {
        borderPane.getChildren().remove(img);
        face.setXValue(face.getXValue() + dx);
        face.setYValue(face.getYValue() + dy);
        img.setX(face.getXValue());
        img.setY(face.getYValue());
        borderPane.getChildren().add(img);
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("Face Clicker");
        stage.setScene(new Scene(createContent()));
        stage.sizeToScene();
        stage.show();
        Services.get(VideoService.class).ifPresent(service -> {
            service.getPlaylist().add("china.wav");
            service.play();
        });

    }

    class myMouseEvent implements EventHandler<MouseEvent> {

        @Override
        public void handle(MouseEvent e) {

            if (e.getButton() == MouseButton.PRIMARY) {
                score.addScore(1, 1);
                generation.setText("Score: " + score.getScore());
                // if(Math.random()*5 == 1){
                // face.setRage();
                // }
                // if(face.getRage()){
                setRandomDx();
                setRandomDy();
                // }

                animate.start();

            }

        }

    }

    private class Animate extends AnimationTimer {
        private long n = 100_000_000;
        private long last = 0;

        @Override
        public void handle(long now) {
            if (now - last >= n) {
                // what happens when animation happens
                if (face.getXValue() + img.getBoundsInLocal().getWidth() / 2 > borderPane.getWidth()) {
                    dx = -dx;
                }
                if (face.getXValue() - img.getBoundsInLocal().getWidth() / 2 <= (-1) * borderPane.getWidth() / 2) {
                    dx = -dx;
                }
                if (img.getBoundsInLocal().getHeight() / 2 + face.getYValue() >= borderPane.getHeight() / 2) {
                    dy = -dy;
                }
                if (face.getYValue() - img.getBoundsInLocal().getHeight() / 2 <= (-1) * borderPane.getHeight() / 2) {
                    dy = -dy;
                }
                speedImg(img, dx, dy);

            }
        }
    }

}

это полный лог кот:

09-22 16:28:44.475 29162 29167 I art     : Do partial code cache collection, code=26KB, data=30KB
09-22 16:28:44.475 29162 29167 I art     : After code cache collection, code=25KB, data=30KB
09-22 16:28:44.475 29162 29167 I art     : Increasing code cache capacity to 128KB
09-22 16:28:44.634 29162 29185 W art     : Before Android 4.1, method double javafx.scene.text.TextFlow.computeChildPrefAreaHeight(javafx.scene.Node, javafx.geometry.Insets) would have incorrectly overridden the package-private method in javafx.scene.layout.Region
09-22 16:28:44.634 29162 29185 W art     : Before Android 4.1, method double javafx.scene.text.TextFlow.computeChildPrefAreaWidth(javafx.scene.Node, javafx.geometry.Insets) would have incorrectly overridden the package-private method in javafx.scene.layout.Region
09-22 16:28:44.634 29162 29185 I System.out: 0.0,0.0
09-22 16:28:44.635  1241  3128 D CustomFrequencyManagerService: releaseDVFSLockLocked : Getting Lock type frm List : DVFS_MIN_LIMIT  frequency : 2361600  uid : 1000  pid : 1241  tag : APP_LAUNCH@CPU_MIN@6
09-22 16:28:44.636 29162 29185 W art     : Class javafx.scene.image.Image failed lock verification and will run slower.
09-22 16:28:44.644 29162 29185 W art     : Class com.sun.javafx.iio.ImageStorage failed lock verification and will run slower.
09-22 16:28:44.734 29162 29185 W art     : Class javafx.scene.Scene$ScenePeerPaintListener failed lock verification and will run slower.
09-22 16:28:44.737 29162 29185 W art     : Before Android 4.1, method void com.sun.javafx.scene.transform.TransformUtils$ImmutableTransform.ensureCanTransform2DPoint() would have incorrectly overridden the package-private method in javafx.scene.transform.Transform
09-22 16:28:44.748 29162 29185 W art     : Class com.sun.javafx.text.GlyphLayout failed lock verification and will run slower.
09-22 16:28:44.778 29162 29185 I DefaultVideoService: Playlist changed: { [china.wav] added at 0 }
09-22 16:28:44.778 29162 29185 I DefaultVideoService: file: china.wav already exists
09-22 16:28:44.779 29162 29185 I AndroidVideoService: Creating new MediaPlayer for china.wav
09-22 16:28:44.785 29162 29185 I MediaPlayer: Need to enable context aware info
09-22 16:28:44.785 29162 29185 V MediaPlayer-JNI: native_setup
09-22 16:28:44.785 29162 29185 E MediaPlayer-JNI: JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
09-22 16:28:44.785 29162 29185 E MediaPlayer-JNI: JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
09-22 16:28:44.785 29162 29185 V MediaPlayer: constructor
09-22 16:28:44.788 29162 29185 V MediaPlayer: setListener
09-22 16:28:44.801   757   757 V MediaPlayerService: Create new media retriever from pid 29162
09-22 16:28:44.805 29162 29185 W System.err: Exception in Application start method
09-22 16:28:44.833  1241  1699 I qti_sensors_hal: processReportInd: Accel - X: 0.893 Y: 1.211 Z: 9.90

person Jun Hong    schedule 21.09.2017    source источник


Ответы (1)


JavaFX на мобильных устройствах не поддерживает мультимедиа. См. этот ответ, чтобы узнать о текущих поддерживаемых функциях.

Но это не значит, что вы не можете использовать родной плеер со своего устройства.

Недавно Charm Down (библиотека с открытым исходным кодом для доступа к устройству и его аппаратным функциям с использованием единого, независимого от платформы API) добавлен видеосервис.

Вы можете увидеть небольшой пост о том, как его использовать здесь.

В основном вам нужно включить плагин video в вашу сборку:

// build.gradle
jfxmobile {
    downConfig {
        version = '3.6.0'
        plugins 'display', 'lifecycle', 'statusbar', 'storage', 'video'
    }
}

поместите аудио/видео файлы в папку ресурсов /src/main/resoures или укажите действительный URL-адрес, после чего вы сможете использовать сервис:

Services.get(VideoService.class).ifPresent(service -> {
    service.getPlayList().add("myAudio.wav");
    service.play(); 
});

Звук не добавляет никакого видимого элемента управления (MediaView), он воспроизводится в фоновом режиме. Вы можете добавить несколько кнопок для воспроизведения/паузы/остановки звука.

person José Pereda    schedule 21.09.2017
comment
Большое спасибо за ответ, я добавил плагин в build.gradle, но я не могу использовать сервис, так как код не может найти VideoService.class, мне нужно сделать что-то еще, чтобы использовать сервис ? - person Jun Hong; 22.09.2017
comment
После изменения файла сборки вам необходимо перезагрузить проект, чтобы загрузить новые зависимости. Если вы откроете проект, проверьте в зависимостях, если вы найдете jar-файлы charm-down-plugin-*. - person José Pereda; 22.09.2017
comment
Извините за все вопросы, я все еще новичок в кодировании, я смог вручную добавить видео-плагин в зависимости. и код теперь компилируется, однако код, похоже, не хочет выполнять службу. Появляется это сообщение: СЕРЬЕЗНО: javafx.platform не определен. Рабочий стол будет использоваться по умолчанию. В то время как остальная часть кода выполняется, когда служба вызывается, программа как бы просто зависает. - person Jun Hong; 23.09.2017
comment
Обратите внимание, что сервис доступен только на мобильных устройствах (Android и iOS), поэтому вам следует протестировать его на своем устройстве. В любом случае, он не должен зависать на рабочем столе, так как Services.get(VideoService.class).ifPresent() не будет выполняться. - person José Pereda; 23.09.2017
comment
хм, при вызове он просто переходит в черный экран на моем андроиде, лог-кот извергает это: 09-22 15:44:05.565 11733 11753 W System.err: java.lang.reflect.InvocationTargetException 09-22 15:44:05.565 11733 11753 W System.err: at java.lang.reflect.Method.invoke(Native Method) ... 09-22 15:44:05.565 11733 11753 W System.err: ... 1 more 09-22 15:44:05.565 11733 11753 W System.err: Caused by: java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA 09-22 15:44:05.565 11733 11753 W System.err: at android.media.MediaMetadataRetriever._setDataSource(Native Method) - person Jun Hong; 23.09.2017
comment
Можете ли вы отредактировать свой вопрос и опубликовать соответствующий код и трассировку стека? - person José Pereda; 23.09.2017
comment
Извините за это, я только что добавил код, и мое устройство Android вернуло лог-кошку при открытии кода. - person Jun Hong; 23.09.2017
comment
Добавьте этот System.setProperty("com.gluonhq.charm.down.debug", "true"); перед вызовом службы, чтобы получить более подробный вывод. Разверните снова и опубликуйте соответствующий вывод. - person José Pereda; 23.09.2017
comment
Это не полный логкэт. Если вы не можете опубликовать все необходимое (слишком длинное), не могли бы вы добавить ссылку на это? - person José Pereda; 23.09.2017
comment
Я сделал документ Google с полным логом cat. Спасибо тебе за помощь. :) docs.google.com/document/d/ - person Jun Hong; 23.09.2017
comment
Я не могу сказать точно, но кажется, что аудиофайл неправильный. Можете ли вы дважды проверить, что вы поместили его под /src/main/resources? Можно ли играть на рабочем столе? Можете ли вы попробовать с другим файлом, mp3? - person José Pereda; 23.09.2017