【问题标题】:Gluon Mobile iOS Audio PlayerGluon 移动 iOS 音频播放器
【发布时间】:2016-07-30 07:11:31
【问题描述】:

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

【问题讨论】:

    标签: javafx javafxports gluon gluon-mobile


    【解决方案1】:

    虽然在 Android 上,我们可以轻松地将原生 API 添加到 Gluon 项目的 Android 文件夹中(查看 solution 以在 Android 上使用原生媒体),在 iOS 上使用原生代码 (Objetive-C) 和媒体 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 实现 - 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。这个是基于这个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
    

    如果一切正常,你应该有:

    • 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 项目

    使用这些依赖项和本机库,您将能够创建一个新的 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.mp3 下,构建并部署到iOS。

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

    【讨论】:

    • 应用所有这些更改后,应用程序冻结了。日志有这个输出: 2016-07-30 12:32:50.769 GluonApp [3146:1115803] 播放音频 2016-07-30 12:32:50.770 GluonApp [3146:1115803] *** NSForwarding: 警告: object 0x1d34b64 of 'Audio' 类没有实现 methodSignatureForSelector: -- 麻烦提前 2016-07-30 12:32:50.770 GluonApp [3146:1115803] *** NSForwarding: 警告: 'Audio' 类的对象 0x1d34b64 没有实现 doesNotRecognizeSelector: --中止
    • 确保你已经按照每一步,有很多文件要修改。您是否成功构建了修改后的 Charm Down?您使用的是 iOS sdk 9.3 吗?
    • 我已经编辑了我的答案,但对Audio.m 进行了细微更改,删除了导入和不必要的view
    • 我可以想象,这一定很困难,但感谢您的巨大帮助! Gluon Mobile 和 javafxports 库非常有帮助,感谢您对它们所做的出色工作!
    • AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:&amp;error]; [session setActive:YES error:nil]; 如果在实例化 AVAudioPlayer 对象之前将此代码放在 Audio.m 中,即使按下设备上的硬件静音按钮,音频文件也会播放。
    猜你喜欢
    • 1970-01-01
    • 2014-11-21
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多