通过系统自带的摄像机可以很方便地录制视频,只要指定摄像动作为MediaStore.ACTION_VIDEO_CAPTURE即可。
当然,需要事先设定下列的录像参数:
1、MediaStore.EXTRA_VIDEO_QUALITY:用于设定视频质量;2、MediaStore.EXTRA_SIZE_LIMIT:用于设定文件大小的上限;3、MediaStore.EXTRA_DURATION_LIMIT:用于设定视频时长的上限。
// 获取视频文件中的某帧图片
public static Bitmap getOneFrame(Context ctx, Uri uri)
{MediaMetadataRetriever retriever = new MediaMetadataRetriever();retriever.setDataSource(ctx, uri);// 获得视频的播放时长,大于1秒的取第1秒的帧图,不足1秒的取第0秒的帧图String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);int pos = (Integer.parseInt(duration)/1000)>1 ? 1 : 0;// 获取并返回指定时间的帧图return retriever.getFrameAtTime(pos * 1000, MediaMetadataRetriever.OPTION_CLOSEST);}
===========================================================================================================
布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_recorder"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="打开摄像机"android:textColor="@color/black"android:textSize="17sp" /><TextViewandroid:id="@+id/tv_video"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="5dp"android:textColor="@color/black"android:textSize="17sp" /><RelativeLayoutandroid:id="@+id/rl_video"android:layout_width="match_parent"android:layout_height="300dp"android:visibility="gone"><ImageViewandroid:id="@+id/iv_video"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter" /><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter"android:src="@drawable/play_video" /></RelativeLayout></LinearLayout>
MediaUtil
package com.example.myapplication.util;import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;import java.io.File;@SuppressLint("DefaultLocale")
public class MediaUtil {private final static String TAG = "MediaUtil";// 格式化播放时长(mm:ss)public static String formatDuration(int milliseconds) {int seconds = milliseconds / 1000;int hour = seconds / 3600;int minute = seconds / 60;int second = seconds % 60;String str;if (hour > 0) {str = String.format("%02d:%02d:%02d", hour, minute, second);} else {str = String.format("%02d:%02d", minute, second);}return str;}// 获得音视频文件的缓存路径public static String getRecordFilePath(Context context, String dir_name, String extend_name) {String path = "";File recordDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + dir_name + "/");if (!recordDir.exists()) {recordDir.mkdirs();}try {File recordFile = File.createTempFile(DateUtil.getNowDateTime(), extend_name, recordDir);path = recordFile.getAbsolutePath();Log.d(TAG, "dir_name=" + dir_name + ", extend_name=" + extend_name + ", path=" + path);} catch (Exception e) {e.printStackTrace();}return path;}// 获取视频文件中的某帧图片public static Bitmap getOneFrame(Context ctx, Uri uri) {MediaMetadataRetriever retriever = new MediaMetadataRetriever();retriever.setDataSource(ctx, uri);// 获得视频的播放时长,大于1秒的取第1秒处的帧图,不足1秒的取第0秒处的帧图String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);Log.d(TAG, "duration="+duration);int pos = (Integer.parseInt(duration)/1000)>1 ? 1 : 0;// 获取指定时间的帧图,注意getFrameAtTime方法的时间单位是微秒return retriever.getFrameAtTime(pos * 1000 * 1000);}
}
主代码:
package com.example.myapplication;import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.myapplication.util.MediaUtil;public class MainActivity extends AppCompatActivity implements View.OnClickListener
{private final static String TAG = "VideoRecordActivity";private int RECORDER_CODE = 1; // 录制操作的请求码private TextView tv_video;private RelativeLayout rl_video;private ImageView iv_video;private Uri mVideoUri; // 视频文件的路径对象@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_video = findViewById(R.id.tv_video);rl_video = findViewById(R.id.rl_video);iv_video = findViewById(R.id.iv_video);findViewById(R.id.btn_recorder).setOnClickListener(this);findViewById(R.id.rl_video).setOnClickListener(this);}@Overridepublic void onClick(View v){if (v.getId() == R.id.btn_recorder){// 下面准备跳到系统的摄像机,并获得录制完的视频文件Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // 视频质量。0 低质量;1 高质量intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 10485760L); // 大小限制,单位字节intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10); // 时长限制,单位秒startActivityForResult(intent, RECORDER_CODE); // 打开系统摄像机}else if (v.getId() == R.id.rl_video){// 创建一个内容获取动作的意图(准备跳到系统播放器)Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(mVideoUri, "video/*"); // 类型为视频startActivity(intent); // 打开系统的视频播放器}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent){super.onActivityResult(requestCode, resultCode, intent);if (resultCode==RESULT_OK && requestCode==RECORDER_CODE) // 从摄像机返回{mVideoUri = intent.getData(); // 获得已录制视频的路径对象// // 生成临时视频的保存路径
// String filePath = String.format("%s/%s.mp4",
// getExternalFilesDir(Environment.DIRECTORY_MOVIES), "video_"+ DateUtil.getNowDateTime());
// // 把录制完的视频保存到临时路径
// FileUtil.saveFileFromUri(this, mVideoUri, filePath);tv_video.setText("录制完成的视频地址为:"+mVideoUri.toString());rl_video.setVisibility(View.VISIBLE);// 获取视频文件的某帧图片Bitmap bitmap = MediaUtil.getOneFrame(this, mVideoUri);iv_video.setImageBitmap(bitmap); // 设置图像视图的位图对象}}}