后台录像代码

RecordThread:

import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 视频录制 * * @author bcaiw * */ public class RecordThread extends Thread { public static final int RECORD_START=0; public static final int RECORD_STOP=1; private MediaRecorder mediarecorder;// 录制视频的类 private SurfaceHolder surfaceHolder; private long recordTime;// 录制时间,单位毫秒 private String filePath;// 录像文件保存路径 private SurfaceView surfaceview;// 显示视频的控件 private Camera mCamera; private Handler m_msgHandler;// 主界面传递过来的handler private int iType; private Object release_ob = new Object(); private Object stop_ob = new Object(); private HashMap<String, String> map = new HashMap<String, String>(); private Handler child_msgHandler;// 接收消息的handler private Timer timer;// 定时器 private long startTime = Long.MIN_VALUE; private long endTime = Long.MIN_VALUE; /** * 保存文件目录 */ private String fileFolder; /** * 需要保存的文件名 */ private String fileName; /** * 每次录制时直接保存的文件名,按时间戳随机生成 */ private String tempFileName; /** * 时间格式化 */ private DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); public String getFileFolder() { return fileFolder; } public void setFileFolder(String fileFolder) { this.fileFolder = fileFolder; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public long getStartTime() { return startTime; } public void setStartTime(long startTime) { this.startTime = startTime; } public long getEndTime() { return endTime; } public void setEndTime(long endTime) { this.endTime = endTime; } public SurfaceHolder getSurfaceHolder() { return surfaceHolder; } public void setSurfaceHolder(SurfaceHolder surfaceHolder) { this.surfaceHolder = surfaceHolder; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public SurfaceView getSurfaceview() { return surfaceview; } public void setSurfaceview(SurfaceView surfaceview) { this.surfaceview = surfaceview; } public Handler getM_msgHandler() { return m_msgHandler; } public void setM_msgHandler(Handler mMsgHandler) { m_msgHandler = mMsgHandler; } public int getiType() { return iType; } public void setiType(int iType) { this.iType = iType; } public long getRecordTime() { return recordTime; } public void setRecordTime(long recordTime) { this.recordTime = recordTime; } public Handler getHandler() { return child_msgHandler; } public RecordThread() { } /** * 构造函数 * * @param recordTime * @param surfaceview * @param surfaceHolder * @param filePath * @param msgHandler * @param iType */ public RecordThread(long recordTime, SurfaceView surfaceview, SurfaceHolder surfaceHolder, String filePath, Handler msgHandler, int iType) { this.recordTime = recordTime; this.surfaceview = surfaceview; this.surfaceHolder = surfaceHolder; this.filePath = filePath; this.m_msgHandler = msgHandler; this.iType = iType; File file = new File(filePath.substring(0, filePath.lastIndexOf("/"))); if (!file.exists()) { file.mkdirs(); } file = null; } /** * 通用方法,接收多线程过来的数据,有可能不仅仅是msg,所以定义map对象 * * @param handle * @param iType * @param info */ public void sendMsgToHandle(Handler handle, int iType, Map<String, String> info) { Message threadMsg = handle.obtainMessage(); threadMsg.what = iType; Bundle threadbundle = new Bundle(); threadbundle.clear(); for (Iterator i = info.keySet().iterator(); i.hasNext();) { Object obj = i.next(); threadbundle.putString(obj.toString(), info.get(obj)); } threadMsg.setData(threadbundle); handle.sendMessage(threadMsg); } @Override public void run() { // 初始化消息循环队列,需要在Handler创建之前 Looper.prepare(); child_msgHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case RECORD_START:// 启动 /** * 开始录制 */ startRecord(); timer = new Timer(); /** * 设置定时任务 */ timer.schedule(new TimerThread(), recordTime); break; case RECORD_STOP:// 关闭 if (timer != null) { timer.cancel(); } stopRecord(); break; } } }; // 启动子线程消息循环队列 Looper.loop(); } /** * 开始录制 */ public void startRecord() { try { if (prepareVideoRecorder()) {// 准备录制 startTime = System.currentTimeMillis(); // 开始录制 mediarecorder.start(); // 通知主线程正在开始录像 map.clear(); map.put("recordingFlag", "true"); String ac_time = getVedioRecordTime();// 录像时间 map.put("recordTime", ac_time); sendMsgToHandle(m_msgHandler, iType, map); } else { releaseMediaRecorder(); } } catch (Exception e) { releaseMediaRecorder(); } } /** * 停止录制 */ public void stopRecord() { // Looper.myLooper().quit(); try { if (mediarecorder != null) { synchronized (stop_ob) { endTime = System.currentTimeMillis(); // 停止录制 mediarecorder.stop(); } // 释放资源 releaseMediaRecorder(); } } catch (IllegalStateException e) { endTime = System.currentTimeMillis(); releaseMediaRecorder(); } catch (Exception e) { endTime = System.currentTimeMillis(); releaseMediaRecorder(); } } /** * 拼接录像文件 */ public void joinFile() { FileOperation fileOperation = new FileOperation(); RandomAccessFile tempAccessFile = null; RandomAccessFile vedioAccessFile = null; try { File tempFile = new File(filePath); File vedioFile = new File(fileFolder + fileName); if (tempFile.exists()) {// 缓存文件存在 if (!vedioFile.exists()) {// 第一次录制 vedioFile = null; tempFile = null; fileOperation.move(filePath, fileFolder + fileName, 1); } else {// 多于一次录制 vedioFile = null; tempFile = null; tempAccessFile = new RandomAccessFile(filePath, "rw"); vedioAccessFile = new RandomAccessFile(fileFolder + fileName, "rw"); vedioAccessFile.seek(vedioAccessFile.length()); // 头部信息32位,固定显示,因此拼接时,去掉头部 tempAccessFile.seek(32); Log.i("process", vedioAccessFile.length()+" before"); byte[] data = new byte[4096]; int length = -1; while ((length = tempAccessFile.read(data)) != -1) { vedioAccessFile.write(data, 0, length); } //vedioAccessFile.close(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (tempAccessFile != null) { tempAccessFile.close(); tempAccessFile = null; } if (vedioAccessFile != null) { vedioAccessFile.close(); vedioAccessFile = null; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 准备录制,判断摄像头是否被占用,初始化mediarecorder对象,以及相关设置 */ public boolean prepareVideoRecorder() { boolean result = false; // 获取摄像头实例对象 int count=0; int c_flag=0; while((mCamera = getCameraInstance())==null){ try { Thread.currentThread().sleep(500); count++; if(count>4)break; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //打开前置摄像头 if(mCamera==null){ int cameraCount = 0; Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); cameraCount = Camera.getNumberOfCameras(); // get cameras number for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) { Camera.getCameraInfo( camIdx, cameraInfo ); // get camerainfo if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_FRONT ) { // 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置 try { mCamera = Camera.open( camIdx ); c_flag=1; break; } catch (Exception e) { e.printStackTrace(); } } } } if (mCamera != null) { try { mediarecorder = new MediaRecorder();// 创建mediarecorder对象 // //解锁camera mCamera.setPreviewDisplay(surfaceHolder); mCamera.startPreview(); mCamera.unlock(); mediarecorder.setCamera(mCamera); // 设置录制视频源为Camera(相机) mediarecorder .setAudioSource(MediaRecorder.AudioSource.MIC); mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); if(c_flag==1){ // 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4 mediarecorder .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 音频编码 // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错 // 设置录制的视频编码h263 h264 mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); // mediarecorder.setVideoSize(640,480); // 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错 // mediarecorder.setVideoFrameRate(12); }else{ // 设置录制文件质量 mediarecorder.setProfile(CamcorderProfile .get(CamcorderProfile.QUALITY_LOW)); } // 判断文件夹是否存在 File file = new File(fileFolder); if (!file.exists()) { file.mkdirs(); } file = null; tempFileName = FileOperation.getCurFileName(fileFolder,fileName); filePath = fileFolder + tempFileName; // 指定保存文件 mediarecorder.setOutputFile(filePath); // 指定预览输出 mediarecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 根据以上配置准备MediaRecorder mediarecorder.prepare(); // 准备成功 result = true; } catch (Exception e) { releaseMediaRecorder(); } } return result; } /** * 获取摄像头实例对象 * * @return */ public Camera getCameraInstance() { Camera c = null; try { c = Camera.open(); } catch (Exception e) { // 打开摄像头错误 Log.i("process", e.getCause().toString()); Log.i("process", e.getMessage()); } return c; } /** * 释放MediaRecorder对象 */ private void releaseMediaRecorder() { try { synchronized (release_ob) { if (mediarecorder != null) { Log.i("process", "release_currentThread" + Thread.currentThread().getId()); mediarecorder.reset(); // 清除recorder配置 mediarecorder.release(); // 释放recorder对象 mediarecorder = null; if (mCamera != null) { mCamera.lock(); // 为后续使用锁定摄像头 mCamera.release(); // 为其它应用释放摄像头 mCamera = null; } map.clear(); map.put("recordingFlag", "false");// 停止录像 String ac_time = getVedioRecordTime();// 录像时间 map.put("recordTime", ac_time); sendMsgToHandle(m_msgHandler, iType, map); } } } catch (Exception e) { map.clear(); map.put("recordingFlag", "false"); String ac_time = getVedioRecordTime();// 录像时间 map.put("recordTime", ac_time); sendMsgToHandle(m_msgHandler, iType, map); } } /** * 计算当前已录像时间,默认值返回0 * * @return */ public String getVedioRecordTime() { String result = "0"; if (startTime != Long.MIN_VALUE && endTime != Long.MIN_VALUE) { long tempTime = (endTime - startTime); result = String.valueOf(tempTime); } return result; } /** * 定时任务,关闭录制程序 * * @author bcaiw * */ class TimerThread extends TimerTask { @Override public void run() { try { stopRecord(); this.cancel(); } catch (Exception e) { map.clear(); map.put("recordingFlag", "false"); String ac_time = getVedioRecordTime();// 录像时间 map.put("recordTime", ac_time); sendMsgToHandle(m_msgHandler, iType, map); } } } }

Activity代码:
1.启动:

private void startVedioThread() { if (!isRecording && recordFlag && catiSurveyAnswer.needVedio()) { // 判断是否存在录音,若存在,则暂停录音 if (catiSurveyAnswer.needRecord()) { pauseRecord(); } recordFlag = false;// 控制一次访问只能录像一次 // 录制时间 long needTime = recordTime - recordingTime; if (needTime > 0) { String recordFileName = camiApp.getCurSampleID() + ".3gp"; // 图片全名称 String recordfullname = ((CapiApplication) getApplication()) .getDatabasePath() + camiApp.getCurProjectId() + "/" + camiApp.getCurAgentCode() + "/" + "vedio/" + recordFileName; thread = new RecordThread(); thread.start(); thread.setRecordTime(needTime); // thread.setFilePath(recordfullname); thread.setSurfaceHolder(surfaceHolder); thread.setSurfaceview(surfaceview); thread.setM_msgHandler(msgHandler); thread.setiType(TYPE_CHANGEVEDOISTATUS); thread.setFileFolder(((CapiApplication) getApplication()) .getDatabasePath() + camiApp.getCurProjectId() + "/" + camiApp.getCurAgentCode() + "/" + "vedio/"); thread.setFileName(recordFileName); while ((child_msgHandler = thread.getHandler()) == null) { try { Thread.currentThread().sleep(500); } catch (InterruptedException e) { Log.i("process", "等会"); } } String msgObj = "message from mainThread"; Message mainThreadMsg = child_msgHandler.obtainMessage(RecordThread.RECORD_START, 1, 1, msgObj); child_msgHandler.sendMessage(mainThreadMsg); } } }

2.停止:

if (child_msgHandler != null) { String msgObj = "message from mainThread"; Message mainThreadMsg = child_msgHandler.obtainMessage( RecordThread.RECORD_STOP, 1, 1, msgObj); child_msgHandler.sendMessage(mainThreadMsg); }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值