2010-12-03 17 views
14

Tengo una VideoView que quiero usar para reproducir un clip de película. Lo uso así para jugarlo y funciona.VideoView flash negro antes y después de jugar

VideoView vv = new VideoView(this); 
vv.setVideoURI(Uri.parse("android.resource://cortex2.hcbj/raw/intro")); 
setContentView(vv); 
vv.start(); 

Sin embargo, veo un flash negro justo antes y después del clip de película. El flash en sí mismo no es un gran problema, pero es negro. El fondo es blanco, por lo que si el flash es blanco o si desaparece, estará bien.

+0

favor pegar algunas capturas de pantalla. –

+0

el flash negro ... realmente desagradable :( –

+0

Solución simple se encuentra en: http://stackoverflow.com/questions/9765629/android-videoview-black-screen/16302973#16302973 – user517708

Respuesta

8

Hoy tuve el mismo problema y encontré una solución muy mala y hacky para este desagradable problema: me di cuenta de que se puede establecer un color de fondo/dibujable en el VideoView que se funde sobre la superficie de video y lo oculta por completo. Esto solo funciona aunque el video subyacente sigue siendo jugando a, no cuando se detiene (ni cuando terminó normalmente ni cuando se llamó a stopPlayback()), de lo contrario volvería a ver un parpadeo negro. El fondo tampoco debe establecerse al principio, de lo contrario, el video estaría completamente oculto desde el principio.

Así que el único paso lógico para mí fue publicar un evento retrasado justo antes de iniciar el video, y como conozco la duración del video, dejo que este evento ocurra solo unos pocos milisegundos antes de que termine normalmente.Me tomó una captura de pantalla de la última trama de VLC y después se mezcla así:

private void startVideo() 
{ 
    introVideo.setBackgroundDrawable(null); 
    introVideo.postDelayed(new Runnable() { 
     public void run() 
     { 
      if (!introVideo.isPlaying()) 
       return; 

      introVideo.setBackgroundResource(R.drawable.video_still_image); 
      // other stuff here, for example a custom transition to 
      // another activity 
     } 
    }, 7500); // the video is roughly 8000ms long 
    introVideo.start(); 
} 

Sin embargo, esto no fue suficiente, ya que cuando el video en realidad terminó, yo todavía tengo un breve parpadeo de la pantalla negro, así que también tenía para establecer la imagen fija como fondo del recipiente que contenía el video (en mi caso fue el diseño de la actividad):

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:background="@drawable/video_still_image"> 

    <VideoView android:id="@+id/introVideo" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:layout_alignParentRight="true" 
       android:layout_alignParentLeft="true" 
       android:layout_alignParentTop="true" 
       android:layout_alignParentBottom="true" 
       android:layout_marginTop="-10dip" /> 

</RelativeLayout> 

Esta actividad se representa en pantalla completa y el video es (en su mayoría) a escala en el tamaño total de la pantalla (pantalla 1024x600, video 960x640). Digo en su mayoría, porque por alguna razón desconocida, la imagen de fondo del diseño se mezcla para aproximadamente 10px en la parte superior. Este fue el último truco que tuve que aplicar para que funcione: mueva el contenedor de video -10dip al vacío en la parte superior.

Esto ahora se ve impresionante en mi Galaxy Tab, que no se atreven a probarlo en el teléfono SGS2, aunque ...

0

Ese flash proviene de cambiar la vista de contenido actual por otra. Podría intentar agregar un VideoView a su archivo xml de diseño y luego hacer referencia al mismo con (VideoView) findViewById(R.id.vid); en lugar de new VideoView(this); y configurar la vista de contenido para ese diseño.

+3

El destello negro también aparece cuando buscas la vista de video a través de findViewById, así que desafortunadamente esta no es una solución. –

+1

Veo el flash negro la primera vez que la videoview reproduce un video. El problema es que toda la interfaz de usuario sufre el flash negro aunque la vista de video solo usa el 50% del UI! –

0

Por qué no usar Estilo y Temas

Se puede probar esto? Esto podría ayudar a

colors.xml

<drawable name="transparent">#00000000</drawable> 

styles.xml

<style name="Transparent"> 
<item name="android:windowIsTranslucent">true</item> 
<item name="android:windowAnimationStyle"> 
@android:style/Animation.Translucent 
</item> 
<item name="android:windowBackground">@drawable/transparent</item> 
<item name="android:windowNoTitle">true</item> 
<item name="android:colorForeground">#fff</item> 
</style> 

para definir un tema para todas las actividades de su aplicación, abra el archivo AndroidManifest.xml y editar la etiqueta de incluye el atributo android: theme con el nombre del estilo.

<application android:theme="@style/Transparent"> 
0

¿Dónde está cambiando el contentView (en qué método escribió las cuatro líneas de código anteriores)?

Solo debe establecer contentView en el método onCreate() de Activity. Si lo hace en otro lugar (por ejemplo, en la devolución de llamada de un botón), debe comenzar una actividad nueva.

0

Hay una alternativa que se utiliza el controlador de medios para esto. Aquí está el código de muestra

videoView = (VideoView) this.findViewById(R.id.videoView); 
MediaController mc = new MediaController(this); 
videoView.setMediaController(mc); 
videoView.setVideoURI(Uri.parse("http://c421470.r70.cf2.rackcdn.com/video_5983079.m4v")); 
videoView.start(); 
videoView.requestFocus(); 

Pruebe esto.

1

Mi solución de este error diabólico utilizado una vista en blanco con el color de fondo de elección sobre la parte superior de VideoView.

<View 
     android:id="@+id/blankView" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:background="@color/white" /> 

entonces en mi código que hicieron esto:

 video = (VideoView) findViewById(R.id.video); 
     // set the video URI, passing the vSourse as a URI 
     video.setVideoURI(Uri.parse(vSource)); 
     video.setZOrderOnTop(false); 

     SurfaceHolder sh = video.getHolder(); 
     sh.setFormat(PixelFormat.TRANSPARENT); 

     ctlr = new BCDMediaController(this); 
     ctlr.setMediaPlayer(video); 
     video.setMediaController(ctlr); 
     video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {    
      @Override 
      public void onCompletion(MediaPlayer mp) { 
       closeActivity(); 
      } 
     }); 

     blankView = findViewById(R.id.blankView); 

     video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
      @Override 
      public void onPrepared(MediaPlayer mp) {  
       blankView.postDelayed(new Runnable() { 
         public void run() 
         { 
          blankView.setVisibility(View.GONE); 
         } 
        }, 500);      
      } 
     }); 

     video.start(); 
     video.requestFocus(); 

que hicieron desaparecer el flash negro empezando por mí. Luego, para el final del flash negro, hice esto:

private void closeActivity() { 
blankView.setVisibility(View.VISIBLE);   
    blankView.postDelayed(new Runnable() { 
     public void run() 
     { 
      video.setOnCompletionListener(null); 
      video.stopPlayback(); 
      video.suspend(); 
      VideoPlayerViewController.this.finish(); 
     } 
    }, 1);  
} 

Si eso ayuda, vote esta respuesta.

2

Terminé teniendo que hacer algo muy similar a @tommyd para evitar el flash negro surfaceView al principio y al final de mis videos. Sin embargo, descubrí que la configuración/anulación del fondo dibujable para el videoView no ocurría instantáneamente en muchos teléfonos. Podría haber un retraso de aproximadamente medio segundo entre mi llamada para establecer el fondo y cuándo realmente se mostró.

Lo que terminé haciendo fue crear un SurfaceView personalizado que mostraba un único color sólido, luego superpuse esto en la parte superior de VideoView y usé SurfaceView.setZOrderMediaOverlay().

Mi SurfaceView costumbre fue en gran medida informada por: http://android-er.blogspot.com/2010/05/android-surfaceview.html

public class SolidSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 

    private static final String TAG = SolidSurfaceView.class.getSimpleName(); 

    private SolidSurfaceThread mThread; 
    private boolean mSurfaceIsValid; 
    private int mColor; 

    public SolidSurfaceView(Context context) { 
     super(context); 
     init(); 
    } 

    public SolidSurfaceView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public SolidSurfaceView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    private void init() { 
     Log.verbose(TAG, "init"); 

     getHolder().addCallback(this); 
     setZOrderMediaOverlay(true); 
    } 

    public void setColor(int color) { 
     mColor = color; 
     invalidate(); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     Log.verbose(TAG, "surfaceCreated"); 

     mSurfaceIsValid = true; 

     mThread = new SolidSurfaceThread(getHolder(), this); 
     mThread.setRunning(true); 
     mThread.start(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     Log.verbose(TAG, "surfaceDestroyed"); 
     mSurfaceIsValid = false; 

     boolean retry = true; 
     mThread.setRunning(false); 
     while (retry) { 
      try { 
       mThread.join(); 
       retry = false; 
      } 
      catch (InterruptedException e) { 
       Log.warning(TAG, "Thread join interrupted"); 
      } 
     } 
     mThread = null; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (! mSurfaceIsValid) { 
      return; 
     } 

     canvas.drawColor(mColor); 
    } 

    private static class SolidSurfaceThread extends Thread { 

     private final SurfaceHolder mSurfaceHolder; 
     private final SolidSurfaceView mSurfaceView; 
     private boolean mIsRunning; 

     public SolidSurfaceThread(SurfaceHolder surfaceHolder, SolidSurfaceView surfaceView) { 
      mSurfaceHolder = surfaceHolder; 
      mSurfaceView = surfaceView; 
     } 

     public void setRunning(boolean running) { 
      mIsRunning = running; 
     } 

     @Override 
     public void run() { 
      while (mIsRunning) { 
       Canvas c = null; 
       try { 
        c = mSurfaceHolder.lockCanvas(null); 
        synchronized (mSurfaceHolder) { 
         mSurfaceView.onDraw(c); 
        } 
       } 
       finally { 
        // do this in a finally so that if an exception is thrown 
        // during the above, we don't leave the Surface in an 
        // inconsistent state 
        if (c != null) { 
         mSurfaceHolder.unlockCanvasAndPost(c); 
        } 
       } 
      } 
     } 
    } 
} 

Y en la actividad principal que alberga los puntos de vista:

mVideoView = (VideoView)findViewById(R.id.video_view); 
    mVideoMask = (SolidSurfaceView)findViewById(R.id.video_mask); 
    mVideoMask.setColor(Color.BLUE); 

A continuación, puede hacer cosas como mVideoMask.setVisibility(View.GONE) para ocultar la máscara o mVideoMask.setVisibility(View.VISIBLE) para mostrar la máscara (y ocultar el VideoView con pantalla negra).

En mis experimentos con varios teléfonos, este método proporcionó una visualización/ocultación muy rápida de la máscara de video, en lugar de establecer/anular el fondo.

+0

Por favor, déjame cómo usar SolidSurfaceView en xml –

0

Otra solución que podría funcionar para las personas que están en busca de esta pregunta:

En mi caso, el vídeo era un recurso en la aplicación (es decir, sabía todo sobre él y no iba a cambian) y sus últimos 500 ms eran el mismo marco, por lo que terminaron haciendo lo siguiente:

mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.splash)); 
mVideoView.start(); 

findViewById(android.R.id.content).postDelayed(new WaitForSplashScreenToFinish(), mVideoView.getDuration() - 1000); 

y la clase de referencia es:

private class WaitForSplashScreenToFinish implements Runnable { 
    @Override 
    public void run() { 
     if (mVideoView.isPlaying() && mVideoView.getCurrentPosition() >= mVideoView.getDuration() - 500) { 
      mVideoView.pause(); 

      // Now do something else, like changing activity 
     } else { 
      findViewById(android.R.id.content).postDelayed(this, 100); 
     } 
    } 
} 

Explicación: Inmediatamente después de iniciar el video, creo un Runnable y postDelayed en la vista raíz (android.R.id.content) a la duración del video, menos la longitud en la que estoy dispuesto a pausar el video (y un buffer generoso, porque postDelayed no está garantizado para jugar exactamente después del tiempo solicitado)

Luego, el ejecutable comprueba si el video llegó a su tiempo de pausa, si es así lo detiene y hace lo que sea que queramos que haga. Si no es así, se ejecuta de nuevo con postDelayed sí, para un tiempo más corto (100 ms en mi caso, pero podría ser más corto)

Por supuesto, este es el momento de ser una solución ideal, pero podría ayudar alguien con un problema específico similar al que me sorprendió durante medio día :)

2

tuve el mismo problema y el blanco en lugar del negro estaba bien para mí ... intenté todas las soluciones anteriores, se me ocurrió lo siguiente

vv.setBackgroundColor(Color.WHITE); 
vv.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        vv.setVideoURI(videoUri); 
       } 
      }, 100); 
vv.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        vv.setBackgroundColor(Color.TRANSPARENT); 
       } 
      }, 300); 
      vv.requestFocus(); 
      vv.start(); 

y retrasé mi video 400 ms empiezo a desvanecerme de blanco funciona como un encanto para mí

0

Sé que es una pregunta antigua, pero si puede agregar algún código a los oyentes de MediaPlayer, la respuesta es muy simple. Resultó que setBackgroundColor para VideoView cambia el color de primer plano (https://groups.google.com/forum/?fromgroups=#!topic/android-developers/B8CEC64qYhQ).
Así que lo único que tienes que hacer es cambiar entre setBackgroundColor (Color.WHITE) y setBackgroundColor (Color.TRANSPARENT).

0

Mi variación sobre el tema @tommyd:

Establecer el dibujable a un fotograma de vídeo estático, entonces la cola de mensajes de spam. Después de un tiempo, borre el dibujo para que los marcos de video se rendericen. Luego, antes de finalizar, restablece la imagen estática.

mMovieView.setBackgroundDrawable(bg); 
    mMovieView.start(); 

    final int kPollTime= 25; 
    mMovieView.postDelayed(new Runnable() { 

     private final int kStartTransitionInThreshold= 50; 
     private final int kStartTransitionOutThreshold= 250; 

     private boolean mTransitioned= false; 
     @Override 
     public void run() { 
      if (mMovieView.isPlaying()) { 
       if (mMovieView.getCurrentPosition() > kStartTransitionInThreshold && !mTransitioned) { 
        mMovieView.setBackgroundDrawable(null); // clear to video 
        mTransitioned= true; 
       } 

       if (mMovieView.getDuration() - mMovieView.getCurrentPosition() < kStartTransitionOutThreshold) 
        mMovieView.setBackgroundDrawable(bg); 
      } 

      mMovieView.postDelayed(this, kPollTime); // come back in a bit and try again 
     } 
    }, kPollTime); 
0

tuve este mismo problema ha trabajado para mí ..

Cuando se quiere mostrar el vídeo hacen videoView.setZOrderOnTop (false); y cuando quiera ocultar la vista de video solo haga videoView.setZOrderOnTop (verdadero);

0

Pruebe esta línea. Esto funcionó para mí. if (jugador! = nulo) player.release();

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
     player.pause(); 
    if(player!=null)player.release(); 
    player = null; 
    videoSurface = null; 
    controller = null; 

} 
0

aquí es simple truco

cheque el reproductor multimedia condición .getCurrentPosition == 0 en el oyente preparado de vista de vídeo, pantalla en negro aparecerá cuando la posición es cero, de manera que se vea una imagen hasta que el vídeo se carga

mycode:

mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
     @Override 
     public void onPrepared(final MediaPlayer mediaPlayer) { 
       mVideoView.start(); 


       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 

         while (mediaPlayer.isPlaying()) { 
          Log.d("MainActivity", "position " + mediaPlayer.getCurrentPosition()); 
          if (mediaPlayer.getCurrentPosition() == 0) { 
           videoStillImageView.setVisibility(View.VISIBLE); 
          } else { 
           videoStillImageView.setVisibility(View.GONE); 


           break; 
          } 
         } 

        } 
       }); 
      } 
     } 
    }); 
Cuestiones relacionadas