VideoView播放前后黑闪

发布于 2024-10-05 18:58:28 字数 306 浏览 0 评论 0原文

我有一个 VideoView,我想用它来播放影片剪辑。我像这样使用它来播放它并且它有效。

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

然而,我在影片剪辑之前和之后看到黑色闪光。闪光灯本身并不是一个大问题,但它的黑色才是大问题。背景是白色的,所以如果闪光是白色的,或者如果它消失了,那就没问题了。

I have a VideoView which I want to use to play a movieclip. I use it like this to play it and it works.

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

However I see a black flash just before and after the movie clip. The flash in itself isn't a big problem, but the blackness of it is. The background is white, so if the flash is white, or if it dissapears it will be okay.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

自演自醉 2024-10-12 18:58:29

我遇到了同样的问题,这对我有用..

当你想显示视频时, make videoView.setZOrderOnTop(false);当你想隐藏视频视图时,只需制作 videoView.setZOrderOnTop(true);

I had same problem this has worked for me ..

When you want to show video make videoView.setZOrderOnTop(false); and when you want to hide video view just make videoView.setZOrderOnTop(true);

抽个烟儿 2024-10-12 18:58:29

试试这条线。这对我有用。 if(player!=null)player.release();

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

 }

Try this line.This worked for me. if(player!=null)player.release();

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

 }
走走停停 2024-10-12 18:58:28

今天我遇到了同样的问题,并针对这个令人讨厌的问题找到了一个非常糟糕且古怪的解决方法:我意识到可以在 VideoView 上设置背景颜色/可绘制内容,它会混合在视频表面上并使其完全混合隐。这仅在底层视频仍在播放时有效,而不是在停止时有效(无论是正常结束时还是调用 stopPlayback() 时),否则您会再次看到黑色闪烁。背景也不能在一开始就设置,否则视频从一开始就会被完全隐藏。

因此,对我来说唯一合乎逻辑的步骤是在开始视频之前发布延迟事件 - 由于我知道视频长度,因此我让该事件在正常结束之前发生几毫秒。我在 VLC 中截取了最后一帧的屏幕截图,然后像这样混合它:

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

但这还不够,因为当视频实际结束时,我仍然有短暂的黑屏闪烁,所以我还必须将静止图像设置为背景包含视频的容器的尺寸(在我的例子中,它是活动的布局):

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

此活动以全屏呈现,并且视频(大部分)缩放到总屏幕尺寸(屏幕 1024x600,视频 960x640)。我说大部分,因为由于某种未知的原因,布局的背景图像在顶部混合了大约 10 像素。这是我必须应用的最后一个技巧才能使其发挥作用 - 将视频容器 -10dip 移动到顶部的空白处。

现在,这在我的 Galaxy Tab 上看起来棒极了,但我不敢在 SGS2 手机上测试它......

Today I had the same problem and found a very bad and hacky workaround for this nasty problem: I realized that one can set a background color / drawable onto the VideoView which blends over the video surface and makes it completely hidden. This only works though while the underlying video is still playing, not when it is stopped (neither when it ended normally nor when stopPlayback() was called), otherwise you'd again see a black flicker. The background must also not be set in the beginning, otherwise the video would be completely hidden right from the start.

So the only logical step for me was to post a delayed event just before I start the video - and since I know the video length, I let this event happen just a few milliseconds before it ends normally. I took a screenshot of the last frame in VLC and then blended it like this:

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

This however was not enough, because when the video actually ended, I still got a short black screen flicker, so I also had to set the still image as background of the container that contained the video (in my case it was the layout of the activity):

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

This activity is rendered in fullscreen and the video is (mostly) scaled to the total screen size (screen 1024x600, video 960x640). I say mostly, because for some unknown reason the layout's background image blends through for about 10px on top. This was the last hack I had to apply to make it work - move the video container -10dip into the void on top.

This now looks awesome on my Galaxy Tab, I don't dare to test it on the SGS2 phone, though...

你如我软肋 2024-10-12 18:58:28

我最终不得不做一些与@tommyd非常相似的事情来避免视频开头和结尾处出现黑色的surfaceView闪烁。然而,我发现在许多手机上设置/清空 videoView 的背景可绘制元素并不会立即发生。我设置背景的调用和实际显示背景之间可能有大约半秒的延迟。

我最终做的是创建一个显示单一纯色的自定义 SurfaceView,然后将其覆盖在 VideoView 之上并使用 SurfaceView.setZOrderMediaOverlay()。

我的自定义 SurfaceView 很大程度上受以下因素影响:
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);
                    }
                }
            }
        }
    }
}

在托管视图的父活动中:

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

然后您可以执行诸如 mVideoMask.setVisibility(View.GONE) 之类的操作来隐藏遮罩或 mVideoMask.setVisibility (View.VISIBLE) 显示遮罩(并隐藏黑屏的 VideoView)。

在我在各种手机上进行的实验中,这种方法提供了非常快速的视频蒙版显示/隐藏,而不是设置/清空背景。

I ended up having to do something very similar to @tommyd to avoid the black surfaceView flash at the beginning and end of my videos. However, I found that setting/nulling the background drawable for the videoView was not occurring instantly on many phones. There could be about a half-second delay between my call to set the background and when it was actually displayed.

What I ended up doing was creating a custom SurfaceView that showed a single, solid color, then overlayed this on top of the VideoView and made use of SurfaceView.setZOrderMediaOverlay().

My custom SurfaceView was heavily informed by:
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);
                    }
                }
            }
        }
    }
}

And in the parent activity that hosts the views:

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

You can then do things like mVideoMask.setVisibility(View.GONE) to hide the mask or mVideoMask.setVisibility(View.VISIBLE) to show the mask (and hide the black-screened VideoView).

In my experiments on various phones, this method provided very fast showing/hiding of the video mask, as opposed to setting/nulling the background.

南烟 2024-10-12 18:58:28

我遇到了同样的问题,白色而不是黑色对我来说没问题。我尝试了上面所有的解决方案,我想出了以下方法

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

,并将我的视频延迟了 400 毫秒,开始从白色褪色,这对我来说就像一个魅力

i had the same problem and white instead of black was ok for me.. i tried all of solutions above i came up with the following

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

and delayed my video 400 ms start fading from white works like a charm for me

最终幸福 2024-10-12 18:58:28

我对 @tommyd 主题的变体:

将可绘制对象设置为静态视频帧,然后向消息队列发送垃圾邮件。一段时间后,清除可绘制对象,以便渲染视频帧。然后,在完成之前,将静态图像设置回去。

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

My variation on the @tommyd theme:

Set the drawable to a static video frame, then spam the message queue. After some time, clear the drawable so video frames render. Then, before completion, set the static image back.

    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);
绝不放开 2024-10-12 18:58:28

这是一个简单的技巧,

检查视频视图准备好的侦听器中的条件 media player.getCurrentPosition == 0 ,当位置为零时会出现黑屏,因此显示图像直到视频加载

我的代码:

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;
                            }
                        }

                    }
                });
            }
        }
    });

here is simple trick

check the condition media player.getCurrentPosition == 0 in on prepared listener of video view ,black screen will appear when position is zero so display an image untill the video will load

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;
                            }
                        }

                    }
                });
            }
        }
    });
羁绊已千年 2024-10-12 18:58:28

我针对这个可怕的错误的解决方法是使用一个空白视图,并在 VideoView 顶部选择背景颜色。

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

然后在我的代码中我这样做了:

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

这为我摆脱了开始的黑色闪光。然后对于最后的黑色闪光,我这样做了:

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

My workaround for this diabolical bug utilised a blank View with the background colour of choice over the top of the VideoView.

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

then in my code I did this:

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

That got rid of the beginning black flash for me. Then for the end black flash, I did this:

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);    
}
千秋岁 2024-10-12 18:58:28

该闪光来自将当前内容视图更改为另一视图。您可以尝试将 VideoView 添加到布局 xml 文件中,然后使用 (VideoView) findViewById(R.id.vid); 引用它,而不是 new VideoView(this); 和将内容视图设置为该布局。

That flash comes from changing the current content view to another one. You could try adding a VideoView to your layout xml file then referencing it with (VideoView) findViewById(R.id.vid); instead of new VideoView(this); and setting the content view to that layout.

束缚m 2024-10-12 18:58:28

为什么不使用样式和主题

你能尝试一下吗?这可能有助于

color.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>

要为应用程序的所有活动设置主题,请打开 AndroidManifest.xml 文件并编辑标签以包含带有样式名称的 android:theme 属性。

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

Why not using Styling and Themes

Can you try this ? This might help

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>

To set a theme for all the activities of your application, open the AndroidManifest.xml file and edit the tag to include the android:theme attribute with the style name.

<application android:theme="@style/Transparent">
浅紫色的梦幻 2024-10-12 18:58:28

你在哪里更改contentView(上面四行代码是在哪个方法中编写的)?

您应该只在 ActivityonCreate() 方法中设置 contentView。如果您在其他地方执行此操作(例如在按钮的回调中),则应该开始一个新的活动。

Where are you changing the contentView (in which method did you write the four lines of code above)?

You should only set the contentView in the onCreate() method of an Activity. If you are doing it somewhere else (for exemple in a button’s callback), you should start a new activity instead.

北风几吹夏 2024-10-12 18:58:28

您可以使用媒体控制器来实现此目的。这是示例代码

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

试试这个。

There is one alternative that you are use media controller for this. Here is sample code

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

Try this.

灼痛 2024-10-12 18:58:28

另一个可能适用于搜索此问题的人的解决方案:

在我的例子中,视频是应用程序中的资源(也就是说,我知道有关它的一切并且不会改变),并且它的最后 500 毫秒是同一帧,所以我最终执行了以下操作:

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

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

引用的类是:

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

说明:在启动视频后,我立即创建一个 Runnable 和 postDelayed 将其发送到根视图 (android.R.id.content)到视频的持续时间,减去我愿意暂停视频的长度(以及足够的缓冲区,因为 postDelayed 不能保证在请求的时间之后完全播放)

然后, runnable 检查视频是否到达其暂停时间,如果是,则暂停并执行我们希望它执行的其他操作。如果没有,它会再次自行运行 postDelayed,时间会缩短(在我的例子中为 100 毫秒,但可能更短)

当然,这远不是一个理想的解决方案,但它可能帮助某人解决与困扰我半天的问题类似的特定问题:)

Another solution that might work for people who are searching for this question:

In my case, the video was a resource in the app (that is, I knew everything about it and it wasn't going to change) and its last 500 ms were the same frame, so I ended up doing the following:

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

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

and the referenced class is:

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

Explanation: Immediately after starting the video I create a Runnable and postDelayed it to the root view (android.R.id.content) to the duration of the video, minus the length at which I'm willing to pause the video (and a generous buffer, because postDelayed isn't guaranteed to play exactly after the requested time)

Then, the runnable checks if the video arrived at its pause-time, if so it pauses it and does whatever else we want it to do. If it doesn't, it runs postDelayed again with itself, for a shortened time (100 ms in my case, but could be shorter)

Granted, this is far from being an ideal solution, but it might help someone with a specific problem similar to the one that stumbled me for half a day :)

迷雾森÷林ヴ 2024-10-12 18:58:28

我知道这是一个老问题,但如果您可以向 MediaPlayer 侦听器添加一些代码,那么答案就非常简单。事实证明,VideoView 的 setBackgroundColor 更改了前景色( https: //groups.google.com/forum/?fromgroups=#!topic/android-developers/B8CEC64qYhQ )。
所以你唯一要做的就是在 setBackgroundColor(Color.WHITE) 和 setBackgroundColor(Color.TRANSPARENT) 之间切换。

I know it's old question but if you can add some code to MediaPlayer listeners there is very simple answer. It turned out that setBackgroundColor for VideoView changes the foreground color ( https://groups.google.com/forum/?fromgroups=#!topic/android-developers/B8CEC64qYhQ ).
So the only thing you have to do is switching between setBackgroundColor(Color.WHITE) and setBackgroundColor(Color.TRANSPARENT).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文