简体   繁体   English

Gluon移动iOS音频播放器

[英]Gluon Mobile iOS Audio Player

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

While on Android we can easily add native API to the Android folders of a Gluon project (check this solution for using native Media on Android), the use of native code (Objetive-C) with the Media API on iOS folders is not enough, since it has to be compiled, and the compiled files have to be included into the ipa. 在Android上,我们可以轻松地将原生API添加到Gluon项目的Android文件夹中(检查此解决方案是否在Android上使用本机媒体),在iOS文件夹上使用本机代码(Objetive-C)与Media API是不够的,因为它必须被编译,并且编译的文件必须包含在ipa中。

Currently, Charm Down is doing this for a bunch of services. 目前, Charm Down正在为一系列服务做这件事。 If you have a look at the build.gradle script for iOS , it includes the xcodebuild task to compile and build the native library libCharm.a , that later should be included in any iOS project using any of those services. 如果您查看iOSbuild.gradle脚本,它包含xcodebuild任务来编译和构建本机库libCharm.a ,以后应该包含在使用任何这些服务的任何iOS项目中。

My suggestion will be cloning Charm Down, and providing a new service: AudioService , with some basic methods like: 我的建议是克隆Charm Down,并提供一项新服务: AudioService ,其中包括一些基本方法:

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

This service will be added to the Platform class: 此服务将添加到Platform类:

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

and you should provide implementations for Desktop (empty), Android (like the one here ) and iOS. 你应该提供桌面(空),Android(像这里的那个)和iOS的实现。

IOS implementation - Java IOS实现 - Java

You will have to add this to the IOSPlatform class: 您必须将此添加到IOSPlatform类:

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

and create the IOSAudioService class: 并创建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();
    }
}

Finally, you will have to add the native calls in CharmApplication : 最后,您必须在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 IOS实施 - 目标-C

Now, on the native folder, on CharmApplication.m , add the implementation of those calls: 现在,在本机文件夹的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;   
}

and create the header file Audio.h : 并创建头文件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

and the implementation Audio.m . 和实现Audio.m This one is based on this 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 构建本机库

Edit the build.gradle for the iOS module, and add the Audio service to the xcodebuild task: 编辑iOS模块的build.gradle ,并将Audio服务添加到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 建立项目

Save the project, and from the root of the Charm Down project, on command line run: 保存项目,并从Charm Down项目的根目录,在命令行运行:

./gradlew clean build

If everything is fine, you should have: 如果一切都很好,你应该:

  • Common/build/libs/charm-down-common-2.1.0-SNAPSHOT.jar 通用/建设/库/魅下共2.1.0-SNAPSHOT.jar
  • Desktop/build/libs/charm-down-desktop-2.1.0-SNAPSHOT.jar 桌面/编译/库/魅力向下桌面-2.1.0-SNAPSHOT.jar
  • Android/build/libs/charm-down-android-2.1.0-SNAPSHOT.jar 安卓/编译/库/魅下的Android 2.1.0-SNAPSHOT.jar
  • IOS/build/libs/charm-down-ios-2.1.0-SNAPSHOT.jar IOS /编译/库/魅力向下-IOS-2.1.0-SNAPSHOT.jar
  • IOS/build/native/libCharm.a IOS /编译/本地/ libCharm.a

Gluon Project 胶子项目

With those dependencies and the native library, you will be able to create a new Gluon Project, and add the jars as local dependencies (to the libs folder). 使用这些依赖项和本机库,您将能够创建一个新的Gluon项目,并将jar作为本地依赖项添加到libs文件夹中。

As for the native library, it should be added to this path: src/ios/jniLibs/libCharm.a . 对于本机库,应将其添加到此路径: src/ios/jniLibs/libCharm.a

Update the build.gradle script: 更新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'
}

On your View, retrieve the service and provide some basic UI to call the play("audio.mp3") , pause() , resume() and stop() methods: 在View上,检索服务并提供一些基本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));
}

Finally, place an audio file like audio.mp3 , under src/ios/assets/audio.mp3 , build and deploy to iOS. 最后,在src/ios/assets/audio.mp3下放置audio.mp3等音频文件,构建并部署到iOS。

Hopefully, this API will be provided by Charm Down any time soon. 希望这个API将很快由Charm Down提供。 Also if you come up with a nice implementation, feel free to share it and create a Pull Request . 此外,如果您想出一个很好的实现,请随意共享它并创建一个Pull Request

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM