如何在React Native中集成并控制Android Kotlin视频播放器及原生Activity?
在React Native中集成并控制Kotlin编写的Android原生视频播放器Activity
下面是完整的实现步骤,涵盖从原生模块封装到JS层调用、双向控制的全流程:
1. 封装Kotlin原生模块
首先在Android项目的app/src/main/java/[你的包名]/modules下创建两个文件:
VideoPlayerModule.kt
这个模块负责处理React Native发来的指令,以及向JS层发送播放器状态:
import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap import com.facebook.react.modules.core.DeviceEventManagerModule import android.content.Intent class VideoPlayerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { private var playerActivity: VideoPlayerActivity? = null override fun getName(): String = "VideoPlayerModule" // 启动视频播放器Activity @ReactMethod fun startPlayerActivity(videoUrl: String) { val intent = Intent(reactApplicationContext, VideoPlayerActivity::class.java) intent.putExtra("VIDEO_URL", videoUrl) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) reactApplicationContext.startActivity(intent) } // 发送播放指令 @ReactMethod fun play() { playerActivity?.player?.play() } // 发送暂停指令 @ReactMethod fun pause() { playerActivity?.player?.pause() } // 跳转至指定进度(单位:毫秒) @ReactMethod fun seekTo(position: Long) { playerActivity?.player?.seekTo(position) } // 设置播放器Activity引用,用于直接控制 fun setPlayerActivity(activity: VideoPlayerActivity) { this.playerActivity = activity } // 向JS层发送播放器状态事件 fun sendPlayerEvent(eventName: String, data: ReadableMap?) { reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(eventName, data) } }
VideoPlayerPackage.kt
用于注册原生模块到React Native:
import com.facebook.react.ReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.uimanager.ViewManager import java.util.ArrayList class VideoPlayerPackage : ReactPackage { override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { val modules = ArrayList<NativeModule>() modules.add(VideoPlayerModule(reactContext)) return modules } override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { return emptyList() } }
2. 配置视频播放器Activity
假设你已经有一个用Kotlin开发的VideoPlayerActivity,需要做以下调整:
在AndroidManifest.xml中注册Activity
<activity android:name=".VideoPlayerActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
修改VideoPlayerActivity.kt,添加与RN模块的交互
在Activity的生命周期方法中绑定模块,并在播放器状态变化时发送事件:
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.facebook.react.bridge.Arguments import com.yourpackage.modules.VideoPlayerModule class VideoPlayerActivity : AppCompatActivity() { lateinit var player: YourVideoPlayer // 替换成你的Kotlin播放器实例 private lateinit var videoPlayerModule: VideoPlayerModule override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_video_player) // 获取RN模块引用 videoPlayerModule = reactApplicationContext.getNativeModule(VideoPlayerModule::class.java) videoPlayerModule.setPlayerActivity(this) // 初始化播放器并设置监听 val videoUrl = intent.getStringExtra("VIDEO_URL") player = YourVideoPlayer(videoUrl) player.setOnPlaybackListener(object : PlaybackListener { override fun onPlay() { val event = Arguments.createMap() event.putString("status", "playing") videoPlayerModule.sendPlayerEvent("onPlayerStatusChange", event) } override fun onPause() { val event = Arguments.createMap() event.putString("status", "paused") videoPlayerModule.sendPlayerEvent("onPlayerStatusChange", event) } override fun onProgressUpdate(currentPosition: Long, duration: Long) { val event = Arguments.createMap() event.putDouble("currentPosition", currentPosition.toDouble()) event.putDouble("duration", duration.toDouble()) videoPlayerModule.sendPlayerEvent("onPlayerProgress", event) } }) } override fun onDestroy() { super.onDestroy() player.release() // 释放播放器资源 videoPlayerModule.setPlayerActivity(null) } }
3. 在React Native JS层调用与监听
封装播放器工具类(VideoPlayer.js)
import { NativeModules, NativeEventEmitter } from 'react-native'; const { VideoPlayerModule } = NativeModules; const videoPlayerEmitter = new NativeEventEmitter(VideoPlayerModule); export const VideoPlayer = { // 启动原生播放器 start: (videoUrl) => { VideoPlayerModule.startPlayerActivity(videoUrl); }, // 播放 play: () => { VideoPlayerModule.play(); }, // 暂停 pause: () => { VideoPlayerModule.pause(); }, // 跳转进度 seekTo: (position) => { VideoPlayerModule.seekTo(position); }, // 监听播放器状态 addStatusListener: (callback) => { return videoPlayerEmitter.addListener('onPlayerStatusChange', callback); }, // 监听播放进度 addProgressListener: (callback) => { return videoPlayerEmitter.addListener('onPlayerProgress', callback); } };
在组件中使用
import React, { useEffect } from 'react'; import { View, Button, Text } from 'react-native'; import { VideoPlayer } from './VideoPlayer'; const App = () => { let statusListener = null; let progressListener = null; useEffect(() => { // 注册监听 statusListener = VideoPlayer.addStatusListener((event) => { console.log('播放器状态:', event.status); }); progressListener = VideoPlayer.addProgressListener((event) => { console.log('当前进度:', event.currentPosition, '总时长:', event.duration); }); // 组件卸载时移除监听 return () => { statusListener?.remove(); progressListener?.remove(); }; }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开播放器" onPress={() => VideoPlayer.start('https://your-video-url.mp4')} /> <Button title="播放" onPress={() => VideoPlayer.play()} style={{ marginTop: 10 }} /> <Button title="暂停" onPress={() => VideoPlayer.pause()} style={{ marginTop: 10 }} /> <Button title="跳转到10秒" onPress={() => VideoPlayer.seekTo(10000)} style={{ marginTop: 10 }} /> </View> ); }; export default App;
关键注意事项
- 确保React Native与原生模块的包名一致,避免注册失败
- 播放器资源释放必须在Activity的
onDestroy中执行,防止内存泄漏 - 事件监听在组件卸载时一定要移除,避免内存泄漏
- 如果需要传递复杂数据,可使用
ReadableMap/WritableMap进行序列化
内容的提问来源于stack exchange,提问作者Hamid khan
相关产品推荐
相关产品推荐

