- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
由于 JavaFx Media 尚未移植到移动平台,任何人都可以帮助我使用 native iOS APi 来播放声音 mp3 文件,该文件将存储在我的 gluon 项目的 main/resources 文件夹中。
最佳答案
在 Android 上,我们可以轻松地将 native API 添加到 Gluon 项目的 Android 文件夹中(查看此 solution 以在 Android 上使用 native 媒体),在 iOS 上使用 native 代码 (Objetive-C) 和 Media API文件夹还不够,因为它必须编译,并且编译后的文件必须包含到 ipa 中。
目前,Charm Down正在为一系列服务这样做。如果您查看 iOS 的 build.gradle
脚本,它包括用于编译和构建 native 库 libCharm.a
的 xcodebuild
任务,稍后应将其包含在使用任何这些服务的任何 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
中添加 native 调用:
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
现在,在 native 文件夹的 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
如果一切正常,您应该:
Gluon 项目
有了这些依赖项和 native 库,您将能够创建一个新的 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'
}
在您的 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));
}
最后,在 src/ios/assets/audio.mp3
下放置一个音频文件,如 audio.mp3
,构建并部署到 iOS。
希望 Charm Down 能够尽快提供此 API。另外,如果您想出了一个很好的实现,请随时分享并创建一个 Pull Request .
关于javafx - Gluon 移动 iOS 音频播放器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38671355/
我有一个自定义的ListCell实现,如下图所示。 左边,代表日期,由3个标签组成,放入一个VBox和由计数器组成的“CounterContent”,每个标签有一个TextField数字,包含在一个
我是 Gluon 领域的新手,但我知道如何创建基于 JDK-8 的 JavaFX 应用程序,其中嵌入了 JavaFX 库。 看来Gluon应用程序可以在 JVM 上轻松执行,但要创建 native 镜
我想使用 PositionService iOS 上的 Gluon Mobile。我编写了一个在桌面上运行的小型示例应用程序,提供(按预期)虚假的位置更改,并在 Android 上运行。但是,在 iO
我正在尝试通过将特定于平台/操作系统的代码放在它们各自的文件夹中来设置我的 Gluon 项目(在新创建的 Gluon 项目中设置的自动创建的项目)。但是,无论我使用 Gradle 执行什么任务,它最终
我使用带有 OS X El Capitan 和 Eclipse IDE 的 mac 当我创建项目“Gluon Mobile - Single View Project”时,我无法针对 Android
只是一个简单的问题。我制作了一个 JavaFX 应用程序,我想让它在 Android 上运行。到目前为止,我发现实现此功能的唯一方法是使用 Gluon Mobile (JavaFXPorts)。但是,
我正在使用 Gluon 并有一个音频播放器。当我调用音频并播放时,一切正常,直到我按下主页按钮。我想让它做的是停止音乐,不再像现在这样继续播放。目前我已经尝试使用事件监听器来捕获事件并停止音乐但它没有
嗨,我一直在尝试对我的 javafx 项目进行 native 构建,但当我尝试运行它时出现异常。我怀疑在编译的二进制文件中找不到 .fxml 文件 Exception in thread "main"
我有一个在 Android 中运行的消息应用程序,其设置类似于 setup of the screen 顺序如下 //issue is here
我正在使用GluonMobile开发一个Android应用程序。对于一项功能,我需要一个ExoPlayer。 因此,我包括了com.google.android.exoplayer:exoplayer
我一直在关注有关该主题的各种问题的各种答案,并且得出了一个结果和一些看起来可行的代码。我被它的 NSURL 部分卡住了。我的 iOS gluon 项目的 assets 文件夹中有 2 个 mp3 轨道
我计划获取手机的 IMEI,以便在我的应用程序中生成二维码或条形码。我在提问之前已经检查过问题。此外,我还查看了 gluon mobile 文档以获取更多详细信息。但它似乎没有解决我的问题。 ispr
我是一名学生,目前正在学习并致力于使用 JavaFX(gluon 移动应用程序)开发移动应用程序。我能够构建独特的应用程序。但是,我想知道是否有任何可能的方法可以在 gluon 移动应用程序中打开网页
我的自定义 jar 文件应该添加到我的 Gluon 项目的类路径中,但我在 Netbeans 中找不到任何允许您添加自定义 jar 的工具。有人可以指导我如何做吗? 构建.gradle buildsc
假设您要使用用 Gluon JavaFX 制作的应用程序打开图片或文件。是否有任何文件导航窗口可用于选择该文件或图片? 假设我们知道我们的localRoot =/root File localRoot
我正在尝试使用 JDBC 编写一个简单的 mysql 连接代码到我在 OSX 上的 LAN 上的 mysql 服务器。 我有,– IntelliJ 15 CE– 安装了 Gluon 插件 1.0.1。
我想将一个字符串从 TextArea 保存到设备,然后在重新打开应用程序后重新加载它。我尝试按照示例 ( link ) 进行操作,但无法正常工作。当我尝试读取文件并使用 StringInputConv
我想生成必须将 Logo 放在中心的 QR CODE。我检查了 zxing 库,并通过阅读这段代码 ( How to generate QR code with logo inside it? ) 使
您好,我正在使用应用程序加载器将我的应用程序加载到 TestFlight 中,但我不断收到 3 个错误,我不知道如何处理它们。 Error ITMS-90096 Your binary is not
我有一个自定义控件 ChoiceTextField,具有相应的 ChoiceTextFieldSkin。 protected Skin createDefaultSkin() { re
我是一名优秀的程序员,十分优秀!