Android VideoView черный экран - PullRequest
49 голосов
/ 19 марта 2012

Я искал способ избавиться от неприятного черного начального экрана в VideoView перед запуском метода start ().

Я пробовал использовать фоновое изображение на виджете, но оно не работаеткак и ожидалось.Я также попытался поместить изображение первого кадра в видео поверх VideoView и скрыть его после метода stars ().Добавление onPrepared слушателя, чтобы начать видео, а затем скрыть изображение.Это работает, но при переходе происходит ужасное мерцание, и я не знаю, как от него избавиться.


Спасибо за ваш ответ.Добавление MediaController не имело никакого эффекта.Проблема сохраняется (я все еще вижу черное мерцание), и я не хочу, чтобы видео элементы управления были видны вообще.Мой код выглядит так:

    VideoView vSurface= (VideoView) findViewById(R.id.surfaceView1);
    vSurface.setVideoURI(Uri.parse("android.resource://com.mypackage/" + R.raw.video1));
    vSurface.setVisibility(View.VISIBLE);
    vSurface.setOnPreparedListener(this);
    vSurface.setDrawingCacheEnabled(true);
    vSurface.setOnErrorListener(this);

Ответы [ 21 ]

48 голосов
/ 29 октября 2014

Я сталкиваюсь с той же проблемой и решаю ее с помощью принятого выше решения, а также:

  @Override
  public void onPrepared(MediaPlayer mp) {
    mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
      @Override
      public boolean onInfo(MediaPlayer mp, int what, int extra) {
        Log.d(TAG, "onInfo, what = " + what);
        if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
          // video started; hide the placeholder.
          placeholder.setVisibility(View.GONE);
          return true;
        }
        return false;
      }
    });

Я думаю, что onPrepared означает, что видео готово к воспроизведению, но не означает, что видео начало воспроизводиться.Если скрыть местозаполнитель в onPrepared, на экране по-прежнему отображается черный экран.

На моих Note3 и Nexus это решение хорошо работает.

38 голосов
/ 30 апреля 2013

У меня была такая же проблема на Galaxy tab 2, Android 4.1.1.

До videoView.setZOrderOnTop(true); и далее videoView.start()

У меня отлично работает.

35 голосов
/ 02 апреля 2012

У меня та же проблема, и я нашел решение.Это немного хакерски, но это делает свое дело.В общем, вам нужно поместить VideoView в FrameLayout.Вы можете добавить еще один FrameLayout к фоновому видео поверх фона видео, и когда видео загружено и готово к воспроизведению, вы скрываете заполнитель.

<FrameLayout
  android:id="@+id/frameLayout1"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:layout_gravity="center"
  android:layout_marginTop="50dip" >

  <VideoView
    android:id="@+id/geoloc_anim"
    android:layout_width="fill_parent"
    android:layout_height="172dip" android:layout_gravity="top|center" android:visibility="visible"/>

  <FrameLayout
      android:id="@+id/placeholder"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" android:background="@drawable/fondvert_anim">
  </FrameLayout>

В своей деятельности вам нужнореализовать OnPreparedListener и добавить это

//Called when the video is ready to play
public void onPrepared(MediaPlayer mp) {

    View placeholder = (View) findViewById(R.id.placeholder);

    placeholder.setVisibility(View.GONE);
}

Так что, когда видео готово, мы скрываем наш заполнитель и этот трюк избегает черного мерцающего экрана.

Надеюсь, это кому-нибудь поможет.

25 голосов
/ 02 июля 2012

У меня была такая же проблема, и это сработало для меня ..

Если вы хотите показать видео, сделайте videoView.setZOrderOnTop (false); и когда вы хотите скрыть видео, просто сделайте videoView.setZOrderOnTop (true);

20 голосов
/ 28 марта 2013

У меня та же проблема, я просто использовал videov.setBackgroundColor (Color.WHITE), а затем наготове, я использовал Color.TRANSPARENT) белый цвет по-прежнему лучше, чем черный для меня

16 голосов
/ 03 июля 2013

Расширяя TextureView, я не получаю чёрных экранов в начале или конце.Это если вы хотите избежать использования ZOrderOnTop(true).

public class MyVideoView extends TextureView implements TextureView.SurfaceTextureListener {
  private MediaPlayer mMediaPlayer;
  private Uri mSource;
  private MediaPlayer.OnCompletionListener mCompletionListener;
  private boolean isLooping = false;


  public MyVideoView(Context context) {
      this(context, null, 0);
  }

  public MyVideoView(Context context, AttributeSet attrs) {
      this(context, attrs, 0);
  }

  public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      setSurfaceTextureListener(this);
  }

  public void setSource(Uri source) {
      mSource = source;
  }

  public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
      mCompletionListener = listener;
  }

  public void setLooping(boolean looping) {
     isLooping = looping;
  }

  @Override
  protected void onDetachedFromWindow() {
     // release resources on detach
     if (mMediaPlayer != null) {
         mMediaPlayer.release();
         mMediaPlayer = null;
     }
     super.onDetachedFromWindow();
   }

   /*
    * TextureView.SurfaceTextureListener
    */
    @Override
   public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
     Surface surface = new Surface(surfaceTexture);
     try {
         mMediaPlayer = new MediaPlayer();
         mMediaPlayer.setOnCompletionListener(mCompletionListener);
         mMediaPlayer.setOnBufferingUpdateListener(this);
         mMediaPlayer.setOnErrorListener(this);
         mMediaPlayer.setLooping(isLooping);
         mMediaPlayer.setDataSource(getContext(), mSource);
         mMediaPlayer.setSurface(surface);
         mMediaPlayer.prepare();
         mMediaPlayer.start();
     } catch (IllegalArgumentException e) {
         e.printStackTrace();
     } catch (SecurityException e) {
         e.printStackTrace();
     } catch (IllegalStateException e) {
         e.printStackTrace();
         mMediaPlayer.reset();
     } catch (IOException e) {
         e.printStackTrace();
     }
   }

   @Override
   public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}

  @Override
  public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
     surface.release();
     return true;
  }

  @Override
  public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}
7 голосов
/ 11 августа 2014

Это сработало для меня:

videoView.setBackgroundColor(Color.WHITE); // Your color.
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        videoView.setBackgroundColor(Color.TRANSPARENT);
    }
});

По крайней мере, два года спустя, но я надеюсь, что это было полезно.

4 голосов
/ 21 сентября 2016

Ничто из вышеперечисленного не сработало для меня.В моем случае onPrepared вызывается ДО того, как черная рамка исчезнет, ​​поэтому я все равно вижу черную рамку.

Мне нужно было решение, в котором видео появилось вскоре после первого кадра.

Итак, я установил альфа-канал VideoView на 0 в формате xml:

android:alpha="0"

, а затем перед тем, как запустить видео, я анимировал альфа обратно на 1:

videoView.animate().alpha(1);
videoView.seekTo(0);
videoView.start();

илиВы можете просто опубликовать отложенный Runnable, чтобы установить альфа на 1 вместо его анимации.

4 голосов
/ 15 марта 2013

Это определенно хакерский, но лучше, чем наложение изображения (IMO).

boolean mRestored = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mRestored = savedInstanceState != null;
}

@Override
public void onPrepared(MediaPlayer mp) {

    if (!mRestored) vSurface.seekTo(1);
}

Предполагается, что вы помещаете вещи в savedInstanceState в onSaveInstanceState.

2 голосов
/ 20 июня 2015

Это работает для меня:

В XML: VideoView прячется за относительный макет с белым фоном

    <VideoView
      android:id="@+id/myVideo"
      android:layout_below="@+id/logo_top"
      android:layout_width="200dp"
      android:layout_height="200dp"
      android:layout_centerHorizontal="true" 
    />
    <RelativeLayout
      android:id="@+id/mask"
      android:background="#FFFFFF"
      android:layout_below="@+id/logo_top"
      android:layout_centerHorizontal="true"
      android:layout_width="200dp"  android:layout_height="200dp"
    >
    </RelativeLayout>

и в Activity: onCreate

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.acceuil);
    myVideo = (VideoView)  findViewById(R.id.myVideo);
    mask = (RelativeLayout)  findViewById(R.id.mask);
    String path = "android.resource://" 
      + getPackageName() + "/" + R.raw.anim_normal;
    myVideo.setVideoURI(Uri.parse(path));
    myVideo.start();
}

при запуске:

 public void onStart() { 
    final long time = System.currentTimeMillis();
    super.onStart();
    new CountDownTimer(5000, 100) { 
    @Override
        public void onTick(long l) {

            long time2 = System.currentTimeMillis();
            if((time2 - time) > 500) {
                mask.setVisibility(View.GONE);
            }
        }

}.start();

Надеюсь, это поможет.

...