我想创建android组件,在这个组件中我有视频播放器,使用MediaPlayer和SurfaceTexture。当我在示例应用程序中尝试compoent时,它工作正常。但是,当我试图按下主页按钮(Android设备中的圆形按钮),然后从历史记录关闭运行应用程序再次打开应用程序(按下按钮任务/菜单,然后单击应用程序),媒体播放器未正常调用。但如果我再次单击应用程序图标,则媒体播放器正常工有谁知道会发生什么?
我尝试记录,当我从后台应用程序恢复它时,它说
04-09 17:42:13.160 330-22013/? E/MediaPlayerService: setVideoSurfaceTexture failed: -19
04-09 17:44:49.944 453-453/com.videofiltertest E/MediaPlayer: pause called in state 0
04-09 17:44:49.945 453-453/com.videofiltertest E/MediaPlayer: error (-38, 0)
感谢。
这是我的原生组件代码。
public class VideoPlayer extends TextureView implements TextureView.SurfaceTextureListener, LifecycleEventListener, MediaPlayer.OnPreparedListener{
private static final String TAG = VideoThumbnail.class.getSimpleName();
public MediaPlayer mMediaPlayer;
public VideoTextureRenderer mRenderer;
private int surfaceWidth;
private int surfaceHeight;
private ThemedReactContext mContext;
private String videoPath;
private String fragmentShaderCode = null;
private boolean isCrop = false;
private boolean isAutoPlay = false;
private boolean isLooping = false;
private boolean mediaPlayerReady = false;
private boolean isTextureAvailable = false;
private SurfaceTexture surfaceTexture;
private SurfaceTexture surface = null;
private int xpos;
private int seekto = 0;
private boolean isPaused = false;
private boolean isCreated = false;
private boolean mediaPlayerPrepared = false;
public VideoPlayer(ThemedReactContext context) {
super(context);
mContext = context;
mContext.addLifecycleEventListener(this);
this.setSurfaceTextureListener(this);
}
public VideoPlayer(ThemedReactContext context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mContext.addLifecycleEventListener(this);
this.setSurfaceTextureListener(this);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
surfaceHeight = View.MeasureSpec.getSize(heightMeasureSpec);
surfaceWidth = View.MeasureSpec.getSize(widthMeasureSpec);
this.setMeasuredDimension(surfaceWidth, surfaceWidth);
}
private void getSurface(){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (surface != null) {
try {
mMediaPlayer.setDataSource(videoPath);
mMediaPlayer.prepare();
isCreated = true;
} catch (IOException e) {
Log.e("DEBUG", e.toString());
throw new RuntimeException("Could not open input video!");
}
} else {
surface = mRenderer.getVideoTexture();
getSurface();
}
}
}, 1000);
}
private void setup(){
if(mMediaPlayer == null){
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(this);
}
if(mRenderer == null){
mRenderer = new VideoTextureRenderer(mContext, surfaceTexture, surfaceWidth, surfaceWidth );
}
getSurface();
}
public void setSource(String src){
videoPath = src;
}
public void setFilter(int filterCode){
switch (filterCode){
...
}
if(mediaPlayerReady){
mMediaPlayer.start();
mRenderer.setShader(fragmentShaderCode);
}
}
public void setCrop(boolean isCrop){
this.isCrop = isCrop;
if(mediaPlayerReady){
if(!mMediaPlayer.isPlaying()){
mMediaPlayer.start();
}
mRenderer.setCrop(this.isCrop);
}
}
public void togglePlayPause(){
if(mediaPlayerReady){
if(!mMediaPlayer.isPlaying()){
mMediaPlayer.start();
}else{
mMediaPlayer.pause();
}
}
}
public boolean isPlaying(){
if(mediaPlayerReady){
return mMediaPlayer.isPlaying();
}
return false;
}
public void setPaused(){
if(mediaPlayerReady){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}
}
}
public void setStop(){
if(mediaPlayerReady){
mMediaPlayer.stop();
}
}
public void setStart(){
if(mediaPlayerReady){
if(!mMediaPlayer.isPlaying()){
mMediaPlayer.start();
}
}
}
public void seekTo(int time){
if(mediaPlayerReady){
mMediaPlayer.seekTo(time);
}else{
seekto = time;
}
}
public boolean isPlayerReady(){
return mediaPlayerReady;
}
public int getCurrentPos(){
if(mediaPlayerReady){
return mMediaPlayer.getCurrentPosition();
}
return 0;
}
public int getDuration(){
return mMediaPlayer.getDuration();
}
public void setAutoPlay(boolean isAutoPlay){
this.isAutoPlay = isAutoPlay;
}
public void setLooping(boolean isLooping){
this.isLooping = isLooping;
}
@Override
public void onHostResume() {
if(isPaused){
resume();
isPaused = false;
}
}
@Override
public void onHostPause() {
pause();
}
@Override
public void onHostDestroy() {
cleanup();
}
public void resume(){
Log.e("DEBUG","IN RESUME");
}
public void pause(){
Log.e("DEBUG","IN PAUSE ");
if (mMediaPlayer != null){
Log.e("DEBUG","!NULL MPLAYER");
mMediaPlayer.pause();
mMediaPlayer.setDisplay(null);
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
if (mRenderer != null){
Log.e("DEBUG","!NULL MRENDER");
mRenderer.onPause();
mRenderer = null;
}
surfaceTexture = null;
mediaPlayerReady = false;
isPaused = true;
}
public void cleanup() {
Log.e("DEBUG", "CLEAN ");
if(mMediaPlayer != null){
mMediaPlayer.pause();
mMediaPlayer.release();
}
if(mRenderer != null){
mRenderer.onPause();
}
}
@Override
public void onSurfaceTextureAvailable(final SurfaceTexture surface, int width, int height) {
Log.e("DEBUG", "surface avalilable");
isTextureAvailable = true;
surfaceTexture = surface;
surfaceWidth = width;
surfaceHeight = height;
setup();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.e("DEBUG", "MASUK ONPREPARED");
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
mRenderer.setMediaPlayer(mMediaPlayer);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.setSurface(new Surface(surface));
mRenderer.setDimension(mMediaPlayer.getVideoWidth(), mMediaPlayer.getVideoHeight());
mRenderer.setShader(fragmentShaderCode);
mRenderer.setCrop(isCrop);
if(!mMediaPlayer.isLooping()){
mMediaPlayer.setLooping(isLooping);
}
if(isAutoPlay){
mMediaPlayer.start();
}else{
mMediaPlayer.seekTo(seekto);
}
mediaPlayerReady = true;
}
});
thread.run();
}
}
这是UI管理器代码
public class RNVideoPlayerManager extends SimpleViewManager<VideoPlayer>{
private static final String REACT_CLASS = "RNVideoEditPlayer";
private static final String PROPS_SRC = "src";
private static final String PROPS_CROP = "isCrop";
private static final String PROPS_SEEK = "seekTo";
private static final String PROPS_AUTOPLAY = "isAutoPlay";
private static final String PROPS_LOOPING = "isLoop";
private static final String PROPS_FILTER = "filter";
@Override
public String getName(){
return REACT_CLASS;
}
@Override
public VideoPlayer createViewInstance(ThemedReactContext themedReactContext){
return new VideoPlayer(themedReactContext);
}
@Override
public void onDropViewInstance(VideoPlayer videoPlayer) {
super.onDropViewInstance(videoPlayer);
videoPlayer.cleanup();
}
@ReactProp(name = PROPS_SRC)
public void setSource(final VideoPlayer videoPlayer, final String src){
videoPlayer.setSource(src);
}
@ReactProp(name = PROPS_CROP, defaultBoolean = false)
public void setCrop(final VideoPlayer videoPlayer, final boolean isCrop){
videoPlayer.setCrop(isCrop);
}
@ReactProp(name = PROPS_SEEK, defaultInt = -1)
public void seekTo(final VideoPlayer videoPlayer, final int seekTime){
if(seekTime > 0){
videoPlayer.seekTo(seekTime);
}else{
return;
}
}
@ReactProp(name = PROPS_AUTOPLAY, defaultBoolean = false)
public void setAutoPlay(final VideoPlayer videoPlayer, final boolean isAutoPlay){
videoPlayer.setAutoPlay(isAutoPlay);
}
@ReactProp(name = PROPS_LOOPING, defaultBoolean = false)
public void setLoop(final VideoPlayer videoPlayer, final boolean isLoop){
videoPlayer.setLooping(isLoop);
}
@ReactProp(name = PROPS_FILTER, defaultInt = 0)
public void setFilter(final VideoPlayer videoPlayer, final int filterId){
videoPlayer.setFilter(filterId);
}
}
这是我的javascript组件代码
import React, { Component, PropTypes } from 'react'
import {
AppRegistry,
requireNativeComponent,
View
} from 'react-native'
var iface = {
name: 'VideoPlayer',
propTypes: {
src : PropTypes.string,
isCrop : PropTypes.bool,
seekTo : PropTypes.number,
isAutoPlay : PropTypes.bool,
isLoop : PropTypes.bool,
filter : PropTypes.number,
...View.propTypes,
}
}
const VideoPlayer = requireNativeComponent('RNVideoEditPlayer', iface)
export class VideoEditPlayer extends Component{
static propTypes = {
src: PropTypes.string.isRequired,
isCrop : PropTypes.bool,
seekTo : PropTypes.number,
isAutoPlay : PropTypes.bool,
isLoop : PropTypes.bool,
filter : PropTypes.number,
style : PropTypes.object,
...View.propTypes,
}
static defaultProps = {
filter : 0,
isCrop : false,
isLoop : false,
isAutoPlay : false,
}
constructor(props){
super(props)
}
render(){
const{
src,
isCrop,
isLoop,
isAutoPlay,
seekTo,
filter,
style,
...props
} = this.props
return(
<VideoPlayer
style={style}
src={src}
isCrop={isCrop}
isAutoPlay={isAutoPlay}
isLoop={isLoop}
filter={filter}
seekTo={seekTo}
{...props}
/>
);
}
}