返回Android中的视频播放活动时出现黑屏

| 我目前正在开发Android应用程序ServeStream,遇到了无法解决的问题。我的应用程序将使用android MediaPlayer类流式传输音乐和视频。我根据以下示例找到了我的班级模型: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.html 此示例与我自己的代码之间的区别在于,我的MediaPlayer是在允许其在后台继续播放的服务中运行的。 android示例代码的问题是,如果我正在观看视频,并且退出了当前的窗口/活动(即,按菜单按钮等),然后返回到播放活动,则我得到黑屏,但仍然从正在播放的视频。 最初创建播放活动时,将执行以下代码。这段代码实质上是创建用于回放的视图,然后将其与媒体播放器联系起来:
        setContentView(R.layout.mediaplayer_2);
        mPreview = (SurfaceView) findViewById(R.id.surface);
        holder = mPreview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
...
        mMediaPlayer.setDisplay(holder);
重要的行是mMediaPlayer.setDisplay(holder),因为它将当前视图/显示与媒体播放器绑定在一起。离开活动时,视图(\“ holder \”)被破坏。返回活动并重新创建视图后,再次执行mMediaPlayer.setDisplay(holder)似乎不会重新附加新创建的视图。显示黑屏,而不是视频。 有没有人有解决此问题的方法或解决方案。我将不胜感激任何帮助或建议。     
已邀请:
        经过大量的搜索并head过ѭ1的状态图后,我终于设法避免了这种所谓的黑屏。我已经在OP的评论部分中发布了该问题似乎可以通过最新的Android版本(大于4.x)解决,因此我选择在Gingerbread设备上也具有类似的行为。 不用说,
SurfaceHolder
回调方法在有界的
MediaPlayer
-
SurfaceView
实现的生命周期中起着至关重要的作用。那些非常回调的方法对于摆脱这种情况很方便。 第一: 内部onCreate():-基本的初始化内容。
    mVideoSurface = (SurfaceView) findViewById(R.id.videoSurface);
    videoHolder = mVideoSurface.getHolder();
    videoHolder.addCallback(this);

    // For Android 2.2

    videoHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    // Media Player and Controller

    player = new MediaPlayer();
    controller = new VideoControllerView(this);
然后, SurfaceView回调: 别忘了将ѭ6设置为ѭ1,恕我直言,,8ѭ是执行此操作的最佳位置。
@Override
 public void surfaceCreated(SurfaceHolder holder) {
    player.setDisplay(holder);
    try {
    player.prepareAsync();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }
}
这是最重要的。当用户通过按“主页”按钮或通过打开预期有任何结果的其他活动离开当前活动时,我们的
SurfaceView
将被销毁。我想要实现的是从上下文切换后的播放位置继续播放正在进行的视频。 因此,为了做到这一点, 将当前播放位置保存在变量中,以便以后可以使用它来查找到该特定位置的播放。 还有一个。释放该死的“ 1”实例。我试图避免释放ѭ1实例,并且重新创建它,但是我不断失败。所以..点了。
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (player != null) {
        mCurrentVideoPosition = player.getCurrentPosition();
        player.release();
        player = null;
    }

}
现在,onPrepared() 如果您有兴趣,请在此处初始化任何
MediaController
。检查视频是否已经在播放,因此将视频搜索到该位置。
     @Override
 public void onPrepared(MediaPlayer mp) {
    controller.setMediaPlayer(this);
    controller.setAnchorView((FrameLayout) findViewById(R.id.videoSurfaceContainer));
    player.start();

    if (mCurrentVideoPosition != 0) {
        player.seekTo(mCurrentVideoPosition);
        player.start();
    }

}
最后,播放视频:
 void playVideo(){  

   try {
        if (player == null) 
            player = new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDataSource(\"SOME_VIDEO_FILE.3gp\");
        player.setOnPreparedListener(this);
        player.setOnErrorListener(new OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                mp.reset();
                return false;
            }
        });

    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
     }
仅此而已。我知道更新的版本并不存在这个问题,而且一切都很好,但是...还有大量的GB。     
        您可以执行以下操作:当
surfaceDestroy
并再次输入视频
setDisplay
时,带有新
surfaceHolder
的mediaPlayer将为
mMediaPlayer.setDisplay(null)
。 请记住,始终将此代码放在ѭ21内,因为当按下主屏幕或锁定屏幕时,它将强制使用新的持有人触发“ sufaceCreate \”。视图将被重新创建,视频将显示为黑屏
    holder = mPreview.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
希望这个帮助!     
        我想我知道问题的原因。似乎mediaplayer仅在您调用prepare / Async()时初始化其表面。如果此后改变表面,您将得到所得到的。因此,解决方案是通过android:configChanges = \“ orientation | keyboardHidden \”禁用活动的标准生命周期。这样可以防止您的活动消遣。否则,您应该在每次重新创建所有者时要求进行准备。     
我有同样的问题! 播放视频时,我按HOME按钮,然后返回到应用程序。我进去了:
public void surfaceCreated(SurfaceHolder holder) {
    player.setDisplay(holder);
    playVideo();
}
playVideo()
中,我有:
private void playVideo() {
    if (extras.getString(\"video_path\").equals(\"VIDEO_URI\")) {
        showToast(\"Please, set the video URI in HelloAndroidActivity.java in onClick(View v) method\");
    } else {
        try {
            if (flag == 0) {
                player.setDataSource(extras.getString(\"video_path\"));
                player.prepareAsync();
                flag = 1;
            }
            else
            {
                player.start();
            }
        } catch (IllegalArgumentException e) {
            showToast(\"Error while playing video\");
            Log.i(TAG, \"========== IllegalArgumentException ===========\");
            e.printStackTrace();
        } catch (IllegalStateException e) {
            showToast(\"Error while playing video\");
            Log.i(TAG, \"========== IllegalStateException ===========\");
            e.printStackTrace();
        } catch (IOException e) {
            showToast(\"Error while playing video. Please, check your network connection.\");
            Log.i(TAG, \"========== IOException ===========\");
            e.printStackTrace();
        }
    }
}
我的背景空白为黑色,听见音频流。 我注意到,如果在第一次启动此活动时,如果我不赚ѭ26,我的行为将相同。 花了两天时间来解决这个问题...     
        编辑:请注意,此解决方案在4.x设备上不起作用-视频根本不会出现,只有黑屏,我无法使其在那里工作。 这是一个执行以下操作的状态机:  1.播放短短几秒钟的视频/res/raw/anim_mp4.mp4(在onCreate()方法中启动的过程)  2.如果用户按下主屏幕按钮,然后返回到应用,它将搜索视频以开始位置并立即暂停(在onResume()方法中启动的过程)
package com.test.video;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;

public class MediaPlayerActivity extends Activity implements OnCompletionListener,
    MediaPlayer.OnPreparedListener, MediaPlayer.OnSeekCompleteListener, SurfaceHolder.Callback {

private final int STATE_NOT_INITIALIZED = 0;
private final int STATE_INITIALIZING = 1;
private final int STATE_INITIALIZED = 2;
private final int STATE_SEEKING = 3;
private final int STATE_DELAYING = 4;
private final int STATE_PLAYING = 5;
private final int STATE_FINISHED = 6;
private final int STATE_RESUMED = 7;
private final int STATE_RESUMED_PREPARING = 8;
private final int STATE_RESUMED_PREPARED = 9;
private final int STATE_RESUMED_SEEKING = 10;
private int state = STATE_NOT_INITIALIZED;

private SurfaceView surface;
private MediaPlayer player;
private SurfaceHolder holder;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.d(Constants.TAG, \"onCreate()\");
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.mediaplayer);

    surface = (SurfaceView) findViewById(R.id.idSurface);
    holder = surface.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
protected void onStart() {
    Log.d(Constants.TAG, \"onStart()\");
    super.onStart();
    state();
}

@Override
protected void onResume() {
    Log.d(Constants.TAG, \"onResume()\");
    super.onResume();
    if (STATE_FINISHED == state) {
        state = STATE_RESUMED;
        state();
    }
}

@Override
protected void onDestroy() {
    Log.d(Constants.TAG, \"onDestroy()\");
    super.onDestroy();
    if (player != null) {
        player.release();
        player = null;
    }
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    Log.d(Constants.TAG, \"surfaceChanged()\");
}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
    Log.d(Constants.TAG, \"surfaceCreated()\");
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
    Log.d(Constants.TAG, \"surfaceDestroyed()\");
}

@Override
public void onPrepared(MediaPlayer mp) {
    Log.d(Constants.TAG, \"onPrepared()\");
    state();
}

@Override
public void onCompletion(MediaPlayer mp) {
    Log.d(Constants.TAG, \"onCompletion()\");
    state();
}

@Override
public void onSeekComplete(MediaPlayer mediaplayer) {
    Log.d(Constants.TAG, \"onSeekComplete()\");
    state();
}

private class ResumeDelayed extends PlayDelayed {
    protected void onPostExecute(Void result) {
        Log.d(Constants.TAG, \"ResumeDelayed.onPostExecute()\");
        state();
    };
}

private void initPlayer() {
    Log.d(Constants.TAG, \"initPlayer()\");
    try {
        if (player == null) {
            player = new MediaPlayer();
            player.setScreenOnWhilePlaying(true);
        } else {
            player.stop();
            player.reset();
        }
        String uri = \"android.resource://\" + getPackageName() + \"/\" + R.raw.anim_mp4;
        player.setDataSource(this, Uri.parse(uri));
        player.setDisplay(holder);
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setOnPreparedListener(this);
        player.prepareAsync();
        player.setOnCompletionListener(this);
        player.setOnSeekCompleteListener(this);
    } catch (Throwable t) {
        Log.e(Constants.TAG, \"Exception in media prep\", t);
    }
}

private class PlayDelayed extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... arg0) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Log.e(Constants.TAG, \"Can\'t sleep\", e);
        }
        return null;
    }

    protected void onPostExecute(Void result) {
        Log.d(Constants.TAG, \"PlayDelayed.onPostExecute()\");
        initPlayer();
    };
}

private void state() {
    switch (state) {
        case STATE_NOT_INITIALIZED:
            state = STATE_INITIALIZING;
            initPlayer();
            break;
        case STATE_INITIALIZING:
            state = STATE_INITIALIZED;
            new PlayDelayed().execute();
            break;
        case STATE_INITIALIZED:
            state = STATE_SEEKING;
            player.start();
            player.seekTo(0);
            break;
        case STATE_SEEKING:
            state = STATE_DELAYING;
            player.pause();
            new ResumeDelayed().execute();
            break;
        case STATE_DELAYING:
            state = STATE_PLAYING;
            player.start();
            break;
        case STATE_PLAYING:
            state = STATE_FINISHED;
            break;
        case STATE_RESUMED:
            state = STATE_RESUMED_PREPARING;
            initPlayer();
            break;
        case STATE_RESUMED_PREPARING:
            state = STATE_RESUMED_PREPARED;
            new PlayDelayed().execute();
            break;
        case STATE_RESUMED_PREPARED:
            state = STATE_RESUMED_SEEKING;
            player.start();
            player.seekTo(0);
            break;
        case STATE_RESUMED_SEEKING:
            state = STATE_FINISHED;
            player.pause();
            break;
        default:
            break;
    }
}
mediaplayer.xml布局:
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"
android:layout_width=\"fill_parent\"
android:layout_height=\"fill_parent\"
android:background=\"@android:color/black\" >

<SurfaceView
    android:id=\"@+id/idSurface\"
    android:layout_width=\"wrap_content\"
    android:layout_height=\"wrap_content\"
    android:layout_gravity=\"center\" />
AndroidManifest.xml看起来像:
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"
package=\"com.test.video\"
android:versionCode=\"1\"
android:versionName=\"1.0\" >

<uses-sdk android:minSdkVersion=\"10\" />

<application
    android:icon=\"@drawable/ic_launcher\"
    android:theme=\"@android:style/Theme.Black.NoTitleBar\" >
    <activity
        android:name=\".MediaPlayerActivity\"
        android:label=\"@string/app_name\"
        android:screenOrientation=\"portrait\"
        android:theme=\"@android:style/Theme.Black.NoTitleBar\" >
        <intent-filter>
            <action android:name=\"android.intent.action.MAIN\" />

            <category android:name=\"android.intent.category.LAUNCHER\" />
        </intent-filter>
    </activity>
</application>
    
        我在银河S3和Xoom平板电脑上播放视频时也遇到了同样的问题。我在播放器设置中关闭了硬件(HW)加速,从而解决了该问题。我不为Android开发,但希望这会为您提供解决方案。也许您可以切换此设置以解决。我正在使用的设备可能没有硬件加速。     
        您是否希望返回时不显示活动? 如果是的话,你可以简单地使用标志
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
如果您想让媒体在后台播放,我建议您使用视频界面,尽管我不想在后台播放,这会激怒我。有很多方法,但我希望这对您有帮助 http://www.brightec.co.uk/blog/custom-android-media-controller 该链接实际上是根据您的需要定制媒体控制器的,但是当我用它创建我的链接时,我被按下Home键所困扰,视频将在后台播放。     

要回复问题请先登录注册