- 内容简介
- 译者序
- 前言
- 第 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};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论