Подтвердить что ты не робот

Черный экран Android VideoView

Я искал способ избавиться от неприятного черного начального экрана в 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);
4b9b3361

Ответ 1

У меня такая же проблема, и я нашел решение. Это немного взломанно, но это делает трюк. Поэтому в основном вам нужно поставить свой 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);
}

Итак, когда видео готово, мы скрываем наш placeholder и этот трюк избегаем экрана черного мерцания.

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

Ответ 2

Я встречаю ту же проблему и решаю ее с принятым решением выше плюс это:

  @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 просто означает, что видео готово к воспроизведению, но не означает, что видео начало играть. Если hide placeholder в onPrepared, на экране по-прежнему отображается черный экран.

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

Ответ 3

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

Сделайте videoView.setZOrderOnTop(true); и следующий videoView.start()

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

Расширяя 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

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

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

Не менее двух лет спустя, но я надеюсь, что это было полезно.

Ответ 8

Это определенно взломанно, но лучше, чем наложение изображения (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.

Ответ 9

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

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

Итак, что я сделал, было установлено, что VideoView alpha равно 0 в xml:

android:alpha="0"

а затем, прежде чем начать видео, я обновляю альфа обратно до 1:

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

альтернативно, вы можете просто опубликовать задержанный Runnable, чтобы установить альфа-значение в 1 вместо анимирования.

Ответ 10

Просто используйте VideoView # setBackgroundDrawable(), я думаю.

  • начальные настройки.

    VideoView.setBackgroundDrawable(yourdrawableid);
    
  • начать видео

    VideoView.start();
    VideoView.setBackgroundDrawable(0);
    

Ответ 11

Просто покажите кадр из видео в виде предварительного просмотра.

vSurface.SeekTo(100);

Ответ 12

Для людей, которые все еще ищут ответ, для меня работали вызовы VideoView.start() и VideoView.pause() подряд внутри onPrepared. Я знаю, что это не может быть идеальным способом достижения этого, однако это может быть тот, у кого минимальное обходное решение, требуемое в коде. Надеюсь, это сработает и для вас.

@Override
public void onPrepared(MediaPlayer mp) {
    mVideoView.start();
    mVideoView.pause();
}

Ответ 13

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

В 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>

и в действии: 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();
}

onStart:

 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();

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

Ответ 14

Это работает для меня как на активность и фрагмент.

VideoView mVideo = (VideoView) findViewById(R.id.yourViewViewId);
          mVideo.setVideoURI(mUri);
          mVideo.setZOrderOnTop(false);

SurfaceHolder surfaceholder = mVideo.getHolder();
surfaceholder.setFormat(PixelFormat.TRANSPARENT);

Ответ 15

Немного поздно для этого ответа, но, возможно, у других пользователей такая же проблема и найти этот вопрос.

Я справился с этим, установив BackgroundResource изначально, а затем, при запуске видео, я установил фон в невидимый цвет.

VideoView myView = findViewById(R.id.my_view);
myView.setBackgroundResource(R.drawable.some_resource);
// some stuff

// this is when starting the video
myView.setVideoUri(someUri);
// also set MediaController somewhere...
//...
// now set the backgroundcolor to be not visible (first val of Color.argb(..) is the alpha)
myView.setBackGroundColor(Color.argb(0, 0, 0, 0));
//...
myView.start();

Ответ 16

Я бы предпочел это решение: fooobar.com/questions/132842/...

его о поверхности, поэтому создайте макет фиктивного @фрагмента, и вы не увидите эту черную вспышку снова.

Ответ 17

Это хорошее решение:

package com.example.videoviewpractice;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;

public class MainActivity extends Activity {

    VideoView myVideoView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initVideo();
}

private void initVideo() {
    myVideoView = (VideoView) findViewById(R.id.videoView1);
    String url = "http://mtc.cdn.vine.co/r/videos/3DF00EB7001110633055418310656_1e50d6d9a65.3.2.mp4?" + 
            "versionId=KVMUFFGqe6rYRrGKgl8hxL6eakVAErPy";
    myVideoView.setVideoURI(Uri.parse(url));
    myVideoView.setMediaController(new MediaController(this));
    myVideoView.requestFocus();
}

public void gone(View v){
    myVideoView.setZOrderOnTop(true);
    View placeholder = (View) findViewById(R.id.placeholder);

    placeholder.setVisibility(View.GONE);
    myVideoView.start();
}

}

activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >

<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/videoView1"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="top|center"
        android:visibility="visible" />

    <FrameLayout
        android:id="@+id/placeholder"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="top|center"
        android:background="@drawable/ic_launcher"
        android:onClick="gone" >
    </FrameLayout>

</FrameLayout>

</LinearLayout>

Ответ 18

Используйте svVideoView.seekTo(позиция).

Укажите позицию в течение 5 (мс).

onPause():
position=svVideoView.getCurrentPosition()

onResume():
svVideoView.seekTo(position);

Ответ 19

Чтобы избежать раздражающих мерцаний и проблем с черным экраном, я написал FrameVideoView.

Это требует преимуществ от решения "placeholder" и (если ваше устройство работает на уровне API 14 или выше) от TextureView, что намного эффективнее, чем VideoView.

Я написал статью в нашем блоге, чтобы осветить то, что он на самом деле делает.

Прост в использовании:

Добавьте FrameVideoView в макет:

<mateuszklimek.framevideoview.FrameVideoView
    android:id="@+id/frame_video_view"
    android:layout_width="@dimen/video_width"
    android:layout_height="@dimen/video_height"
  />

найдите свой экземпляр в Activity и вызовите соответствующие методы в onResume и onPause:

public class SampleActivity extends Activity {

  private FrameVideoView videoView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple);

    String uriString = "android.resource://" + getPackageName() + "/" + R.raw.movie;
    videoView = (FrameVideoView) findViewById(R.id.frame_video_view);
    videoView.setup(Uri.parse(uriString), Color.GREEN);
  }

    @Override
    protected void onResume() {
      super.onResume();
      videoView.onResume();
    }

    @Override
    protected void onPause() {
      videoView.onPause();
      super.onPause();
    }
  }

Ответ 20

У меня была такая же проблема. Я обнаружил, что основной причиной этого было использование FrameLayout в качестве родительского макета. Используйте RelativeLayout в качестве родительского макета VideoView

Ответ 21

Изменение ответа @emmgfx сработало для меня:

videoView.setBackgroundColor(Color.WHITE)
videoView.start()
Timer().schedule(100){
  videoView?.setBackgroundColor(Color.TRANSPARENT)
}

Хитрость заключается в том, чтобы отложить просмотр видео до загрузки видео. PS: это котлин.

Ответ 22

см. это

VideoView videoView = (VideoView) findViewById(R.id.VideoView);
        MediaController mediaController = new MediaController(this);
        mediaController.setAnchorView(videoView);
        Uri video = Uri.parse("android.resource://your_package_name/"+R.raw.monkeysonthebed_video);

        videoView.setMediaController(mediaController);
        videoView.setVideoURI(video);
        videoView.start();