2

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

4

1 回答 1

4

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

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

我的建议是克隆 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(就像这里的那个)和 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实现——Objective-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。这个基于本教程

#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

构建原生库

编辑build.gradleiOS 模块,并将音频服务添加到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

如果一切正常,您应该拥有:

  • common/build/libs/charm-down-common-2.1.0-SNAPSHOT.jar
  • 桌面/build/libs/charm-down-desktop-2.1.0-SNAPSHOT.jar
  • Android/build/libs/charm-down-android-2.1.0-SNAPSHOT.jar
  • IOS/build/libs/charm-down-ios-2.1.0-SNAPSHOT.jar
  • IOS/build/native/libCharm.a

胶子计划

使用这些依赖项和本机库,您将能够创建一个新的 Gluon 项目,并将 jars 添加为本地依赖项(到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'
}

在您的视图中,检索服务并提供一些基本 UI 来调用、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.mp3build 和 deploy 到 iOS。

希望这个 API 很快就会由 Charm Down 提供。此外,如果您提出了一个不错的实现,请随时分享并创建一个Pull Request

于 2016-07-30T14:20:44.497 回答