相关文章:
《react-native 集成 FFmpeg 能力 - 使用 FFmpegKit(一)》
《react-native 集成 FFmpeg 能力 - 使用 FFmpegKit(三)》
这一篇主要记录对于 react-native 项目里,直接使用原生模块。
其实 react-native 能用起来,那就意味着原生的引入已经成功了。但是我以为和上一篇处理 react-native 库一样,在根目录的 ios 和 android 文件夹引入声明,相当于全局声明,自定义原生模块就可以直接使用了,但实际上不是,还需要在相应的自定义原生模块里再引入声明。
expo 项目有可以协助创建自定义原生模块的 create-expo-module。然后前提还是先把 ffmpegkit 的库下到本地来引入。
1. expo 项目 Android 引入
在 modules/native-module/android/build.gradle
加上:
dependencies {
// 1. 直接引入 AAR,位置合理放置就行
implementation files('libs/ffmpeg-kit-full-6.0-2.aar')
// 2. 添加传递依赖(必须)
implementation 'com.arthenica:smart-exception-java:0.2.1'
}
在代码里使用:
package expo.modules.settings
// 引入下面这三个
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.FFmpegSession
import com.arthenica.ffmpegkit.ReturnCode
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class ExpoSettingsModule : Module() {
override fun definition() = ModuleDefinition {
Name("ExpoSettings")
Function("getTheme") {
return@Function "system"
}
}
}
2. expo 项目 IOS 引入
在 modules/native-module/ios/NativeModule.podspec
加上:
Pod::Spec.new do |s|
s.name = 'NativeModule'
s.version = '1.0.0'
s.summary = ''
s.description = ''
s.author = ''
s.homepage = 'https://docs.expo.dev/modules/'
s.platforms = {
:ios => '15.1',
:tvos => '15.1'
}
s.source = { git: '' }
s.static_framework = true
s.dependency 'ExpoModulesCore'
# Swift/Objective-C compatibility
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
}
s.source_files = "src/**/*.{h,m,mm,swift,hpp,cpp}"
// 直接引入 xcframework, 位置合理放置就行
s.vendored_frameworks = 'libs/*.xcframework'
end
在代码里使用:
import ExpoModulesCore
// 加上这句引用
import ffmpegkit
public class ExpoSettingsModule: Module {
public func definition() -> ModuleDefinition {
Name("ExpoSettings")
Function("getTheme") { () -> String in
"system"
}
}
}
下面两个只是尝试,然后记录一下,实际上用的上面 expo 项目
3. react-native 项目 IOS 引入, 使用 swift 语法
本质上差别不大,只是没有 expo 的辅助,改回 react-native 要求的语法。
在 modules/native-module/src/NativeModule.ts
改成:
// expo 改成 react-native 的模块引入方式
import { NativeModules } from 'react-native';
export const NewVideoEditor = NativeModules.NewVideoEditorModule;
podspec
文件和 expo 项目一样就行。
新增 modules/new-module/ios/src/NativeModule.m
文件:
#import <React/RCTBridgeModule.h>
#import <FFmpegKit/FFmpegKit.h>
@interface RCT_EXTERN_MODULE(NewVideoEditorModule, NSObject)
// 同步方法 - getName
RCT_EXTERN_METHOD(getName)
// 异步方法 - getFFmpegVersion
RCT_EXTERN_METHOD(getFFmpegVersion:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
@end
新增 modules/new-module/ios/src/NativeModule.swift
文件:
import Foundation
import React
import ffmpegkit
@objc(NewVideoEditorModule)
class NewVideoEditorModule: NSObject, RCTBridgeModule {
// MARK: - RCTBridgeModule
static func moduleName() -> String! {
return "NewVideoEditorModule"
}
static func requiresMainQueueSetup() -> Bool {
return false
}
// MARK: - Exported Methods
// 导出同步方法 - 使用 @objc 标记,React Native 会自动发现
@objc
func getName() -> String {
return "NewVideoEditor-Name"
}
@objc
func getFFmpegVersion(_ resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock) {
let version = FFmpegKitConfig.getFFmpegVersion()
resolve(version)
}
}
上面的代码也是问 AI 问出来的,仅供参考,模块名和文件名需要按实际填写。这里的注意点还是原生 ios 的问题吧,据说 ios 提供给 react-native 的库是用 Objective-c 写的。所以在 react-native 里自定义原生 ios 模块里写 swift 也要包装成 Objective-c。
4. react-native 项目 IOS 引入, 使用 Objective-c 语法
参考 FFmpegKit 仓库 的写法就行,就是用 Objective-c 写的。
ios 的声明文件 podspec 文件和 ts 的导出文件 NativeModule.ts 和 swift 写法的一样就行。