1.界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_video_recorder"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/liveBack"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@mipmap/icon_back"
/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_below="@+id/ll_video_recorder">
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|center"
/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/colorPrimary"
android:layout_marginBottom="10dp"
android:textSize="20sp"
android:text="00:00:00"
android:layout_gravity="right|top"
/>
<ImageView
android:id="@+id/fl_video_priview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_video_grid"
android:layout_gravity="center"
android:visibility="gone"/>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/black"
>
<Button
android:id="@+id/start"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:background="@drawable/shape_circle1"
/>
<Button
android:id="@+id/stop"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:background="@mipmap/video_record_stop"
android:visibility="gone"/>
<Button
android:id="@+id/save1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_margin="20dp"
android:text="确定"
android:textColor="@color/white"
android:background="@drawable/shape_circle"
android:textSize="20sp"
android:visibility="gone"
/>
<Button
android:id="@+id/cancel1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_margin="20dp"
android:text="取消"
android:textColor="@color/white"
android:textSize="20sp"
android:background="@drawable/shape_circle"
android:visibility="gone"
/>
</RelativeLayout>
</LinearLayout>
2.录制Activity
import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.SensorManager;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import butterknife.BindView;
import butterknife.ButterKnife;
public class VideoRecoderActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener,View.OnTouchListener, MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
/**
* 保存
*/
@BindView(R.id.save1)
Button save1;
/**
* 取消
*/
@BindView(R.id.cancel1)
Button cancel;
/**
* 开始录制按钮
*/
@BindView(R.id.start)
Button start;
/**
* 停止录制按钮
*/
@BindView(R.id.stop)
Button stop;
/**
* 显示录制时间
*/
@BindView(R.id.time)
TextView time;
/**
* 返回
*/
@BindView(R.id.liveBack)
ImageView back;
/**
* 显示视频的控件
*/
@BindView(R.id.surfaceview)
SurfaceView surfaceview;
private MediaRecorder mediarecorder;// 录制视频的类
private SurfaceHolder surfaceHolder;
private String videoPath = null;
private boolean previewRunning = true;
public static int RESULT_VIDEO_CODE1 = 4001;
/**
* 计时器
*/
private long mlCount = 0;
private Timer timer = null;
private TimerTask task = null;
private Handler handler = null;
private Message msg = null;
private Camera camera = null;
private boolean isRecording; // 记录是否正在录像,fasle为未录像, true 为正在录像
private boolean storage1;
private final static int CAMERA_ID = 0;
private boolean mIsSufaceCreated = false;
// private int mWidth;// 视频分辨率宽度
// private int mHeight;// 视频分辨率高度
// private Context context;
private Camera.Parameters params;
private Timer mTimer;
private TimerTask mTimerTask;
private Camera.AutoFocusCallback mAutoFocusCallback;
private Camera.PreviewCallback previewCallback;
private boolean isVideoAuto = true;//是否自动聚焦
/**定义一个常量值*/
private static final int SENSOR_VALUE = 100;
/**SensorManager对象*/
private SensorManager mSensorManager;
/**Vibrator对象*/
private Vibrator mVibrator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
// 选择支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.activity_video_recoder);
ButterKnife.bind(this);
init();
initTime();
storage1 = Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
if (storage1) {
start.setOnClickListener(this);
stop.setOnClickListener(this);
save1.setOnClickListener(this);
cancel.setOnClickListener(this);
back.setOnClickListener(this);
}
}
private void init() {
surfaceview.setZOrderOnTop(true);
surfaceview.setZOrderMediaOverlay(true);
surfaceHolder = surfaceview.getHolder();// 取得surfaceHolder
surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
// setType必须设置,要不出错.
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this); // surfaceHolder加入回调接口
//自动聚焦回调
mAutoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
// isAutoFocus = true;
// camera.setOneShotPreviewCallback(null);
}
else {
mTimerTask.run();
}
}
};
//自动聚焦定时器
mTimer = new Timer();
mTimerTask = new TimerTask() {
@Override
public void run() {
if (camera != null) {
camera.autoFocus(mAutoFocusCallback);
}
}
};
mTimer.schedule(mTimerTask, 0, 5000);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:// 开始录制
startTakeVideo();
break;
case R.id.stop:// 停止
stopTakeVideo();
break;
case R.id.save1:// 确定
File f = new File(videoPath);
long size1 = getFileSize(f);
Intent intent1 = new Intent(VideoRecoderActivity.this, MainActivity.class);
Bundle bundle = new Bundle();
bundle.putString("path", videoPath);
intent1.putExtras(bundle);
setResult(RESULT_VIDEO_CODE1, intent1);
finish();
break;
case R.id.cancel1: // 取消
File f1 = new File(videoPath);
FileUtil.deleteFile(f1);
videoPath = null;
start.setVisibility(View.VISIBLE);
stop.setVisibility(View.GONE);
save1.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
time.setVisibility(View.GONE);
break;
case R.id.liveBack:// 返回
if (videoPath != null) {
File f2 = new File(videoPath);
deleteFile(f2);
videoPath = null;
}
finish();
break;
}
}
/**
* 获取指定文件大小
* @param
* @return
* @throws Exception
*/
private long getFileSize(File file) {
long size = 0;
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
size = fis.available();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return size;
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
try {
if (mr != null)
mr.reset();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void startTakeVideo() {
initMediaRecorder();
try {
// 准备录制
mediarecorder.prepare();
mediarecorder.setOnInfoListener(VideoRecoderActivity.this);
mediarecorder.setOnErrorListener(VideoRecoderActivity.this);
// 开始录制
mediarecorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
initTime();
time.setVisibility(View.VISIBLE);
if (null == timer) {
if (null == task) {
task = new TimerTask() {
@Override
public void run() {
if (null == msg) {
msg = new Message();
} else {
msg = Message.obtain();
}
msg.what = 1;
handler.sendEmptyMessageDelayed(0,2000);
handler.sendMessage(msg);
}
};
}
timer = new Timer(true);
timer.schedule(task, 1000, 1000);
}
start.setVisibility(View.GONE);
stop.setVisibility(View.VISIBLE);
save1.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
}
private void initMediaRecorder() {
mediarecorder = new MediaRecorder();//实例化
if (camera != null) {
camera.unlock();
}
//给Recorder设置Camera对象,保证录像跟预览的方向保持一致
mediarecorder.setCamera(camera);
mediarecorder.setOrientationHint(90); //改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)
mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置从麦克风采集声音
// mediarecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从摄像头采集图像
mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置视频的输出格式 为MP4
mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // 设置音频的编码格式
mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频的编码格式
mediarecorder.setVideoSize(640, 480); // 设置视频大小(不同手机的分辨率不同,4.0 版本 (176,144))
// mediarecorder.setVideoFrameRate(20); // 设置帧率
mediarecorder.setVideoEncodingBitRate(5 * 1024 * 1024);// 设置帧频率,然后就清晰了
// mRecorder.setMaxDuration(10000); //设置最大录像时间为10s
mediarecorder.setPreviewDisplay(surfaceHolder.getSurface());
//设置视频存储路径
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "VideoRecorder");
if (!file.exists()) {
//多级文件夹的创建
file.mkdirs();
}
videoPath = file.getPath() + File.separator + "VID_" + System.currentTimeMillis() + ".mp4";
mediarecorder.setOutputFile(videoPath);
}
private void stopTakeVideo() {
stop.setVisibility(View.GONE);
start.setVisibility(View.GONE);
save1.setVisibility(View.VISIBLE);
cancel.setVisibility(View.VISIBLE);
//设置后不会崩
if (mediarecorder != null) {
// 停止录制
mediarecorder.stop();
// 释放资源
mediarecorder.release();
mediarecorder = null;
}
task.cancel();
task = null;
timer.cancel();
timer.purge();
timer = null;
handler.removeMessages(msg.what);
if (camera != null) {
camera.lock();
}
camera.stopPreview();
}
private void initTime() {
mlCount = 0;
time.setVisibility(View.VISIBLE);
time.setText("00:00:00");
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
mlCount++;
int totalSec = 0;
totalSec = (int) (mlCount);
// Set time display
int hor = (totalSec / 3600);
int min = (totalSec / 60);
if (min >= 60) {
min = (totalSec - hor * 3600) / 60;
}
int sec = (totalSec % 60);
try {
// second(1000ms)
time.setText(String.format("%1$02d:%2$02d:%3$02d", hor, min, sec));
} catch (Exception e) {
time.setText("" + hor + ":" + min + ":" + sec);
e.printStackTrace();
}
break;
default:
break;
}
super.handleMessage(msg);
}
};
}
/**
* 释放摄像头资源
*/
private void freeCameraResource() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.lock();
camera.release();
camera = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (camera != null && !mIsSufaceCreated) {
return;
}
// Camera.Size size = getBestPreviewSize(width,height, params);
// if (size != null) {
// // 在使用摄像头支持的最大分辨率进行拍摄的时候会出现stop failed错误,无法关闭MediaRecorder,原因不明!
// params.setPreviewSize(size.width,size.height);
// }
// params = camera.getParameters();
// params.setPictureFormat(PixelFormat.JPEG);
// // 设置预浏尺寸,注意要在摄像头支持的范围内选择
params.setPreviewSize(176,144);
// params.setPreviewSize(640, 480);//arg2--width, arg3--height
设置照片分辨率,注意要在摄像头支持的范围内选择
params.setPictureSize(640,480);//(手机5.0以下会出错)
// camera.setParameters(params);
//
// if (Build.VERSION.SDK_INT >= 14) {
// params.setFocusMode("auto");
// camera.autoFocus(mAutoFocusCallback);
// } else {
// params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
// isVideoAuto = false;
// }
// params.setPreviewFrameRate(20);
// //设置相机预览方向
// camera.setDisplayOrientation(90);
//
// try {
// camera.setPreviewDisplay(holder);
//
// } catch (Exception e) {
// e.printStackTrace();
// }
initCamera();
}
/**
*加载相机相关组件
*/
private void initCamera() {
surfaceview.setFocusable(false);
surfaceview.setEnabled(false);
if(camera==null){
camera = Camera.open(CAMERA_ID);
}
params = camera.getParameters();
//获得摄像头支持的分辨率
// List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
// for(Camera.Size size:supportedPreviewSizes){
// Log.d("tag", "width" + size.width + ",height" + size.height);
// }
// if (Build.VERSION.SDK_INT >= 14) {
// params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// camera.autoFocus(mAutoFocusCallback);
// } else {
// isVideoAuto = false;
// }
List<Camera.Size> sizeList = params.getSupportedPreviewSizes();
int PreviewWidth = 640;
int PreviewHeight = 480;
Boolean findSize = false;
if (sizeList.size() > 1) {
Iterator itor = sizeList.iterator();
while (itor.hasNext()) {
Camera.Size cur = (Camera.Size) itor.next();
if (cur.width >= PreviewWidth
&& cur.height >= PreviewHeight) {
findSize = true;
PreviewWidth = cur.width;
PreviewHeight = cur.height;
break;
}
}
}
if (!findSize) {
PreviewWidth = sizeList.get(0).width;
PreviewHeight = sizeList.get(0).height;
}
params.setPreviewSize(PreviewWidth, PreviewHeight);
// params.setPreviewSize(640, 480);
params.setPreviewFrameRate(20);
if (params.isVideoStabilizationSupported())
{
params.setVideoStabilization(true);
}
params.setRotation(90);
camera.setParameters(params);
//设置相机预览方向
camera.setDisplayOrientation(90);
try {
camera.setPreviewDisplay(surfaceview.getHolder());
} catch (IOException e1) {
e1.printStackTrace();
}
surfaceview.setOnTouchListener(this);
camera.startPreview();
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSufaceCreated = true;
if (camera != null) {
freeCameraResource();
}
if (null == camera) {
try {
camera = Camera.open(CAMERA_ID);
camera.setPreviewDisplay(holder);
// camera.autoFocus(mAutoFocusCallback);
} catch (Exception e) {
e.printStackTrace();
freeCameraResource();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// surfaceDestroyed的时候同时对象设置为null
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
surfaceview = null;
mediarecorder = null;
mIsSufaceCreated = false;
mAutoFocusCallback = null;
}
@Override
public void onInfo(MediaRecorder mediaRecorder, int i, int i1) {
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (camera != null && isVideoAuto) {
float x = event.getX();
float y = event.getY();
float touchMajor = event.getTouchMajor();
float touchMinor = event.getTouchMinor();
Rect touchRect = new Rect((int) (x - touchMajor / 2),
(int) (y - touchMinor / 2), (int) (x+touchMajor / 2),
(int) (y + touchMinor / 2));
this.submitFocusAreaRect(touchRect);
}
}
return false;
}
private void submitFocusAreaRect(final Rect touchRect) {
Camera.Parameters cameraParameters = camera.getParameters();
if (cameraParameters == null
|| cameraParameters.getMaxNumFocusAreas() == 0) {
return;
}
// Convert from View's width and height to +/- 1000
Rect focusArea = new Rect();
focusArea.set(touchRect.left * 2000 / surfaceview.getWidth() - 1000,
touchRect.top * 2000 / surfaceview.getHeight() - 1000,
touchRect.right * 2000 / surfaceview.getWidth() - 1000,
touchRect.bottom * 2000 / surfaceview.getHeight() - 1000);
// Submit focus area to camera
ArrayList<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
focusAreas.add(new Camera.Area(focusArea, 1000));
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
cameraParameters.setFocusAreas(focusAreas);
try {
camera.setParameters(cameraParameters);
camera.autoFocus(mAutoFocusCallback);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除文件
* @param file 已经存在的文件
*/
public static void deleteFile(File file) {
if (file.exists()) { // 判断文件是否存在
if (file.isFile()) { // 判断是否是文件
file.delete(); // delete()方法 你应该知道 是删除的意思;
} else if (file.isDirectory()) { // 否则如果它是一个目录
File files[] = file.listFiles(); // 声明目录下所有的文件 files[];
for (int i = 0; i < files.length; i++) { // 遍历目录下所有的文件
deleteFile(files[i]); // 把每个文件 用这个方法进行迭代
}
}
file.delete();
} else {
}
}
}
3.在AndroidManifest.xml表单文件中添加权限
<!-- 拍摄视频 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />