javafxports, как вызвать Android родной Media Player

1

Поскольку javafxports Media еще не реализована, я вместо этого использую Android Native MediaPlayer. Кто-нибудь знает, как это сделать.

Теги:
javafx
android-mediaplayer
javafxports

2 ответа

5

Если вы посмотрите на образец GoNative здесь (docs и code), вы найдете способ добавить собственный код Android в свой проект JavaFX.

Это простой пример добавления android.media.MediaPlayer в проект JavaFX с использованием плагина Gluon.

На основе проекта Single View добавьте сначала интерфейс с необходимыми сигнатурами звукового метода:

public interface NativeAudioService {
    void play();
    void pause();
    void resume();
    void stop();
}

Теперь в нашем представлении мы можем создать кнопки для вызова этих методов на основе экземпляра класса AndroidNativeAudio, который реализует интерфейс NativeAudioService:

public class BasicView extends View {

    private NativeAudioService service;
    private boolean pause;

    public BasicView(String name) {
        super(name);

        try {
            service = (NativeAudioService) Class.forName("com.gluonhq.nativeaudio.AndroidNativeAudio").newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
            System.out.println("Error " + ex);
        }

        if (service != null) {
            final HBox hBox = new HBox(10, 
                    MaterialDesignIcon.PLAY_ARROW.button(e -> service.play()),
                    MaterialDesignIcon.PAUSE.button(e -> {
                        if (!pause) {
                            service.pause();
                            pause = true;
                        } else {
                            service.resume();
                            pause = false;
                        }
                    }),
                    MaterialDesignIcon.STOP.button(e -> service.stop()));
            hBox.setAlignment(Pos.CENTER);
            setCenter(new StackPane(hBox));
        } else {
            setCenter(new StackPane(new Label("Only for Android")));
        }
    }

    @Override
    protected void updateAppBar(AppBar appBar) {
        appBar.setNavIcon(MaterialDesignIcon.MUSIC_NOTE.button());
        appBar.setTitleText("Native Audio");
    }
}

Теперь мы создаем родной класс под папкой Android. Он будет использовать API android. Он попытается найти аудиофайл audio.mp3, который мы должны разместить в папке /src/android/assets:

package com.gluonhq.nativeaudio;

import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import java.io.IOException;
import javafxports.android.FXActivity;

public class AndroidNativeAudio implements NativeAudioService {

    private MediaPlayer mp;
    private int currentPosition;

    public AndroidNativeAudio() { }

    @Override
    public void play() {
        currentPosition = 0;
        try {
            if (mp != null) {
                stop();
            }
            mp = new MediaPlayer();
            AssetFileDescriptor afd = FXActivity.getInstance().getAssets().openFd("audio.mp3");

            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            mp.setAudioStreamType(AudioManager.STREAM_RING);
            mp.setOnCompletionListener(mp -> stop());
            mp.prepare();
            mp.start();
        } catch (IOException e) {
            System.out.println("Error playing audio resource " + e);
        }
    }

    @Override
    public void stop() {
        if (mp != null) {
            if (mp.isPlaying()) {
                mp.stop();
            }
            mp.release();
            mp = null;
        }
    }

    @Override
    public void pause() {
        if (mp != null) {
            mp.pause();
            currentPosition = mp.getCurrentPosition();
        }
    }

    @Override
    public void resume() {
        if (mp != null) {
            mp.start();
            mp.seekTo(currentPosition);
        }
    }
}

Наконец, мы можем развернуть проект на Android-устройстве под управлением gradlew androidInstall.

Изображение 174551

  • 0
    - Отлично. Работает отлично.
  • 0
    В настоящее время я пытаюсь реализовать это, как вы предложили, @ josé-pereda - Но я не могу найти класс Android "MediaPlayer". Я включил compile 'org.javafxports:jfxdvk:8.60.8' для FXActivity, но не понимаю, что еще нужно. Я думаю, android.jar , верно? Но где именно? (кстати: я использую плагин Eclipse, если это важно.)
Показать ещё 4 комментария
1

Собственный аудиоплеер использовался в следующем примере:

https://gist.github.com/bgmf/d87a2bac0a5623f359637a3da334f980

Помимо некоторых предварительных условий, код выглядит следующим образом:

package my.application;

import my.application.Constants;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import org.robovm.apple.avfoundation.AVAudioPlayer;
import org.robovm.apple.foundation.NSErrorException;
import org.robovm.apple.foundation.NSURL;
import org.robovm.apple.foundation.NSURLScheme;

import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;

public class NativeAudioServiceIOS extends PathHelperIOS implements NativeAudioService {
    private static final Logger LOG = Logger.getLogger(NativeAudioServiceIOS.class.getName());
    private static final String DIR_NAME = Constants.OBJECTS_BASE_PATH;

    private final ReadOnlyObjectWrapper<Status> status = new ReadOnlyObjectWrapper<>(this, "status", Status.STOP);
    private String filename = null;
    private AVAudioPlayer player = null;

    public NativeAudioServiceIOS() {
        super();
    }

    @Override
    public void init(String filename) throws NativeServiceException {
        this.filename = filename.startsWith("/") ? filename.substring(1) : filename;
        LOG.warning("Called with file: " + filename);
        status.set(Status.STOP);

        try {
            if(!filename.startsWith("/")) filename = "/" + filename;
            File fullfile = new File(pathBase.getAbsolutePath() + filename);
            if(fullfile.exists()) {
                NSURL fullurl = new NSURL(NSURLScheme.File, "", fullfile.getAbsolutePath());
                LOG.log(Level.SEVERE, "Loading URL: " + fullurl);

                // Create audio player object and initialize with URL to sound
                player = new AVAudioPlayer(fullurl);
                LOG.log(Level.SEVERE, "Player initialized: " + player);

                status.set(Status.STOP);
            } else {
                LOG.log(Level.WARNING, String.format("Audiofile doesn't exist: %s (%s / %s)",
                        fullfile.getAbsolutePath(),
                        pathBase.getAbsolutePath(),
                        filename));
                player = null;
                status.set(Status.ERROR);
            }
        } catch(NSErrorException error) {
            LOG.log(Level.SEVERE, "Audio Setup Failed: " + error.toString(), error);
            status.set(Status.ERROR);
        }
    }

    @Override
    public void play() throws NativeServiceException {
        if(player == null) return;

        player.play();
        status.set(Status.PLAY);
    }

    @Override
    public void pause() throws NativeServiceException {
        if(player == null) return;

        player.pause();
        status.set(Status.PAUSE);
    }

    @Override
    public void resume() throws NativeServiceException {
        if(player == null) return;

        player.play();
        status.set(Status.PLAY);
    }

    @Override
    public void stop() throws NativeServiceException {
        if(player == null) return;

        player.stop();
        player.setCurrentTime(0.0);
        status.set(Status.STOP);
    }

    @Override
    public ReadOnlyObjectProperty<Status> statusProperty() {
        return status.getReadOnlyProperty();
    }

    @Override
    public Status getStatus() {
        return status.get();
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню