2016-07-17 21 views

回答

5

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

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

基于一个单一的视图项目,让我们添加第一个接口与所需的音频方法签名:

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的文件夹下创建的原生类。它会利用android API。它会尝试找到音频文件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); 
     } 
    } 
} 

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

+0

- 完美。很棒。 –

+0

我目前尝试实现它,如您所说,@josé-pereda - 但我无法找到Android类“MediaPlayer”。我为FXActivity编写了'compile'org.javafxports:jfxdvk:8.60.8'',但未能理解,还需要什么。我猜'android.jar',对吧?但究竟在哪里? (顺便说一句:我使用的Eclipse插件,如果这很重要。) – dzim

+0

我能够实现它,通过添加此依赖项:'编译文件('libs/android-22.jar')'(其中数字22标记目标SDK)。但我明确需要在构建应用程序之前对此行进行评论,否则Retrolambda会崩溃...此外,我听不到任何事情,并且卷按钮事件似乎不会触发通常的音量上/下行为。 #edit:我在设置中提升了音量,但仍然听不到任何声音。我没有收到任何错误,所以一切似乎都没有问题,但无法正常工作...... – dzim

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