问题描述
项目中要做视频播放,接入阿里云的 flutter_aliplayer后模拟器跑不起来
bash
Error (Xcode): Undefined symbol: _OBJC_CLASS_$_AVPFilter
Error (Xcode): Undefined symbol: _OBJC_CLASS_$_AVPFilterConfig
Error (Xcode): Undefined symbol: _OBJC_CLASS_$_AVPFilterOptions
Error (Xcode): Undefined symbol: _OBJC_CLASS_$_AVPPreloadTask
Error (Xcode): Undefined symbol: _OBJC_CLASS_$_AliMediaLoaderV2
问题原因
AliPlayer SDK 的 AliyunPlayer.framework 在 iOS 模拟器架构(x86_64/arm64-simulator)中缺少以下符号的实现:
-
AVPFilter、AVPFilterConfig、AVPFilterOptions- 视频滤镜相关类 -
AVPPreloadTask、AliMediaLoaderV2- 预加载功能相关类
这些符号在真机架构(arm64)中存在,但在模拟器架构中缺失,导致链接失败。
解决方案
通过在 flutter_aliplayer 插件中添加条件编译,在模拟器上使用存根实现,在真机上使用完整实现。
核心思路
-
条件编译 :使用
#if TARGET_OS_SIMULATOR区分模拟器和真机 -
存根实现:在模拟器上提供最小化实现,返回明确的错误提示
-
完整实现:在真机上使用完整的 AliPlayer SDK 功能
-
依赖管理 :通过
dependency_overrides使用修改后的本地版本
实现细节
1. 修改 FlutterAliMediaLoaderV2.m
为预加载 v2 功能添加模拟器存根:
objective-c
#import "FlutterAliMediaLoaderV2.h"
#import <TargetConditionals.h>
#if TARGET_OS_SIMULATOR
// 模拟器版本:返回错误,不调用任何 AliPlayer API
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
result([FlutterError errorWithCode:@"AliPlayerPreloadV2Unavailable"
message:@"AliPlayer preload v2 is not available on the iOS Simulator."
details:nil]);
}
#else
// 真机版本:正常实现
// ... 原有完整实现 ...
#endif
2. 修改 AliPlayerFactory.m
为滤镜功能添加模拟器保护:
objective-c
- (void)setFilterConfig:(NSArray *)arr {
FlutterResult result = arr[1];
#if TARGET_OS_SIMULATOR
result([FlutterError errorWithCode:@"AliPlayerFilterUnavailable"
message:@"Video filter effects are not available on the iOS Simulator."
details:nil]);
return;
#else
// 真机版本:正常实现滤镜功能
// ... 原有完整实现 ...
#endif
}
- (void)updateFilterConfig:(NSArray *)arr {
FlutterResult result = arr[1];
#if TARGET_OS_SIMULATOR
result([FlutterError errorWithCode:@"AliPlayerFilterUnavailable"
message:@"Video filter effects are not available on the iOS Simulator."
details:nil]);
return;
#else
// 真机版本:正常实现
// ... 原有完整实现 ...
#endif
}
修改完毕后,就可以愉快的用模拟器开发啦。个人开发直接放在本地,使用模拟器开发的时候引用本地flutter_aliplayer包,真机上线时使用阿里云的正式包。团队开发时最好把修改后的代码上传到自己公司的git,然后配置打包脚本。
项目配置
1. 使用 Git 仓库版本
在 pubspec.yaml 中配置 dependency_overrides:
yaml
dependency_overrides:
flutter_aliplayer:
git:
url: 自己的.git
2. 构建脚本自动切换
build.sh 脚本会在不同场景自动切换依赖源:
-
注释掉 git 配置,使用 pub.dev 原始版本
-
取消注释 git 配置,使用包含模拟器修复的版本
bash
# 注释掉 flutter_aliplayer git 配置,使用 pub.dev 版本
comment_flutter_aliplayer_override
# 恢复 flutter_aliplayer git 配置,使用 git 版本(包含模拟器修复)
uncomment_flutter_aliplayer_override
模拟器上的限制
在 iOS 模拟器上,视频播放的功能不可用,修改只是为了开发中方便使用iOS模拟器。
符号检查
可以通过以下命令检查框架中的符号:
bash
# 检查所有架构
lipo -info ios/Pods/AliPlayerSDK_iOS/AliyunPlayer.framework/AliyunPlayer
# 检查 x86_64 架构中的符号
lipo ios/Pods/AliPlayerSDK_iOS/AliyunPlayer.framework/AliyunPlayer -thin x86_64 -output /tmp/AliyunPlayer_x86_64
nm -gU /tmp/AliyunPlayer_x86_64 | grep AVPFilter
依赖管理
-
开发环境:使用 git 仓库版本(包含模拟器修复)
-
生产环境:使用 pub.dev 原始版本(避免本地修改影响生产构建)
未来改进
如果哪天AliPlayer SDK官方提供了包含完整模拟器支持的版本,那最好不过。
相关文件
-
plugins/flutter_aliplayer/ios/Classes/FlutterAliMediaLoaderV2.m- 预加载 v2 实现 -
plugins/flutter_aliplayer/ios/Classes/AliPlayerFactory.m- 播放器工厂实现 -
pubspec.yaml- 依赖配置 -
build.sh- 构建脚本