仅将视频加载到 VideoView 中而不立即播放
Posted
技术标签:
【中文标题】仅将视频加载到 VideoView 中而不立即播放【英文标题】:Only loading video into VideoView without instantly playing 【发布时间】:2010-07-23 08:48:26 【问题描述】:我有一个问题,是否可以在 android 中将视频数据加载到 VideoView
而不立即开始播放?如果是这样,我该怎么做?
【问题讨论】:
【参考方案1】:我也在考虑像 sghael 所说的那样显示一个缩略图。但我认为这可能会导致性能下降。
所以我现在做的就是打电话
videoView.seekTo(1);
将视频转发到第一毫秒。这对我来说很好,而且实施起来很快。
【讨论】:
这不起作用,因为视频必须处于播放状态。seekTo(1)
对我来说似乎很重要。如果没有搜索,我的视频将显示一个随机帧,通常是 1 秒后的帧,在我调用 start()
的一开始【参考方案2】:
我还希望我的 VideoView 在活动开始时处于暂停状态。我找不到让 VideoView 显示视频的第一帧(非黑色)的简单方法。
作为一种解决方法,我从视频资源创建了一个位图缩略图,然后在活动开始时将该缩略图作为 VideoView 的背景。然后当视频开始播放时,您只需要将背景清空(否则您正在播放的视频会隐藏在背景图像后面)。
Bitmap thumbAsBitmap = null;
BitmapDrawable thumbAsDrawable = null;
private String current;
private void setupVideo()
try
setVideoFilePath();
if (current == null || current.length() == 0)
Toast.makeText(PreviewMessage.this, "File URL/path is empty",
Toast.LENGTH_LONG).show();
else
keepScreenOn();
mVideoView.setVideoPath(getDataSource(current));
mVideoView.setOnCompletionListener(this);
// create and place a thumbnail for the start state
thumbAsBitmap = ThumbnailUtils.createVideoThumbnail(current, MediaStore.Images.Thumbnails.MINI_KIND);
thumbAsDrawable = new BitmapDrawable(thumbAsBitmap);
mVideoView.setBackgroundDrawable(thumbAsDrawable);
mVideoView.pause();
isPlaying = false;
catch (Exception e)
if (mVideoView != null)
mVideoView.stopPlayback();
那么无论你的播放按钮在哪里,你都可以做类似的事情
mPlay.setOnClickListener(new OnClickListener()
public void onClick(View view)
if(!isPlaying)
keepScreenOn();
mPlay.setText("Pause");
// make sure to null the background so you can see your video play
mVideoView.setBackgroundDrawable(null);
mVideoView.start();
isPlaying = true;
else
mPlay.setText("Play");
mVideoView.pause();
isPlaying = false;
);
【讨论】:
【参考方案3】:VideoView
不会自动开始播放,至少如果您附加了MediaController
。您需要拨打start()
让它开始播放。因此,如果您不想让它开始播放,请不要拨打start()
。
【讨论】:
我现在唯一遇到的问题是视频根本没有显示在视图中,我的意思是我希望它显示(仅第一帧)并具有控件(播放/暂停、停止、前进和后退)就在它下面...MediaController
是一个弹出窗口——用户必须点击您的VideoView
才能出现。如果您想要始终可见的控件,您可能必须自己做。有关使用 MediaPlayer
和带有自定义“控制器”面板的 SurfaceView
的项目,请参阅 github.com/commonsguy/vidtry。关于第一帧,除了开始播放之外,您无法强制显示该帧,AFAIK。
我如何知道视频何时加载?所以,我可以处理一些其他动作或向用户展示一些东西。
@xaif:我不知道你认为“加载”是什么意思,但有developer.android.com/reference/android/widget/…【参考方案4】:
我发现仅使用VideoView.seekTo(n)
不足以在所有设备上显示视频的第一帧。
如果您只需要显示第一帧,而不是播放视频,那么您可以这样做,这有助于渲染视频的缩略图:
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(context, uri);
Bitmap firstFrame = MediaMetadataRetriever.getFrameAtTime(0);
// Set firstFrame bitmap to ImageView...
但是,为了在您希望在渲染后的某个时间点播放视频(例如来自用户交互)时可靠地显示第一帧,我的解决方案是注册一个OnPreparedListener
,然后调用start()
。我还注册了OnInfoListener
,以便在渲染开始时收到通知。然后我检查该信息是否确实是“渲染开始”事件,并检查这是否是VideoView
第一次开始渲染。如果是这样,我pause()
然后seekTo(0)
。
如下所示:
private void showFirstFrame(final VideoView videoView, Uri uri)
videoView.setVideoURI(uri);
final AtomicBoolean showedFirstFrame = new AtomicBoolean(false);
videoView.setOnInfoListener(new MediaPlayer.OnInfoListener()
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra)
// If this is our first time starting video rendering, pause and show first frame
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START
&& showedFirstFrame.compareAndSet(false, true))
videoView.pause();
videoView.seekTo(0);
return false;
);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
@Override
public void onPrepared(MediaPlayer mp)
videoView.start();
);
【讨论】:
【参考方案5】:我使用 MediaController 作为我的播放按钮,所以我使用下面的链接答案结合这个背景位图作为我的解决方案。
Event for VideoView playback state or MediaController play/pause
【讨论】:
【参考方案6】:我发现可以通过启动视频,等待 1 毫秒并暂停:
mediaController = new MediaController(this);
//set the path for video here
Uri video = Uri.parse(tempPath);
//set the VideoView id in xml file here
vv_item = (VideoView) findViewById(R.id.itemdetails_vv_item);
vv_item.setMediaController(mediaController);
vv_item.setVideoURI(video);
vv_item.setOnPreparedListener(new OnPreparedListener()
public void onPrepared(MediaPlayer mp)
//first starting the video, when loaded
vv_item.start();
//then waiting for 1 millisecond
try
Thread.sleep(1);
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
//then pausing the video. i guess it's the first frame
vv_item.pause();
//showing the control buttons here
mediaController.show();
);
【讨论】:
【参考方案7】:我建议您使用以下代码,其中我正在成功运行我的应用程序
代码如下:
XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:background="#f0f0f0" >
<Button
android:id="@+id/btnVideoGallery"
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:text="@string/gallery" />
<Button
android:id="@+id/btnCancel"
android:layout_
android:layout_
android:layout_below="@+id/btnVideoGallery"
android:layout_centerHorizontal="true"
android:layout_marginTop="22dp"
android:text="@string/cancel" />
<TextView
android:id="@+id/lblDisplayImage"
android:layout_
android:layout_
android:layout_below="@+id/btnCancel"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="@string/below_this_text_video_will_be_displayed"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#000000"
android:textSize="13dp" />
<VideoView
android:id="@+id/vvDisplayVideo"
android:layout_
android:layout_
android:layout_below="@+id/lblDisplayImage"
android:layout_marginTop="15dp" />
</RelativeLayout>
Java 文件:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.VideoView;
public class VideoActivity extends Activity
private Button btnVideoGallery,btnCancel;
private VideoView vvDisplayVideo;
/** The Constant PICK_VIDEO. */
private static final int PICK_VIDEO=1;
@Override
protected void onCreate(Bundle savedInstanceState)
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_options);
btnVideoGallery=(Button)findViewById(R.id.btnVideoGallery);
vvDisplayVideo=(VideoView)findViewById(R.id.vvDisplayVideo);
btnCancel=(Button)findViewById(R.id.btnCancel);
vvDisplayVideo.setVisibility(View.GONE);
btnVideoGallery.setOnClickListener(new OnClickListener()
public void onClick(View v)
Intent video=new Intent();
video.setAction(Intent.ACTION_PICK);
video.setType("video/*");
startActivityForResult(video, PICK_VIDEO);
);
btnCancel.setOnClickListener(new OnClickListener()
public void onClick(View v)
Intent goStartUp=new Intent(VideoActivity.this, StartUpActivity.class);
goStartUp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(goStartUp);
finish();
);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
// TODO Auto-generated method stub
if (resultCode==Activity.RESULT_OK && requestCode == PICK_VIDEO)
vvDisplayVideo.setVisibility(View.VISIBLE);
vvDisplayVideo.setVideoURI(data.getData());
vvDisplayVideo.setFocusable(true);
MediaController mc=new MediaController(this);
vvDisplayVideo.setMediaController(mc);
Log.i("True", "Executed");
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
// TODO Auto-generated method stub
Intent goStartUp=new Intent(VideoActivity.this, StartUpActivity.class);
goStartUp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(goStartUp);
finish();
return super.onKeyDown(keyCode, event);
您也可以根据自己的用途修改清单文件:
<manifest>
...
<uses-sdk... />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_VIDEO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application>...</application>
</manifest>
【讨论】:
以上是关于仅将视频加载到 VideoView 中而不立即播放的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Android 中的 VideoView 需要花费太多时间来加载和播放来自 http 链接的视频?