| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- ---
- description: 原生模块集成指南
- globs: ["**/cpp/**/*", "**/napi/**/*", "**/ijkplayer/**/*", "**/lib/**/*"]
- alwaysApply: false
- ---
- # 原生模块集成指南
- ## ijkplayer播放器集成
- ### 基本使用
- ```typescript
- import { IjkMediaPlayer } from '@ohos/ijkplayer';
- // 创建播放器实例
- private player: IjkMediaPlayer = new IjkMediaPlayer();
- // 设置数据源
- async setDataSource(path: string) {
- try {
- await this.player.setDataSource(path);
- await this.player.prepare();
- } catch (err: Error) {
- Logger.error(`设置数据源失败: ${err.message}`);
- }
- }
- ```
- ### 播放控制
- ```typescript
- // 播放
- async play() {
- try {
- await this.player.start();
- this.playStatus = PlayStatus.PLAY;
- } catch (err: Error) {
- Logger.error(`播放失败: ${err.message}`);
- }
- }
- // 暂停
- async pause() {
- try {
- await this.player.pause();
- this.playStatus = PlayStatus.PAUSE;
- } catch (err: Error) {
- Logger.error(`暂停失败: ${err.message}`);
- }
- }
- // 停止
- async stop() {
- try {
- await this.player.stop();
- this.playStatus = PlayStatus.STOP;
- } catch (err: Error) {
- Logger.error(`停止失败: ${err.message}`);
- }
- }
- ```
- ### 播放状态监听
- ```typescript
- // 设置播放状态监听器
- setupPlayerListener() {
- this.player.on('stateChange', (state: string) => {
- switch (state) {
- case 'prepared':
- // 准备完成
- break;
- case 'playing':
- this.playStatus = PlayStatus.PLAY;
- break;
- case 'paused':
- this.playStatus = PlayStatus.PAUSE;
- break;
- case 'completed':
- this.playStatus = PlayStatus.DONE;
- this.playNext(); // 播放下一首
- break;
- case 'error':
- this.handlePlaybackError(new Error('播放器错误'));
- break;
- }
- });
- this.player.on('timeUpdate', (currentTime: number, duration: number) => {
- this.currentTime = currentTime;
- this.duration = duration;
- this.updateProgress();
- });
- }
- ```
- ### 音频焦点处理
- ```typescript
- import { avSession } from '@kit.ArkAVSessionKit';
- // 请求音频焦点
- async requestAudioFocus() {
- try {
- const audioSession = await avSession.createAVSession(getContext(this), 'audio', 'music');
- await audioSession.activate();
- this.audioSession = audioSession;
- } catch (err: Error) {
- Logger.error(`获取音频焦点失败: ${err.message}`);
- }
- }
- // 释放音频焦点
- async releaseAudioFocus() {
- if (this.audioSession) {
- try {
- await this.audioSession.deactivate();
- await this.audioSession.destroy();
- this.audioSession = null;
- } catch (err: Error) {
- Logger.error(`释放音频焦点失败: ${err.message}`);
- }
- }
- }
- ```
- ## 歌词库集成
- ### LyricHelper使用
- ```typescript
- import { LyricHelper } from '@lib/LyricHelper';
- // 解析歌词文件
- async parseLyricFile(filePath: string): Promise<LyricLine[]> {
- try {
- const lyrics = await LyricHelper.parseLyricFile(filePath);
- return lyrics;
- } catch (err: Error) {
- Logger.error(`解析歌词文件失败: ${err.message}`);
- return [];
- }
- }
- // 解析歌词文本
- parseLyricText(lyricText: string): LyricLine[] {
- try {
- return LyricHelper.parseLyricText(lyricText);
- } catch (err: Error) {
- Logger.error(`解析歌词文本失败: ${err.message}`);
- return [];
- }
- }
- ```
- ### 歌词同步
- ```typescript
- // 获取当前时间对应的歌词行
- getCurrentLyric(currentTime: number): LyricLine | null {
- if (!this.lyrics || this.lyrics.length === 0) {
- return null;
- }
- for (let i = 0; i < this.lyrics.length; i++) {
- if (this.lyrics[i].time > currentTime) {
- return i > 0 ? this.lyrics[i - 1] : null;
- }
- }
- return this.lyrics[this.lyrics.length - 1];
- }
- // 获取下一句歌词
- getNextLyric(currentTime: number): LyricLine | null {
- if (!this.lyrics || this.lyrics.length === 0) {
- return null;
- }
- for (let i = 0; i < this.lyrics.length; i++) {
- if (this.lyrics[i].time > currentTime) {
- return this.lyrics[i];
- }
- }
- return null;
- }
- ```
- ## NAPI开发指南
- ### 基本NAPI模块结构
- ```cpp
- // napi_init.cpp
- #include "napi/native_api.h"
- static napi_value Init(napi_env env, napi_value exports) {
- // 导出函数
- napi_property_descriptor desc[] = {
- {"createPlayer", nullptr, CreatePlayer, nullptr, nullptr, nullptr, napi_default, nullptr},
- {"destroyPlayer", nullptr, DestroyPlayer, nullptr, nullptr, nullptr, napi_default, nullptr},
- };
-
- napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
- return exports;
- }
- static napi_module demoModule = {
- .nm_version = 1,
- .nm_flags = 0,
- .nm_filename = nullptr,
- .nm_register_func = Init,
- .nm_modname = "entry",
- .nm_priv = ((void*)0),
- .reserved = {0},
- };
- extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {
- napi_module_register(&demoModule);
- }
- ```
- ### 异步操作处理
- ```cpp
- // 异步操作结构体
- struct AsyncData {
- napi_async_work work;
- napi_deferred deferred;
- napi_ref callback;
- std::string result;
- std::string error;
- };
- // 异步执行函数
- static void ExecuteCallback(napi_env env, void* data) {
- AsyncData* asyncData = (AsyncData*)data;
-
- try {
- // 执行耗时操作
- asyncData->result = performOperation();
- } catch (const std::exception& e) {
- asyncData->error = e.what();
- }
- }
- // 完成回调函数
- static void CompleteCallback(napi_env env, napi_status status, void* data) {
- AsyncData* asyncData = (AsyncData*)data;
-
- napi_value callback;
- napi_get_reference_value(env, asyncData->callback, &callback);
-
- napi_value result;
- if (asyncData->error.empty()) {
- napi_create_string_utf8(env, asyncData->result.c_str(), NAPI_AUTO_LENGTH, &result);
- napi_call_function(env, nullptr, callback, 1, &result, nullptr);
- } else {
- napi_value error;
- napi_create_string_utf8(env, asyncData->error.c_str(), NAPI_AUTO_LENGTH, &error);
- napi_call_function(env, nullptr, callback, 1, &error, nullptr);
- }
-
- // 清理资源
- napi_delete_async_work(env, asyncData->work);
- napi_delete_reference(env, asyncData->callback);
- delete asyncData;
- }
- ```
- ## 性能优化建议
- ### 播放器优化
- 1. 使用对象池管理播放器实例,避免频繁创建和销毁
- 2. 预加载下一首歌曲,减少切换歌曲时的延迟
- 3. 使用硬件解码加速,降低CPU占用
- 4. 合理设置缓冲区大小,平衡播放流畅度和内存占用
- ### 内存管理
- 1. 及时释放不再使用的资源,如播放器实例、音频会话等
- 2. 使用弱引用避免循环引用导致的内存泄漏
- 3. 监控内存使用情况,及时处理内存警告
- ### 线程管理
- 1. 将耗时操作放在工作线程中执行,避免阻塞UI线程
- 2. 使用线程池管理并发任务,避免创建过多线程
- 3. 合理使用同步机制,避免死锁和竞态条件
- ## 错误处理
- ### 播放器错误处理
- ```typescript
- // 播放器错误处理
- handlePlayerError(error: Error) {
- Logger.error(`播放器错误: ${error.message}`);
-
- // 根据错误类型采取不同处理策略
- if (error.message.includes('网络')) {
- // 网络错误,尝试重试或使用本地缓存
- this.retryWithCache();
- } else if (error.message.includes('解码')) {
- // 解码错误,尝试使用备用解码器
- this.switchToBackupDecoder();
- } else {
- // 其他错误,显示错误提示并停止播放
- this.showErrorMessage(error.message);
- this.stop();
- }
- }
- ```
- ### NAPI错误处理
- ```cpp
- // NAPI错误处理
- static napi_value SomeFunction(napi_env env, napi_callback_info info) {
- size_t argc = 1;
- napi_value args[1];
- napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
-
- if (status != napi_ok || argc < 1) {
- napi_throw_error(env, nullptr, "Invalid arguments");
- return nullptr;
- }
-
- // 参数验证
- bool isString;
- napi_is_string(env, args[0], &isString);
- if (!isString) {
- napi_throw_type_error(env, nullptr, "Expected string");
- return nullptr;
- }
-
- // 执行操作...
-
- return result;
- }
- ```
|