【问题标题】:javafxports how to call android native Media Playerjavafxports如何调用android原生媒体播放器
【发布时间】:2016-07-17 09:11:38
【问题描述】:

由于尚未实现 javafxports Media,我希望改用 Android Native MediaPlayer。有谁知道如何做到这一点。

【问题讨论】:

    标签: android javafx android-mediaplayer javafxports


    【解决方案1】:

    如果您查看 GoNative 示例 heredocscode),您会找到一种将 Android 本机代码添加到 JavaFX 项目的方法。

    这是一个使用 Gluon 插件将 android.media.MediaPlayer 添加到 JavaFX 项目的简单示例。

    基于 Single View 项目,我们先添加一个带有所需音频方法签名的接口:

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

    现在在我们的视图中,我们可以创建按钮来调用这些方法,基于实现NativeAudioService 接口的AndroidNativeAudio 类的实例:

    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 文件夹下创建原生类。它将使用 android API。它将尝试找到我们必须放在/src/android/assets 文件夹下的音频文件audio.mp3

    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);
            }
        }
    }
    

    最后,我们可以将项目部署到运行gradlew androidInstall的Android设备上。

    【讨论】:

    • - 完美。效果很好。
    • 我目前正在尝试按照您的建议实现它,@josé-pereda - 但我找不到 Android 类 "MediaPlayer" 。我为 FXActivity 添加了compile 'org.javafxports:jfxdvk:8.60.8',但不明白,还需要什么。我猜是android.jar,对吧?但具体在哪里? (顺便说一句:我正在使用 Eclipse 插件,如果这很重要的话。)
    • 我能够通过添加此依赖项来实现它:compile files('libs/android-22.jar')(其中数字 22 标记了目标 SDK)。但我明确需要在构建应用程序之前评论这一行,因为否则 Retrolambda 会崩溃......此外,我听不到任何声音,音量按钮事件似乎不会触发通常的音量增大/减小行为。 #edit:我在设置中提高了音量,但仍然听不到任何声音。我没有收到任何错误,所以一切似乎都很好,但无论如何都无法正常工作......
    • 由于我的编辑没有被批准:当前示例使用铃声音量,为了让您应用程序使用音乐/媒体音量,您应该添加以下行:FXActivity.getInstance().setVolumeControlStream(AudioManager.STREAM_MUSIC); 另外您需要更改mp.setAudioStreamType(AudioManager.STREAM_RING);mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
    • @dzim 关于您的依赖问题,如果您使用 jfxmobile 插件,并为您的 android sdk 路径提供有效的 ANDROID_HOME,您的项目中应该默认包含 android jar。如果您仍有问题,请创建一个新问题。
    【解决方案2】:

    本机音频播放器用于以下示例:

    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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多