- 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/
谁能详细说明以下问题? 蓝牙堆栈如何处理音频数据? 如何处理音频命令? 我们需要任何服务来处理音频数据吗? 提前致谢。 最佳答案 基本上,通过 BLE 的语音命令需要: 一些用于减少所需带宽的音频编解
我正在使用Player库以实现全屏视频播放。我相信它在幕后使用 AVFoundation。 我可以使用Float(self.player.maximumDuration)来实现视频的完整持续时间。但是
我正在制作一种宏记录器/播放器 我已经使用 java.awt.Robot() 等实用程序完成播放器部分,它模拟基本的人类鼠标/键盘输出命令,读取 XML 文件。 我卡在了必须记录该 XML 文件的部分
我目前有以下代码可以在页面上播放 youtube 视频。 //Load player api asynchronously. var tag = document.createElement('s
我需要提供音频内容(但不是音乐,更像是播客;人类语音),我正在考虑使用基于 Flash 的播放器让用户无需下载即可收听内容。 我需要一个免费的可嵌入 Flash 的 mp3 播放器。有什么建议? 因为
html5 player/api 更新了吗?事件 SC.Widget.Events.PLAY, SC.Widget.Events.PAUSE, SC.Widget.Events.FINISH, htm
我想在 Lubuntu VMware 中自动打开和关闭 vlc 播放器。我试过一个shell脚本代码,如: vlc rtmp://code sleep(5) exit 0 or vl
我有一个只支持纵向模式的应用程序,它有一个表格,每个单元格包含一个标题和一个带有 YouTube 视频的 web View 。 现在您将如何让 Youtube 播放器同时处于横向和纵向模式?
我正在尝试在我的应用程序中使用 YouTube 播放器 API,但我不知道如何确定视频是否为直播。如果有人知道如何获得视频的真实持续时间。 更新: 我想出了一种方法来确定内容是否是实时的,我使用我的后
我想创建一个能够播放 YouTube 视频的音频并将下载的内容保存在本地缓存中的应用程序,因此当用户决定恢复或再次播放视频时,它不必再次下载部分视频而只需下载剩余部分(用户可以决定如何处理缓存,以及如
我希望我的页面将 div 显示为模态,然后播放 YouTube 视频。我能够按预期播放视频(下面的代码),但是当我在过滤操作时切换到隐藏的 div 时,页面加载时隐藏的 div 不会将 data-sr
我正在尝试使用 AngularJS 和 WP API 构建 SPA。我使用部分在 ng-view 中加载我需要通过路由显示的所有内容。在此基础上,我添加了 Plangular,它是一个使用 Sound
我找到了一个不错的 HTML 5 音频播放器,它带有基于 plyr 的播放列表和艺术品。它在我的桌面浏览器上运行良好,但在我的移动设备 (iOS) 上,按播放后无法播放。有一个codepen来演示:
我正在尝试通过pyglet在Python 3中播放歌曲。我可以播放和停止播放一首歌曲,但是当我尝试播放下一首歌曲时会产生错误。 I followed these instructions.我将在tki
如何将嵌入的 Vimeo 视频重置为播放完毕后的加载状态? Vimeo API 提供了卸载方法 player.api("unload") 但它不适用于非 Flash 播放器。 最佳答案 使用Vimeo
我有一个用于音频录制和播放的网络应用程序。为此,我正在使用 html5 播放器。 现在我必须开发 Phonegap Android 应用程序。我已将插件(org.apache.cordova.medi
有人知道如何像 SuperFlix 一样将自己的字幕加载到 Netflix 播放器吗?关于 Netflix HTML5 播放器的信息很少,其中之一是我应该可以使用 操作播放器 netflix.cadm
如何将新的黑色 YouTube 播放器嵌入到我的网站(刚刚推出的网站)中? 我以前曾问过这个问题,但它已关闭,因为在投票否决和关闭之前没有人愿意真正阅读该问题。不,我没有问如何嵌入V2或V3播放器,我
几个小时以来,我一直在尝试添加一种打开我的 mp3 文件的方法并在队列中一一打开它们。但我不知道该怎么做。当涉及到单个文件时,我打开并播放不是问题。所以我正在考虑 Media(JavaFX) 类中的线
我知道这个函数 (setFullscreen) 只适用于 HTML5,但它对我不起作用。这是我使用的方式: setFullscreen: true 我希望 JW Player 在页面加载后立即以全屏模
我是一名优秀的程序员,十分优秀!