Черный экран 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);
Ответы
Ответ 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(), я думаю.
Ответ 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();