Androidで、VideoView
すぐに再生を開始せずにビデオデータをにロードすることは可能ですか?もしそうなら、どうすればそれを行うことができますか?
7 に答える
sghaelが言ったように、私はサンブネイルを見せることも考えていました。ただし、これによりパフォーマンスが低下する可能性があると思います。
だから私が今しているのはただ電話することです
videoView.seekTo(1);
ビデオを最初のミリ秒に転送します。これは私にとっては問題なく機能し、実装も高速です。
また、アクティビティの開始時に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;
}
}
});
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();
}
});
}
再生ボタンにMediaControllerを使用していたので、以下のリンク回答をこの背景ビットマップと組み合わせてソリューションに使用しました。
アプリケーションを正常に実行している次のコードをお勧めします
コードは次のとおりです。
XMLファイル:
<?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ファイル:
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>
ビデオを開始し、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();
}
});