Android 反应本机UI组件,从任务/菜单按钮恢复后未调用MediaPlayer
我想创建一个android组件,在这个组件中我有一个视频播放器,它使用带有SurfacetTexture的MediaPlayer。当我在示例应用程序中尝试该组件时,它运行良好。但当我试着按下Home按钮(android设备中的圆圈按钮),然后从history off running应用程序(按下按钮任务/菜单,然后单击应用程序)再次打开应用程序时,媒体播放器无法正常调用。但如果我再次单击应用程序图标,媒体播放器将正常工作。有人知道会发生什么吗 当我从后台应用程序恢复它时,我尝试登录,它说Android 反应本机UI组件,从任务/菜单按钮恢复后未调用MediaPlayer,android,react-native,Android,React Native,我想创建一个android组件,在这个组件中我有一个视频播放器,它使用带有SurfacetTexture的MediaPlayer。当我在示例应用程序中尝试该组件时,它运行良好。但当我试着按下Home按钮(android设备中的圆圈按钮),然后从history off running应用程序(按下按钮任务/菜单,然后单击应用程序)再次打开应用程序时,媒体播放器无法正常调用。但如果我再次单击应用程序图标,媒体播放器将正常工作。有人知道会发生什么吗 当我从后台应用程序恢复它时,我尝试登录,它说 04-
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);
}
}
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}
/>
);
}
}
公共类RNVideoPlayerManager扩展了SimpleViewManager{
私有静态最终字符串REACT\u CLASS=“RNVideoEditPlayer”;
私有静态最终字符串道具\u SRC=“SRC”;
私有静态最终字符串道具\u CROP=“isCrop”;
私有静态最终字符串道具\u SEEK=“seekTo”;
私有静态最终字符串道具\u AUTOPLAY=“isAutoPlay”;
私有静态最终字符串PROPS\u LOOPING=“isLoop”;
私有静态最终字符串道具\u FILTER=“FILTER”;
@凌驾
公共字符串getName(){
返回一个类;
}
@凌驾
公共VideoPlayer createViewInstance(主题ReactContext主题ReactContext){
返回新的视频播放器(上下文);
}
@凌驾
公共无效onDropViewInstance(VideoPlayer VideoPlayer){
super.onDropViewInstance(视频播放器);
videoPlayer.cleanup();
}
@ReactProp(name=PROPS\u SRC)
public void setSource(最终VideoPlayer VideoPlayer,最终字符串src){
videoPlayer.setSource(src);
}
@ReactProp(name=PROPS\u CROP,defaultBoolean=false)
public void setCrop(最终视频播放器VideoPlayer,最终布尔值isCrop){
videoPlayer.setCrop(isCrop);
}
@ReactProp(name=PROPS\u SEEK,defaultInt=-1)
public void seekTo(最终视频播放器VideoPlayer,最终整数seekTime){
如果(请参见时间>0){
videoPlayer.seekTo(seekTime);
}否则{
返回;
}
}
@ReactProp(name=PROPS\u AUTOPLAY,defaultBoolean=false)
公共无效设置自动播放(最终视频播放器视频播放器,最终布尔值自动播放){
videoPlayer.setAutoPlay(自动播放);
}
@ReactProp(name=PROPS\u循环,defaultBoolean=false)
public void setLoop(最终VideoPlayer VideoPlayer,最终布尔isLoop){
视频播放器。设置循环(isLoop);
}
@ReactProp(name=PROPS\u过滤器,defaultInt=0)
公共无效设置筛选器(最终VideoPlayer VideoPlayer,最终int筛选器ID){
videoPlayer.setFilter(filterId);
}
}
这是我的javascript组件代码
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);
}
}
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}
/>
);
}
}
import React,{Component,PropTypes}来自“React”
进口{
评估学,
要求活动组件,
看法
}从“反应本机”
var iface={
名称:“视频播放器”,
道具类型:{
src:PropTypes.string,
isCrop:PropTypes.bool,
seekTo:PropTypes.number,
iAutoPlay:PropTypes.bool,
isLoop:PropTypes.bool,
过滤器:PropTypes.number,
…视图.propTypes,
}
}
const VideoPlayer=requirenActiveComponent('RNVideoEditPlayer',iface)
导出类VideoEditPlayer扩展组件{
静态类型={
src:PropTypes.string.isRequired,
isCrop:PropTypes.bool,
seekTo:PropTypes.number,
iAutoPlay:PropTypes.bool,
isLoop:PropTypes.bool,
过滤器:PropTypes.number,
样式:PropTypes.object,
…视图.propTypes,
}
静态defaultProps={
筛选器:0,
isCrop:false,
isLoop:false,
isAutoPlay:错,
}
建造师(道具){
超级(道具)
}
render(){
常数{
src,
isCrop,
伊斯卢普,
我是自动游戏,
希克托,
过滤器,
风格
…道具
}=这是道具
返回(
);
}
}
请显示一个演示问题的图标。@alroc这是否足够?这是演示问题所需的绝对最小值吗?还是一堆你的代码?@alroc我的问题是:1。我打开我的示例应用程序,使用我的组件(上面的组件代码),该应用程序正常显示视频。然后,;2.我按下home按钮(android设备中的midle按钮)。然后,;3.我打开后台应用程序,然后选择我的示例应用程序。应用程序已打开,但未显示任何视频。我收到了错误信息。但是如果我使用这个步骤:1。我打开我的示例应用程序,使用我的组件(上面的组件代码),该应用程序显示视频。然后,;2.我按下home按钮(android设备中的midle按钮)。然后,;3.我再次按下示例应用程序图标,它工作正常。