- 内容简介
- 译者序
- 前言
- 第 1 章 安装配置新项目
- 第 2 章 Flexbox 布局介绍
- 第 3 章 用 React Native 开发一个应用
- 第 4 章 在 React Native 中使用导航
- 第 5 章 动画和滑动菜单
- 第 6 章 用 React Native 绘制 Canvas
- 第 7 章 使用 React Native 播放音频
- 第 8 章 你的第一个自定义视图
- 第 9 章 Flux 介绍
- 第 10 章 处理复杂的应用程序状态
- 第 11 章 使用 Node 来实现服务端 API
- 第 12 章 在 React Native 中使用文件上传
- 第 13 章 理解 JavaScript Promise
- 第 14 章 fetch 简介
- 第 15 章 在 iOS 中使用 SQLite
- 第 16 章 集成 Google Admob
- 第 17 章 React Native 组件国际化
- 附录 A React.js 快速介绍
- 附录 B Objective-C Primer
- 附录 C webpack 入门
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
第 7 章 使用 React Native 播放音频
在这一章,我们将学习自定义的 React Native 组件。
有时一个应用程序需要访问平台 API, React Native 并没有相应的封装器。也许你想重用现有的一些 Objective-C 或 C++代码,而不想在 JavaScript 上重新实现;或者你可能想写一些高性能、多线程的代码,用于诸如图像处理、网络堆栈、数据库或渲染等高级扩展。
我们是可以编写真正的 native 代码,并且访问整个平台的。这涉及更高级的特性,虽然我们并不期望它成为通常开发过程中的一部分,但是它的存在是至关重要的。如果 React Native 对你需要的特性不是原生支持的,那么你应该能够自己构建它。
这是一个更高级的指南,展示了如何构建一个原生模块。前提是读者需要了解 Objective-C (或 Swift)和核心库(Foundation、UIKit)。
让我们开始使用下面的命令创建我们的自定义组件:
react-native new-library AudioPlayerManager
将生成的 AudioPlayerManager.xcproj 文件拖动到项目目录下的 Libraries 文件夹中来链接库。如果有任何疑问请参考第 1 章相关内容。
AudioPlayerManager.h
#import "RCTBridgeModule.h"
#import "RCTLog.h"
#import <AVFoundation/AVFoundation.h>
@interface AudioPlayerManager : NSObject <RCTBridgeModule,
AVAudioPlayerDelegate>
@end
AudioPlayerManager.m
//
// AudioPlayerManager.m
// AudioPlayerManager
//
// Created by Joshua Sierles on 15/04/15.
// Copyright (c) 2015 Joshua Sierles. All rights reserved.
//
#import "AudioPlayerManager.h"
#import "RCTConvert.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import <AVFoundation/AVFoundation.h>
NSString *const AudioPlayerEventProgress = @"playerProgress";
NSString *const AudioPlayerEventFinished = @"playerFinished";
@implementation AudioPlayerManager {
AVAudioPlayer *_audioPlayer;
NSTimeInterval _currentTime;
id _progressUpdateTimer;
int _progressUpdateInterval;
NSDate *_prevProgressUpdateTime;
NSURL *_audioFileURL;
}
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE();
- (void)sendProgressUpdate {
if (_audioPlayer && _audioPlayer.playing) {
_currentTime = _audioPlayer.currentTime;
}
NSString *time = [NSString stringWithFormat:@"%f", _currentTime];
if (_prevProgressUpdateTime == nil ||
(([_prevProgressUpdateTime timeIntervalSinceNow] * -1000.0) >=
_progressUpdateInterval)) {
[_bridge.eventDispatcher sendDeviceEventWithName:
AudioPlayerEventProgress body:@{
@"currentTime": [NSNumber numberWithFloat:_currentTime]
}];
_prevProgressUpdateTime = [NSDate date];
}
}
- (void)stopProgressTimer {
[_progressUpdateTimer invalidate];
}
- (void)startProgressTimer {
_progressUpdateInterval = 250;
_prevProgressUpdateTime = nil;
[self stopProgressTimer];
_progressUpdateTimer = [CADisplayLink displayLinkWithTarget:self
selector:@selector(sendProgressUpdate)];
[_progressUpdateTimer addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSDefaultRunLoopMode];
}
- (void)AudioPlayerDidFinishPlaying:(AVAudioPlayer *)recorder
successfully:(BOOL)flag {
NSLog(flag ? @"FINISHED OK" : @"FINISH ERROR");
[_bridge.eventDispatcher sendDeviceEventWithName:
AudioPlayerEventFinished body:@{
@"finished": @TRUE
}];
}
RCT_EXPORT_METHOD(play:(NSString *)path)
{
NSError *error;
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *audioFilePath = [resourcePath
stringByAppendingPathComponent:path];
_audioFileURL = [NSURL fileURLWithPath:audioFilePath];
NSLog([_audioFileURL absoluteString]);
_audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:_audioFileURL
error:&error];
if (error) {
[self stopProgressTimer];
NSLog(@"audio playback loading error: %@", [error
localizedDescription]);
// TODO: 通过接口分发错误
} else {
[self startProgressTimer];
[_audioPlayer play];
}
}
RCT_EXPORT_METHOD(playWithUrl:(NSURL *) url)
{
NSError *error;
NSData* data = [NSData dataWithContentsOfURL: url];
_audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:&
error];
if (error) {
[self stopProgressTimer];
NSLog(@"audio playback loading error: %@", [error
localizedDescription]);
// TODO: 通过接口分发错误
} else {
[self startProgressTimer];
[_audioPlayer play];
}
}
RCT_EXPORT_METHOD(pause)
{
if (_audioPlayer.playing) {
[_audioPlayer pause];
}
}
RCT_EXPORT_METHOD(stop)
{
if (_audioPlayer.playing) {
[_audioPlayer stop];
}
}
@end
audio_player.js
'use strict';
/**
* 这个模块是一个轻量的原生模块。它的作用是实现注册回调,更改设置等。
*/
var React = require('react-native');
var AudioPlayerManager = require('NativeModules').
AudioPlayerManager;
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var AudioPlayer = {
play: function(path) {
AudioPlayerManager.play(path);
},
pause: function() {
AudioPlayerManager.pause();
},
stop: function() {
AudioPlayerManager.stop();
if (this.subscription) {
this.subscription.remove();
}
}
};
module.exports = {AudioPlayer};
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论