Android MediaPlayer onResume时黑屏问题求助
Hey there, let's tackle this black screen issue when resuming your video playback in the scaled state! I've run into similar TextureView quirks before, so here are some targeted fixes and checks you can try:
1. Wait for TextureView's Surface to Be Fully Available
TextureView's surface doesn't always initialize synchronously with the fragment's onResume() method. If you try to resume playback before the surface is ready, MediaPlayer has nothing to render to—resulting in a black screen.
Instead of triggering playback directly in onResume(), rely on the SurfaceTextureListener to handle surface readiness:
// Initialize this listener when setting up your TextureView textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener { override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) { val playbackSurface = Surface(surface) mediaPlayer.setSurface(playbackSurface) // Restore your saved playback state here mediaPlayer.seekTo(savedPlaybackPosition) if (isFullScreenMode) { mediaPlayer.start() } // For scaled mode, skip start()—seekTo will display the last paused frame } override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) { // Optional: Adjust video aspect ratio to match the new surface size } override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean { mediaPlayer.setSurface(null) return true } override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {} }
2. Properly Preserve and Restore Playback State
Make sure you're saving critical state in onPause() to avoid losing track of where the video was, or whether it should resume:
private var savedPlaybackPosition = 0 private var isFullScreenMode = false private var wasPlayingBeforePause = false override fun onPause() { super.onPause() if (mediaPlayer.isPlaying) { savedPlaybackPosition = mediaPlayer.currentPosition wasPlayingBeforePause = true mediaPlayer.pause() } else { wasPlayingBeforePause = false } // Release the surface to avoid memory leaks mediaPlayer.setSurface(null) // Save your fullscreen/scaled state here (e.g., from your UI state) isFullScreenMode = getCurrentScreenMode() }
Then in your fragment's onResume(), add a check to handle cases where the surface is already available:
override fun onResume() { super.onResume() if (textureView.isAvailable) { // Surface is ready—restore playback immediately restorePlaybackState() } // If not available, the SurfaceTextureListener will handle it later } private fun restorePlaybackState() { val playbackSurface = Surface(textureView.surfaceTexture) mediaPlayer.setSurface(playbackSurface) mediaPlayer.seekTo(savedPlaybackPosition) if (isFullScreenMode && wasPlayingBeforePause) { mediaPlayer.start() } }
3. Check for MediaPlayer Errors
Sometimes black screens hide underlying MediaPlayer errors. Add an error listener to catch issues during resume:
mediaPlayer.setOnErrorListener { mp, errorCode, extraCode -> Log.e("VideoPlayer", "Resume error: Code $errorCode, Extra $extraCode") // Optional: Reset and re-prepare the MediaPlayer if needed mp.reset() prepareMediaPlayer() // Your existing media preparation logic return@setOnErrorListener true }
4. Avoid Over-Releasing MediaPlayer
Don't call mediaPlayer.release() in onPause() unless you're sure the fragment will be destroyed. Releasing and reinitializing MediaPlayer on every pause/resume can cause delays and black screens. Stick to pausing and clearing the surface instead.
内容的提问来源于stack exchange,提问作者Chandan Pednekar

