首页 文章

Gluon移动iOS音频播放器

提问于
浏览
3

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

1 回答

  • 3

    在Android上,我们可以轻松地将原生API添加到Gluon项目的Android文件夹中(在Android上使用本机媒体检查这个solution),在iOS文件夹上使用本机代码(Objetive-C)与Media API是不够的,因为它必须被编译,并且编译的文件必须包含在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 implementation - 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 implementation - 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 . 这个是基于这个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
    

    Build the native library

    编辑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"]
    

    Build the project

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

    ./gradlew clean build
    

    如果一切都很好,你应该:

    • Common / build / libs / charm-down-common-2.1.0-SNAPSHOT.jar

    • Desktop / 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 Project

    使用这些依赖项和本机库,您将能够创建一个新的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'
    }
    

    在您的视图上,检索服务并提供一些基本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.mp3 下,构建并部署到iOS .

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

相关问题