react native 实现surfaceview播放视频

来源:互联网 发布:win7没有网络连接图标 编辑:程序博客网 时间:2024/06/06 02:58

本文在react native的js页面中调用android层写的surfaceview播放视频


1.我们搭建好rn环境后,创建rn项目并运行到设备上(本文省略),在项目的目录下 /android/app/src/main/java/com/项目名/ 下自定义一个surfaceview(mediaplayer也在其中)

package com.untitled;import android.content.Context;import android.media.MediaPlayer;import android.net.Uri;import android.view.SurfaceHolder;import android.view.SurfaceView;import java.io.IOException;/** * Created by zjh on 17-7-20. */public class MyPlay extends SurfaceView implements SurfaceHolder.Callback{    private MediaPlayer player = new MediaPlayer();    String uri="http://192.168.1.110:8080/background.mp4";//这是本人以本机搭的服务器,请务必换个url来测试    SurfaceHolder holder;    public MyPlay(Context context) {        super(context);        try {            player.setDataSource(context, Uri.parse(uri));            holder=this.getHolder();            holder.addCallback(this);            player.prepare();            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {                @Override                public void onPrepared(MediaPlayer mp) {                    player.start();                    player.setLooping(true);                }            });        } catch (IOException e) {            e.printStackTrace();        }    }    public void vRestart(){        player.start();    }    public void vPause(){        player.pause();    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        player.setDisplay(holder);    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {    }}

2.在android/app/src/main/java/com/项目名/ 下新建一个ReactVideo类,继承SimpleViewManager泛型为自己自定义的MyPlay

package com.untitled;import com.facebook.react.bridge.ReadableArray;import com.facebook.react.common.MapBuilder;import com.facebook.react.uimanager.SimpleViewManager;import com.facebook.react.uimanager.ThemedReactContext;import java.util.Map;import javax.annotation.Nullable;public class ReactVideo extends SimpleViewManager<MyPlay> {    private static final int COMMAND_PAUSE_ID = 1;    private static final String COMMAND_PAUSE_NAME = "pause";    private static final int COMMAND_START_ID = 2;    private static final String COMMAND_START_NAME = "start";    @Override    public String getName() {        return "RV";    }    @Override    protected MyPlay createViewInstance(ThemedReactContext reactContext) {        MyPlay view = new MyPlay(reactContext);        return view;    }    @Nullable    @Override    public Map<String, Integer> getCommandsMap() {        return MapBuilder.of(                COMMAND_PAUSE_NAME,COMMAND_PAUSE_ID,                COMMAND_START_NAME,COMMAND_START_ID        );    }    @Override    public void receiveCommand(MyPlay root, int commandId, @Nullable ReadableArray args) {        switch (commandId){            case COMMAND_PAUSE_ID:                root.vPause();                break;            case COMMAND_START_ID:                root.vRestart();                break;            default:                break;        }    }}

3.在android/app/src/main/java/com/项目名/ 下新建一个package类,继承reactapplication,在其中实现createViewManagers方法,并将上一步的ReactVideo添加到集合中(注:0.47.0已经没有了createJSModules(),下面重写的方法如果没有返回值不要直接return null;会报错,用return Collections.emptyList();)

package com.untitled;import com.facebook.react.ReactPackage;import com.facebook.react.bridge.JavaScriptModule;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.List;public class MyPackage implements ReactPackage {    @Override    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {        return Collections.emptyList();    }    @Override    public List<Class<? extends JavaScriptModule>> createJSModules() {        return Collections.emptyList();    }    @Override    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {        return Arrays.<ViewManager>asList(                new ReactVideo()        );    }}

4.在创建项目就有的android/app/src/main/java/com/项目名/mianapplication中的getpackages创建上步的package实例

package com.untitled;import android.app.Application;import com.facebook.react.ReactApplication;import com.facebook.react.ReactNativeHost;import com.facebook.react.ReactPackage;import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;import java.util.Arrays;import java.util.List;public class MainApplication extends Application implements ReactApplication {  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {    @Override    public boolean getUseDeveloperSupport() {      return BuildConfig.DEBUG;    }    @Override    protected List<ReactPackage> getPackages() {      return Arrays.<ReactPackage>asList(          new MainReactPackage(),          new MyPackage()//这里!!!      );    }  };  @Override  public ReactNativeHost getReactNativeHost() {    return mReactNativeHost;  }  @Override  public void onCreate() {    super.onCreate();    SoLoader.init(this, /* native exopackage */ false);  }}

5.在项目根目录下创建Vv.js

'use strict';import React,{ Component,PropTypes }from 'react';import {    requireNativeComponent,    View,    UIManager,    findNodeHandle,}from 'react-native';var RCT_VIDEO_REF = 'VideoView';class VideoView extends Component {    constructor(props) {        super(props);    }    pause(){        UIManager.dispatchViewManagerCommand(            findNodeHandle(this.refs[RCT_VIDEO_REF]),            UIManager.RV.Commands.pause,            null        );    }    start(){        UIManager.dispatchViewManagerCommand(            findNodeHandle(this.refs[RCT_VIDEO_REF]),            UIManager.RV.Commands.start,            null        );    }    render(){        return <RCTVideoView            {...this.props}            ref = {RCT_VIDEO_REF}        />;    };}VideoView.propTypes = {    style: View.propTypes.style,    ...View.propTypes,};var RCTVideoView = requireNativeComponent('RV',VideoView,{    nativeOnly: {onChange: true}});module.exports = VideoView;

6.最后在js代码中调用就可以,在创建项目就有的项目根目录下android的js入口文件,index.android.js中添加

import React, { Component } from 'react';import {  AppRegistry,  StyleSheet,  Text,  View,  NativeModules,    processColor,    TouchableOpacity} from 'react-native';import VideoView from './Vv';export default class untitled extends Component {    onPressPause(){        this.video.pause();    }    onPressStart(){        this.video.start();    }    render() {    return (      <View style={styles.container}>        <VideoView            style={{height:450,width:580}}            ref={(video)=>{this.video = video}}           // seturl='http://192.168.1.110:8080/background.mp4'        />        <View style={{height:50,flexDirection:'row',justifyContent:'flex-start'}}>          <TouchableOpacity style={{marginLeft:10}} onPress={this.onPressPause.bind(this)}>            <Text>暂停</Text>          </TouchableOpacity>          <TouchableOpacity style={{marginLeft:10}} onPress={this.onPressStart.bind(this)}>            <Text>开始</Text>          </TouchableOpacity>        </View>      </View>    );  }}const styles = StyleSheet.create({  container: {    flex: 1,    justifyContent: 'center',    alignItems: 'center',    backgroundColor: '#F5FCFF',  },  welcome: {    fontSize: 20,    textAlign: 'center',    margin: 10,  },  instructions: {    textAlign: 'center',    color: '#333333',    marginBottom: 5,  },});AppRegistry.registerComponent('untitled', () => untitled);

这样一个简单的播放器就完成了
本文参考:https://github.com/helengray/XiFan(稀饭的项目功能更加强大,不过用的是VideoView实现)