我有一个问题,是否可以在 Android 中将视频数据加载到 a 中VideoView
而不立即开始播放?如果是这样,我该怎么做?
7 回答
正如 sghael 所说,我还在考虑展示一个缩略图。但我认为这可能会导致性能下降。
所以我现在做的就是打电话
videoView.seekTo(1);
将视频转发到第一毫秒。这对我来说很好,并且可以快速实施。
I also wanted my VideoView to be in a paused state when the activity started. I could not find a simple way to have the VideoView show the first (non-black) frame of the video.
As a workaround, I created a bitmap thumbnail from the video resource, and then place that thumbnail as the background to the VideoView on activity start. Then when the Video begins playing, you only need to null out the background (or else your playing video is hidden behind your background image).
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();
}
}
}
Then whereever your playbutton is, you can do something like
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;
}
}
});
VideoView
不会自动开始播放,至少如果你有一个MediaController
附件。你需要打电话start()
让它开始播放。因此,如果您不希望它开始播放,请不要调用start()
.
我发现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();
}
});
}
I suggest you for the following Code wherein I am running my application successfully
The Code is as Follows:
XML file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f0f0f0" >
<Button
android:id="@+id/btnVideoGallery"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:text="@string/gallery" />
<Button
android:id="@+id/btnCancel"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@+id/btnVideoGallery"
android:layout_centerHorizontal="true"
android:layout_marginTop="22dp"
android:text="@string/cancel" />
<TextView
android:id="@+id/lblDisplayImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/lblDisplayImage"
android:layout_marginTop="15dp" />
</RelativeLayout>
Java File:
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);
}
}
Also you can modify the Manifest File as per your use:
<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>
我发现可以通过启动视频,等待 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();
}
});
我使用 MediaController 作为我的播放按钮,所以我使用下面的链接答案结合这个背景位图作为我的解决方案。