Javafxports How To Call Android Native Media Player
Solution 1:
If you have a look at the GoNative sample here (docs and code), you'll find a way to add Android native code to your JavaFX project.
This is a simple example of adding android.media.MediaPlayer
to a JavaFX project using the Gluon plugin.
Based on a Single View project, let's add first an interface with the required audio method signatures:
publicinterfaceNativeAudioService {
voidplay();
voidpause();
voidresume();
voidstop();
}
Now in our View we can create the buttons to call those methods based on an instance of AndroidNativeAudio
class that implements the NativeAudioService
interface:
publicclassBasicViewextendsView {
private NativeAudioService service;
privateboolean pause;
publicBasicView(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) {
finalHBoxhBox=newHBox(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(newStackPane(hBox));
} else {
setCenter(newStackPane(newLabel("Only for Android")));
}
}
@OverrideprotectedvoidupdateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MUSIC_NOTE.button());
appBar.setTitleText("Native Audio");
}
}
Now, we create the native class under the Android folder. It will make use of the android API. It will try to find the audio file audio.mp3
that we have to place under the /src/android/assets
folder:
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;
publicclassAndroidNativeAudioimplementsNativeAudioService {
private MediaPlayer mp;
privateint currentPosition;
publicAndroidNativeAudio() { }
@Overridepublicvoidplay() {
currentPosition = 0;
try {
if (mp != null) {
stop();
}
mp = newMediaPlayer();
AssetFileDescriptorafd= 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);
}
}
@Overridepublicvoidstop() {
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
}
mp.release();
mp = null;
}
}
@Overridepublicvoidpause() {
if (mp != null) {
mp.pause();
currentPosition = mp.getCurrentPosition();
}
}
@Overridepublicvoidresume() {
if (mp != null) {
mp.start();
mp.seekTo(currentPosition);
}
}
}
Finally, we can deploy the project to an Android device running gradlew androidInstall
.
Solution 2:
The native audio player was used in the following example:
https://gist.github.com/bgmf/d87a2bac0a5623f359637a3da334f980
Beside some prerequisites, the code looks like this:
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;
publicclassNativeAudioServiceIOSextendsPathHelperIOSimplementsNativeAudioService {
privatestaticfinalLoggerLOG= Logger.getLogger(NativeAudioServiceIOS.class.getName());
privatestaticfinalStringDIR_NAME= Constants.OBJECTS_BASE_PATH;
privatefinal ReadOnlyObjectWrapper<Status> status = newReadOnlyObjectWrapper<>(this, "status", Status.STOP);
privateStringfilename=null;
privateAVAudioPlayerplayer=null;
publicNativeAudioServiceIOS() {
super();
}
@Overridepublicvoidinit(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;
Filefullfile=newFile(pathBase.getAbsolutePath() + filename);
if(fullfile.exists()) {
NSURLfullurl=newNSURL(NSURLScheme.File, "", fullfile.getAbsolutePath());
LOG.log(Level.SEVERE, "Loading URL: " + fullurl);
// Create audio player object and initialize with URL to sound
player = newAVAudioPlayer(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);
}
}
@Overridepublicvoidplay()throws NativeServiceException {
if(player == null) return;
player.play();
status.set(Status.PLAY);
}
@Overridepublicvoidpause()throws NativeServiceException {
if(player == null) return;
player.pause();
status.set(Status.PAUSE);
}
@Overridepublicvoidresume()throws NativeServiceException {
if(player == null) return;
player.play();
status.set(Status.PLAY);
}
@Overridepublicvoidstop()throws NativeServiceException {
if(player == null) return;
player.stop();
player.setCurrentTime(0.0);
status.set(Status.STOP);
}
@Overridepublic ReadOnlyObjectProperty<Status> statusProperty() {
return status.getReadOnlyProperty();
}
@Overridepublic Status getStatus() {
return status.get();
}
}
Post a Comment for "Javafxports How To Call Android Native Media Player"