Gluon移动iOS音频播放器

时间:2016-07-30 07:11:32

标签: javafx javafxports gluon gluon-mobile

由于JavaFx Media尚未移植到移动平台,任何人都可以帮助我使用原生iOS APi播放声音mp3文件,该文件将存储在我的胶子的main / resources文件夹中项目。

1 个答案:

答案 0 :(得分:3)

在Android上,我们可以轻松地将原生API添加到Gluon项目的Android文件夹中(检查此solution是否在Android上使用本机媒体),使用本机代码(Objetive-C)与Media API在iOS文件夹上是不够的,因为它必须被编译,并且编译的文件必须包含在ipa中。

目前,Charm Down正在为一堆服务执行此操作。如果您查看iOSbuild.gradle脚本,它包含xcodebuild任务来编译和构建本机库libCharm.a,以后应该包含在任何iOS中项目使用任何这些服务。

我的建议是克隆Charm Down,并提供一项新服务:AudioService,其中包括一些基本方法:

public interface AudioService {
    void play(String audioName);
    void pause();
    void resume();
    void stop(); 
}

此服务将添加到Platform类:

public abstract class Platform {
    ...
    public abstract AudioService getAudioService();
}

你应该为桌面(空),Android(如here}和iOS提供实现。

IOS实施 - Java

您必须将此添加到IOSPlatform类:

public class IOSPlatform extends Platform {
    ...
    @Override
    public AudioService getAudioService() {
        if (audioService == null) {
            audioService = new IOSAudioService();
        }
        return audioService;
    }
}

并创建IOSAudioService类:

public class IOSAudioService implements AudioService {

    @Override
    public void play(String audioName) {
        CharmApplication.play(audioName);
    }

    @Override
    public void pause() {
        CharmApplication.pause();
    }

    @Override
    public void resume() {
        CharmApplication.resume();
    }

    @Override
    public void stop() {
        CharmApplication.stop();
    }
}

最后,您必须在CharmApplication中添加原生调用:

public class CharmApplication {
    static {
        System.loadLibrary("Charm");
        _initIDs();
    }
    ...
    public static native void play(String audioName);
    public static native void pause();
    public static native void resume();
    public static native void stop();
}

IOS实施 - 目标-C

现在,在CharmApplication.m上的本机文件夹中,添加这些调用的实现:

#include "CharmApplication.h"
...
#include "Audio.h"

// Audio
Audio *_audio;

JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_ios_CharmApplication_play
(JNIEnv *env, jclass jClass, jstring jTitle)
{
    NSLog(@"Play audio");
    const jchar *charsTitle = (*env)->GetStringChars(env, jTitle, NULL);
    NSString *name = [NSString stringWithCharacters:(UniChar *)charsTitle length:(*env)->GetStringLength(env, jTitle)];
    (*env)->ReleaseStringChars(env, jTitle, charsTitle);

    _audio = [[Audio alloc] init];
    [_audio playAudio:name];
    return;
}

JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_ios_CharmApplication_pause
(JNIEnv *env, jclass jClass)
{
    if (_audio) 
    {
        [_audio pauseAudio];
    }
    return;   
}

JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_ios_CharmApplication_resume
(JNIEnv *env, jclass jClass)
{
    if (_audio) 
    {
        [_audio resumeAudio];
    }
    return;   
}

JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_ios_CharmApplication_stop
(JNIEnv *env, jclass jClass)
{
    if (_audio) 
    {
        [_audio stopAudio];
    }
    return;   
}

并创建标题文件Audio.h

#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>

@interface Audio :UIViewController <AVAudioPlayerDelegate>
{
}
    - (void) playAudio: (NSString *) audioName;
    - (void) pauseAudio;
    - (void) resumeAudio;
    - (void) stopAudio;
@end

和实施Audio.m。这个基于tutorial

#include "Audio.h"
#include "CharmApplication.h"

@implementation Audio 

AVAudioPlayer* player;

- (void)playAudio:(NSString *) audioName 
{
    NSString* fileName = [audioName stringByDeletingPathExtension];
    NSString* extension = [audioName pathExtension];

    NSURL* url = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"%@",fileName] withExtension:[NSString stringWithFormat:@"%@",extension]];
    NSError* error = nil;

    if(player)
    {
        [player stop];
        player = nil;
    }

    player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    if(!player)
    {
        NSLog(@"Error creating player: %@", error);
        return;
    }
    player.delegate = self;
    [player prepareToPlay];
    [player play];

}

- (void)pauseAudio
{
    if(!player)
    {
        return;
    }
    [player pause];
}

- (void)resumeAudio
{
    if(!player)
    {
        return;
    }
    [player play];
}

- (void)stopAudio
{
    if(!player)
    {
        return;
    }
    [player stop];
    player = nil;
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    NSLog(@"%s successfully=%@", __PRETTY_FUNCTION__, flag ? @"YES"  : @"NO");
}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
    NSLog(@"%s error=%@", __PRETTY_FUNCTION__, error);
}

@end

构建本机库

编辑iOS模块的build.gradle,并将音频服务添加到xcodebuild任务:

def nativeSources = ["$project.projectDir/src/main/native/CharmApplication.m",
                     ...,
                     "$project.projectDir/src/main/native/Audio.m"]

...
def compileOutputs = [
                "$project.buildDir/native/$arch/CharmApplication.o",
                "$project.buildDir/native/$arch/Charm.o",
                 ...,
                "$project.buildDir/native/$arch/Audio.o"]

构建项目

保存项目,并从Charm Down项目的根目录,在命令行运行:

./gradlew clean build

如果一切正常,你应该:

  • 普通/建造/库/魅力 - 下 - 共2.1.0-SNAPSHOT.jar
  • 桌面/建造/库/魅力 - 下 - 桌面2.1.0-SNAPSHOT.jar
  • 的Android /建造/库/魅力 - 下 - 机器人-2.1.0-SNAPSHOT.jar
  • IOS /建造/库/魅力 - 下 - IOS-2.1.0-SNAPSHOT.jar
  • IOS /建造/天然的/ libCharm.a

胶子项目

使用这些依赖项和本机库,您将能够创建一个新的Gluon项目,并将jar作为本地依赖项添加到libs文件夹中。

对于本机库,应将其添加到此路径:src/ios/jniLibs/libCharm.a

更新build.gradle脚本:

repositories {
    flatDir {
       dirs 'libs'
   }
    jcenter()
    ...
}

dependencies {
    compile 'com.gluonhq:charm-glisten:3.0.0'
    compile 'com.gluonhq:charm-down-common:2.1.0-SNAPSHOT'
    compile 'com.gluonhq:charm-glisten-connect-view:3.0.0'

    iosRuntime 'com.gluonhq:charm-glisten-ios:3.0.0'
    iosRuntime 'com.gluonhq:charm-down-ios:2.1.0-SNAPSHOT'
}

在您的视图上,检索服务并提供一些基本用户界面来调用play("audio.mp3")pause()resume()stop()方法:

private boolean pause;

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

    AudioService audioService = PlatformFactory.getPlatform().getAudioService();
    final HBox hBox = new HBox(10, 
            MaterialDesignIcon.PLAY_ARROW.button(e -> audioService.play("audio.mp3")),
            MaterialDesignIcon.PAUSE.button(e -> {
                if (!pause) {
                    audioService.pause();
                    pause = true;
                } else {
                    audioService.resume();
                    pause = false;
                }

            }),
            MaterialDesignIcon.STOP.button(e -> audioService.stop()));
    hBox.setAlignment(Pos.CENTER);
    setCenter(new StackPane(hBox));
}

最后,在audio.mp3下放置src/ios/assets/audio.mp3之类的音频文件,构建并部署到iOS。

希望这个API将很快由Charm Down提供。此外,如果您想出一个很好的实现,请随意分享并创建Pull Request