アクティビティでVideoView
を作成しました。以下はコードです。
VideoView vvVideos = (VideoView) rootView.findViewById(R.id.videoView);
MediaController mediacontroller = new MediaController(ctx);
mediacontroller.setAnchorView(vvVideos);
Uri video = Uri.parse("Android.resource://" + packageName +"/"+R.raw.sample);
vvVideos.setMediaController(mediacontroller);
LayoutParams params=vvVideos.getLayoutParams();
params.height=150;
vvVideos.setLayoutParams(params);
vvVideos.setVideoURI(video);
vvVideos.requestFocus();
vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
vvVideos.start();
}
});
アクティビティが作成されると、ビデオの再生が開始されます。次のように活動したい
seekTo( 1 )
を使用して、最初のフレームを表示します。ムービーが一時停止していることを確認してから、seekTo()
を使用してビデオの最初のフレームを表示します。
_VideoView mVideoView = (VideoView) findViewById( R.id.video_preview );
mVideoView.setVideoURI( yourVideoPath );
mVideoView.seekTo( 1 ); // 1 millisecond (0.001 s) into the clip.
_
注:.seekTo( 1 )
の設定はAndroid 9。では機能しなかったため、.seekTo( 0 )
を使用します。
クリックされたときに再生するには、別の回答で@Lingvistonが回答しています。
これを使用してビデオのサムネイルを作成します
Bitmap thumb = ThumbnailUtils.createVideoThumbnail("file path/url",
MediaStore.Images.Thumbnails.MINI_KIND);
そして、videoviewに設定します
BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
mVideoView.setBackgroundDrawable(bitmapDrawable);
1)onPrepareListenerを削除します。アクティビティの作成後に動画の再生が開始される理由はわかりませんが、onViewpareListenerはvideoView.start()の後に呼び出されます。
2)VideoViewの上にあるレイアウトにImageViewウィジェットを追加します。次に、次のように別のonPrepareListenerを設定します。
_vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
previewImage.setVisibility(View.GONE);
}
});
_
OnPreparedListenerの起動が早すぎることに気付いたので、
new Handler().postDelay(Runnable, timeInMilis)
プレビュー画像を閉じます。
3)OnTouchListenerをジェスチャー検出とともにVideoViewに追加します。私が今使用しているものの例を次に示します。
_ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
mGestureDetector = new GestureDetector(this, mGestureListener);
((VideoView) findViewById(R.id.activity_video_videoview)).setOnTouchListener(mTouchListener);
}
private OnTouchListener mTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return true;
}
};
private SimpleOnGestureListener mGestureListener = new SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if(mVideoView.isPlaying())
mVideoView.pause();
else
mVideoView.start();
return true;
};
};
_
タップで再生を開始/停止します。
ビデオを100ミリ秒までシークするだけで、seekTo()メソッドを使用してサムネイルを表示します。
videoView.seekTo(100);
Glide 4.x
でできます。ビデオの最初のフレームを取得し、ImageView
で表示します
build.gradle
に追加します
implementation 'com.github.bumptech.glide:glide:4.x.x'
そしてあなたのクラスで
GlideApp.with(context)
.load("your video URL")
.into(videoImageView);;
私のソリューションを共有すると思いました。 seekTo
メソッドはうまく機能しますが、一部のデバイスでのみ機能します。これが私の回避策です。これはonPreparedListenerのonPreparedメソッドで処理しますが、それはあなた次第です。
@Override
public void onPrepared(MediaPlayer mp) {
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(uri.getPath());
try {
Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(currentPosition);
videoView.setBackgroundDrawable(new BitmapDrawable(bitmap));
} catch (OutOfMemoryError outOfMemoryError) {
//Not entirely sure if this will ever be thrown but better safe than sorry.
videoView.seekTo(currentPosition);
}
}
ビデオを再生するとき、次のようにこの背景画像を削除する必要があります。
private void play() {
...
videoView.setBackgroundDrawable(null);
..
}
楽しい!
私はそれが古い質問であることを知っていますが、同じ解決策が必要であり、他のどこにも答えを見つけることができなかったので、解決策を行い、ここで愛を共有しています:
ちょっとしたクラスを作成しました。
_ public class LoadFirstVideoFrame implements Runnable {
private static Handler uiHandler = new Handler(Looper.getMainLooper());
private VideoView videoView;
private LoadFirstVideoFrame(VideoView videoView) {
this.videoView = videoView;
videoView.start();
videoView.resume();
uiHandler.post(this);
}
public void stop() {
videoView = null;
uiHandler.removeCallbacks(this);
}
@Override public void run() {
if (videoView == null) return;
if (videoView.isPlaying()) {
videoView.pause();
videoView.seekTo(0);
videoView = null;
} else {
uiHandler.post(this);
}
}
}
_
単に再生を開始するよう要求し、実際に再生されるとすぐに最初のフレームでビデオを一時停止します(つまり、ファイルをロードし、SurfaceViewで既にレンダリングしていることを意味します)。
ここでの重要な注意点は、このクラスでstop()
を呼び出すことを忘れないでください。そうすれば、適切にクリーンアップでき、メモリリークは発生しません。
役に立てば幸いです。
このようなサムネイル用のImageViewを作成しました
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/white"
Android:clickable="true"
Android:focusable="true">
<VideoView
Android:id="@+id/video_view"
Android:layout_width="match_parent"
Android:layout_height="220dp"/>
<ImageView
Android:id="@+id/videoView_thumbnail"
Android:layout_width="match_parent"
Android:layout_height="220dp"
Android:scaleType="centerCrop"/>
</RelativeLayout>
そして、setOnPreparedListenerとsetOnCompletionListenerをJava Like This Wayに追加
VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
ImageView thumbnailView=(ImageView)view.findViewById(R.id.videoView_thumbnail);
Glide.with(getApplicationContext()).load(your_Image_Path).into(thumbnailView);
//you can add progress dialog here until video is start playing;
mediaController= new MediaController(getContext());
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setKeepScreenOn(true);
videoView.setVideoPath(your_video_path);
videoView.start(); //call this method for auto playing video
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
thumbnailView.setVisibility(View.GONE);
//you can Hide progress dialog here when video is start playing;
}
});
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
videoView.stopPlayback();
thumbnailView.setVisibility(View.VISIBLE);
}
});
それは私のために非常にうまく機能します
@Joshua Pinterの回答を使用して問題を解決できます。しかし、私はそれについてより多くの提案をしたいと思います。あなたは、seekTo(100)
の代わりにseekTo(1)
が機能すると答えます。どちらの方法も完璧ではありません。 seekTo(1)
が黒い画像を取得し、seekTo(100)
が例外を取得する可能性があるためです。
私はこのようにすることを好む:
// calculate the during time of the media
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
long time = mediaPlayer.getDuration();
// use a proper number
mVideoView.seekTo(time/2);
バックエンドサーバーがない場合は、より良い可能性があります。または、バックエンドサーバーがある場合は、この方法で試すことができます。
サムネイルはサーバーによって計算され、クライアントはバックエンドが応答する画像を表示するだけです。そして、サーバー側に来るとき、あなたは多くのことをすることができます。
2つの質問について詳しく話したい場合は、後で説明します。