Android MediaRecorder 后台视屏录制
2016-12-14 10:46
92 查看
MediaRecorder ,一般用在多媒体视频录制上面,今天我们就来聊聊视频录制,首先录制视频我们少不了要用Camera,
1、SurfaceView 用于承载画面
这里我们需要首先是implements SurfaceHolder.Callback,这样我们才能在surface创建的时候初始化相机渲染画面,
在画面销毁的时候销毁相机
2、初始化相机Camera
3、 初始化震动传感器监听 用于录制视频
4、SoundPool 用于开始录像时播放的声音
5、配置MediaRecorder 的录制参数后开始录制
6、停止录像
MainActivity.class
Demo 下载地址:http://download.csdn.net/download/pigseesunset/9711129
1、SurfaceView 用于承载画面
这里我们需要首先是implements SurfaceHolder.Callback,这样我们才能在surface创建的时候初始化相机渲染画面,
在画面销毁的时候销毁相机
2、初始化相机Camera
3、 初始化震动传感器监听 用于录制视频
4、SoundPool 用于开始录像时播放的声音
5、配置MediaRecorder 的录制参数后开始录制
6、停止录像
MainActivity.class
package com.testopensourceapplication.recorderdemo; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.Color; import android.hardware.Camera; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.media.AudioManager; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.media.SoundPool; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener ,SurfaceHolder.Callback{ public static CustomProgressDialog progressDialog; SurfaceView surfaceView; TextView timer; ImageView recording; LinearLayout ll_hud_record_viewc; TextView start; TextView save; TextView photo; TextView stop; private String innerSDcard;// 储存内部SD卡路径 public static String rootpath; private String extSDcard;// 储存外部SD卡的路径(需要root权限) private MediaRecorder mediaRecorder;// 录制视频的类 private SensorManager sensorManager;// 检测震动相关对象(加速度传感器) private final int MENU_HIDE_MSG = 0x001; private final int TIMER_GOING_MSG = 0x002; private final int RECORDER_RESTART_MSG = 0x003; private final int LAUNCH_RECORD = 0x004; private int textColor; private boolean isRecording = false; private String nowTime; private int second; private int minute; private int hour; private Camera mCamera; private SurfaceHolder surfaceHolder; private Camera.Size previewSize; private boolean safeToTakePicture = false; private SoundPool soundPool; private int cameraSound;// 音效的ID /** * 定时器设置,实现计时 */ private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == TIMER_GOING_MSG) { handler.sendEmptyMessageDelayed(TIMER_GOING_MSG, 1000); second++; if (second >= 60) { minute++; second = second % 60; } if (minute >= 60) { hour++; minute = minute % 60; } timer.setText(RecordUtils.format(hour) + ":" + RecordUtils.format(minute) + ":" + RecordUtils.format(second)); } if (msg.what == RECORDER_RESTART_MSG) { prepareRecorder(); } if (msg.what == MENU_HIDE_MSG) { start.setVisibility(View.GONE); stop.setVisibility(View.GONE); save.setVisibility(View.GONE); photo.setVisibility(View.GONE); } if (msg.what == LAUNCH_RECORD) { RecordUtils.spaceNotEnoughDeleteTempFile(MainActivity.this, rootpath); if (mediaRecorder == null) { prepareRecorder(); } else { Toast.makeText(MainActivity.this, "视频录制中", Toast.LENGTH_SHORT) .show(); } } super.handleMessage(msg); } }; //拍照的回调 Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { String path = innerSDcard + "/infisight/Recorders/photo/"; File photoFile = new File(path); if(!photoFile.exists()){ photoFile.mkdirs(); } if (isRecording == false) { mCamera.stopPreview(); } File pictureFile =new File(path,System.currentTimeMillis()+".jpg"); try{ FileOutputStream fos =new FileOutputStream(pictureFile); fos.write(data); fos.close(); }catch (Exception e){ Log.d("takePhoto", "File not found: " + e.getMessage()); } safeToTakePicture = true; if (isRecording == false) { mCamera.startPreview(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initActivity(); } private void initView(){ // SurfaceView 用于承载画面 surfaceView = (SurfaceView) findViewById(R.id.surfaceview); timer = (TextView) findViewById(R.id.timer); recording = (ImageView) findViewById(R.id.recording); ll_hud_record_viewc = (LinearLayout) findViewById(R.id.ll_hud_record_view); start = (TextView) findViewById(R.id.start); save = (TextView) findViewById(R.id.save); photo = (TextView) findViewById(R.id.photo); stop = (TextView) findViewById(R.id.stop); SurfaceHolder holder = surfaceView.getHolder();// 取得holder holder.addCallback(this); // holder加入回调接口 // 用于开始录像时播放的声音 音效的数量,类型,质量 soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0); //加载声音资源 cameraSound = soundPool.load(MainActivity.this, R.raw.camera, 0); start.setOnClickListener(this); save.setOnClickListener(this); photo.setOnClickListener(this); stop.setOnClickListener(this); textColor = getTextColor(stop); disenableView(stop); } private void initActivity(){ innerSDcard = Environment.getExternalStorageDirectory().getPath(); List extSDCardPath = RecordUtils.getAppPaths(MainActivity.this); for(int i=0;i<extSDCardPath.size();i++){ if(extSDCardPath.get(i).equals(innerSDcard)){ rootpath = innerSDcard; break; } extSDcard = extSDCardPath.get(i) + ""; } //如果没有外置SD卡用内置 File[] externalFilesDirs =new File[0]; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { externalFilesDirs = this.getExternalFilesDirs(null); } for(int i=0;i<externalFilesDirs.length;i++){ if (externalFilesDirs[i] != null) { rootpath = externalFilesDirs[0] + ""; } } // 获取传感器管理器 sensorManager = (SensorManager) this.getSystemService( Context.SENSOR_SERVICE); } @Override protected void onResume() { if (sensorManager != null) {// 注册监听器 sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); // 第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率 } super.onResume(); } // 震动传感器监听 private SensorEventListener sensorEventListener = new SensorEventListener() { // 传感器数据变动事件 @Override public void onSensorChanged(SensorEvent event) { float[] valuer = event.values; float x =valuer[0];// x轴方向的重力加速度,向右为正 float y =valuer[1];// y轴方向的重力加速度,向前为正 float z =valuer[2];// z轴方向的重力加速度,向上为正 // LogTools.i("Sensor", "x轴方向的重力加速度" + x + ";y轴方向的重力加速度" + y + // ";z轴方向的重力加速度" + z); int medumValue =20; if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) { RecordUtils.spaceNotEnoughDeleteTempFile(MainActivity.this, rootpath); if (mediaRecorder == null) { prepareRecorder(); } else { Toast.makeText(MainActivity.this, "视频录制中", Toast.LENGTH_SHORT) .show(); } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; /** * 设置MediaRecorder(初始化) */ public void prepareRecorder(){ enableView(stop); disenableView(start); recording.setVisibility(View.VISIBLE); isRecording = true; // 每次准备录像的时候生成nowTime作为文件名(可以确保每次录制的文件名不一样) nowTime = RecordUtils.getCurrentTime("yyyyMMddHHmmss"); second = 0; minute = 0; hour = 0; timer.setVisibility(View.VISIBLE); handler.sendEmptyMessage(TIMER_GOING_MSG); File file = new File(rootpath + "/temporary/"); if (!file.exists()) { file.mkdirs(); } mediaRecorder = new MediaRecorder();// 创建mediarecorder对象 CamcorderProfile camcorderProfile = CamcorderProfile .get(CamcorderProfile.QUALITY_HIGH); unlockCamera(); // 设置声源 // mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置录制视频源为Camera(相机) mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 可以设置视频录制完以后输出的角度 mediaRecorder.setOrientationHint(0); //设置输出格式 mediaRecorder.setOutputFormat(camcorderProfile.fileFormat); //设置视频帧率 mediaRecorder.setVideoFrameRate(camcorderProfile.videoFrameRate); mediaRecorder.setVideoSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight); mediaRecorder.setVideoEncodingBitRate(camcorderProfile.videoBitRate); //设置视频编码 mediaRecorder.setVideoEncoder(camcorderProfile.videoCodec); mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 设置视频文件输出的路径 // mediaRecorder.setOutputFile("/sdcard/driveVideo.mp4"); //设置输出路径 mediaRecorder.setOutputFile(rootpath + "/temporary/" + nowTime + ".mp4"); // 设置录制文件最长时间(10分钟) mediaRecorder.setMaxDuration(60000 * 10); try { // 准备录制(prepare为耗时操作,会造成主界面的ANR,如果可以,尽量放在子线程中)(导致开始录像时画面卡顿的原因) mediaRecorder.prepare(); //开始录制 mediaRecorder.start(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 激活控件 */ private void enableView(TextView v) { v.setClickable(true); v.setTextColor(textColor); } /** * 注销控件 */ private void disenableView(TextView v) { v.setClickable(false); v.setTextColor(Color.parseColor("#474747")); } /** * 获取文字颜色 * * @param v * @return */ private int getTextColor(TextView v) { ColorStateList textColors = v.getTextColors(); int defaultColor = textColors.getDefaultColor(); return defaultColor; } /** * 开始摄像前的准备工作 */ private void unlockCamera() { if (mCamera != null) { mCamera.unlock(); mediaRecorder.setCamera(mCamera); } else { } } /* 当 Surface第一次创建后会立即调用该函数。 * 程序可以在该函数中做些和绘制界面相关的初始化工作, * 一般情况下都是在另外的线程来绘制界面, **/ @Override public void surfaceCreated(SurfaceHolder holder) { // 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder Log.e("TAG","surfaceCreated1"); surfaceHolder = holder; startCamera(holder); } /*当Surface的状态(大小和格式) 发生变化的时候会调用该函数, 在surfaceCreated调用后该函数至少会 被调用一次。*/ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("TAG","surfaceCreated2"); surfaceHolder = holder; if (surfaceHolder.getSurface() == null) { // 预览surface不存在 return; } try { mCamera.stopPreview(); } catch (Exception e) { } if (mCamera != null) { Log.e("TAG","safeToTakePicture"+safeToTakePicture); //设置摄像头的初始参数 Camera.Parameters parameters = mCamera.getParameters(); previewSize = parameters.getPreviewSize(); mCamera.startPreview(); safeToTakePicture = true; } } /* 当Surface被摧毁前会调用该函数 该函数被调用后就不能继续使用Surface了, 一般在该函数中来清理使用的资源。*/ @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.e("TAG","surfaceCreated3"); if (mediaRecorder != null) { stopRecorder(); } surfaceView = null; surfaceHolder = null; mediaRecorder = null; if (mCamera != null) { mCamera.autoFocus(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } } @Override public void onClick(View v) { if(v == start){ RecordUtils.spaceNotEnoughDeleteTempFile(MainActivity.this, rootpath); if (mediaRecorder == null && !isRecording) { prepareRecorder(); } else { Toast.makeText(MainActivity.this, "视频录制中", Toast.LENGTH_SHORT) .show(); } } if(v == stop){ if(mediaRecorder == null){ Toast.makeText(MainActivity.this, "当前没有录制,无法停止", Toast.LENGTH_SHORT) .show(); } stopRecorder(); isRecording = false; recording.setVisibility(View.GONE); } if(v == save){ // 必须释放camera资源否则会导致camera被占用,无法被再次开启 stopRecorder(); isRecording = false; recording.setVisibility(View.GONE); Intent intent =new Intent(MainActivity.this,HomeActivity.class); startActivity(intent); Intent service =new Intent(MainActivity.this,BackgroundRecoder.class); startService(service); MainActivity.progressDialog.show(); } if(v == photo){ // ID,左声道,右声道,,循环次数,速率 soundPool.play(cameraSound, 1f, 1f, 0, 0, 1f); try{ if (safeToTakePicture) { mCamera.takePicture(null, null, mPictureCallback); safeToTakePicture = false; Toast.makeText(MainActivity.this, "拍照", Toast.LENGTH_SHORT) .show(); } }catch (Exception e){ Toast.makeText(MainActivity.this, "拍照失败", Toast.LENGTH_SHORT) .show(); e.printStackTrace(); } } } private void startCamera(SurfaceHolder holder){ openCamera(); if(mCamera!=null){ Camera.Parameters parameters =mCamera.getParameters(); //判断屏幕是横屏或是竖屏 if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ parameters.set("orientation", "portrait");//镜头角度转90度(默认摄像头是横拍) mCamera.setDisplayOrientation(90); }else{// 如果是横屏 parameters.set("orientation", "landscape"); mCamera.setDisplayOrientation(0); } int fittedWidth = 640; int fittedHeight = 480; // 指定preview的大小 previewSize = mCamera.new Size(fittedWidth, fittedHeight); //指定拍照图片的大小 parameters.setPreviewSize(fittedWidth, fittedHeight); // 将Camera.Parameters设定予Camera mCamera.setParameters(parameters); try { mCamera.setPreviewDisplay(holder); }catch (Exception e){ e.printStackTrace(); } // 打开预览画面 mCamera.startPreview(); } } /** * 打开摄像头 */ public void openCamera(){ int cameraCount =Camera.getNumberOfCameras(); //得到相机数 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); int cameraUse =0; for(int camIdx=0;camIdx<cameraCount;camIdx++){ Camera.getCameraInfo(camIdx,cameraInfo); //得到相机信息 try { cameraUse++; mCamera = Camera.open(camIdx); break; }catch (Exception e){ } }if(cameraUse == 0){ Toast.makeText(MainActivity.this, "无法搜索到摄像设备", Toast.LENGTH_SHORT) .show(); } } /** * 停止录制并解锁camera */ private void stopRecorder(){ if(mediaRecorder != null){ try{ mediaRecorder.stop(); }catch (Exception e){ Toast.makeText(MainActivity.this, "您操作速度过快,小瑞正全力加载,请稍候", Toast.LENGTH_SHORT).show(); return; } mediaRecorder.reset(); // 释放资源 mediaRecorder.release(); mediaRecorder = null; // 释放相机,否则预览将会停止 } enableView(start); disenableView(stop); isRecording = false; handler.removeMessages(TIMER_GOING_MSG); timer.setVisibility(View.GONE); if (mCamera != null) { mCamera.lock(); } } @Override protected void onPause() { if (sensorManager != null) {// 取消监听器 sensorManager.unregisterListener(sensorEventListener); } super.onPause(); } @Override protected void onDestroy() { if (mCamera != null) { mCamera.release(); mCamera = null; } super.onDestroy(); } }
RecordUtils.class
package com.testopensourceapplication.recorderdemo; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; import android.os.StatFs; import android.os.storage.StorageManager; import android.widget.Toast; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by HL on 2016/12/12. */ public class RecordUtils { public static final String FILE_DATA = "Data"; /** * 获得内外置SD卡的/Android/data/你的应用的包名/files/ 目录 */ public static List getAppPaths(Context context){ List pathsList =new ArrayList(); //存储的管理器 StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); //获取sdcard 的路径 外置和内置 String[] paths =null; try{ paths = (String[]) sm.getClass().getMethod("getVolumePaths").invoke(sm); }catch (Exception e){ e.printStackTrace(); } for(int i=0;i<paths.length;i++){ pathsList.add(paths[i]); } return pathsList; } /** * 当内存卡容量少于1000M时,自动删除视频列表里面的第一个文件 */ public static void spaceNotEnoughDeleteTempFile(Context context,String filepath){ try { if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ File file = new File(filepath); if(!file.exists()){ boolean mkdirs =file.mkdirs(); } StatFs statFs = new StatFs(filepath); // 获取block的SIZE long blocSize = statFs.getBlockSize(); // 获取总的BLOCK数量 long totalBlocks = statFs.getBlockCount(); // 可使用的Block的数量 long availaBlock = statFs.getAvailableBlocks(); // 获取当前可用内存容量,单位:MB long sd = availaBlock * blocSize / 1024 / 1024; while (sd<1000){ String filepath1 =filepath + "/temporary"; File file1 = new File(filepath1); if(!file1.exists()){ file1.mkdirs(); } File[] files =file1.listFiles(); if(files.length>0){ String dele =files[0] +""; File file2 =new File(dele); file2.delete(); } } }else if(Environment.getExternalStorageState().equals(Environment.MEDIA_REMOVED)){ Toast.makeText(context, "请插入内存卡", Toast.LENGTH_SHORT).show(); } }catch (Exception e){ e.printStackTrace(); } } /** * 获取当前时间 format:yyyy-MM-dd HH:mm:ss */ public static String getCurrentTime(String format) { SimpleDateFormat df = new SimpleDateFormat(format); return df.format(new Date()); } /** * 格式化时间 */ public static String format(int i) { String s = i + ""; if (s.length() == 1) { s = "0" + s; } return s; } /** * 存储数据 */ public static void putData(Context context,boolean data){ SharedPreferences spf =context.getSharedPreferences(FILE_DATA,Context.MODE_PRIVATE); SharedPreferences.Editor editor =spf.edit(); editor.putBoolean("isRecording",data); editor.commit(); } }
BackgroundRecoder.class
package com.testopensourceapplication.recorderdemo; import android.annotation.TargetApi; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.support.annotation.Nullable; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.Toast; import java.io.File; /** * Created by HL on 2016/12/13. */ public class BackgroundRecoder extends Service implements SurfaceHolder.Callback { private NotificationManager manager; private Notification.Builder notifiBuilder; private Notification notifi; private String innerSDcard;// 储存内部SD卡路径 private String rootpath; private static final int NOTIFICATION_DI = 1234; private static final int LAUNCH_RECORD = 0x001; private WindowManager mWindowManager; private View mRecorderView; private SurfaceView mSurfaceView; private ImageView move; ImageButton btn_start; ImageButton btn_stop; ImageButton btn_close; private boolean isRecording = false; private MediaRecorder mMediaRecorder; private Camera mCamera; private SurfaceHolder mSurfaceHolder; private WindowManager.LayoutParams mLayoutParams; private float x; private float y; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == LAUNCH_RECORD) { startRecord(); } super.handleMessage(msg); } }; @Override public void onCreate() { super.onCreate(); showNotifaction(); innerSDcard = Environment.getExternalStorageDirectory().getPath(); rootpath = MainActivity.rootpath; File file =new File(innerSDcard + File.separator + "infisight" + File.separator + "Recorders"+File.separator + "temporary"); if(!file.exists()){ file.mkdirs(); } startForeground(NOTIFICATION_DI,notifi); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mRecorderView = LayoutInflater.from(this).inflate( R.layout.recorder_layout, null); mSurfaceView = (SurfaceView) mRecorderView.findViewById(R.id.sv_recorder); move = (ImageView) mRecorderView.findViewById(R.id.move); btn_start = (ImageButton) mRecorderView.findViewById(R.id.btn_start); btn_stop = (ImageButton) mRecorderView.findViewById(R.id.btn_stop); btn_close = (ImageButton) mRecorderView.findViewById(R.id.btn_close); mSurfaceView.getHolder().addCallback(this); paramsButtonSetOnClick(); mLayoutParams = new WindowManager.LayoutParams(); mLayoutParams.type =WindowManager.LayoutParams.TYPE_PHONE; mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;// 设置悬浮窗口长宽数据 mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mWindowManager.addView(mRecorderView, mLayoutParams); mRecorderView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { x = event.getRawX(); y =event.getRawY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Animation animation1 = AnimationUtils.loadAnimation( BackgroundRecoder.this, R.anim.params_anim1); // close.startAnimation(animation1); move.startAnimation(animation1); break; case MotionEvent.ACTION_MOVE: updateViewPosition(event); break; case MotionEvent.ACTION_UP: updateViewPosition(event); // 动画 Animation animation = AnimationUtils.loadAnimation( BackgroundRecoder.this, R.anim.params_anim); // close.startAnimation(animation); move.startAnimation(animation); break; } return false; } }); } private void updateViewPosition(MotionEvent event){ mLayoutParams.x = (int) event.getRawX() - move.getWidth() / 2; mLayoutParams.y = (int) event.getRawY() - move.getHeight() / 2; mWindowManager.updateViewLayout(mRecorderView, mLayoutParams); } /** * 显示一个通知 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void showNotifaction(){ manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent pendingIntent =PendingIntent.getActivity(this,0,new Intent(this,MainActivity.class),0); notifiBuilder = new Notification.Builder(this); notifi = notifiBuilder.setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("行车记录仪") .setContentText("") .setAutoCancel(true).build(); } private void paramsButtonSetOnClick(){ btn_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startRecord(); } }); btn_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopRecord(); } }); btn_close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onDestroy(); } }); } private void startRecord(){ RecordUtils.spaceNotEnoughDeleteTempFile(BackgroundRecoder.this, rootpath); btn_start.setVisibility(View.INVISIBLE); btn_stop.setVisibility(View.VISIBLE); isRecording = true; RecordUtils.putData(BackgroundRecoder.this,isRecording); String nowTime = RecordUtils.getCurrentTime("yyyyMMddHHmmss"); mMediaRecorder =new MediaRecorder(); openCamera(); if(mCamera!=null){ mCamera.unlock(); mMediaRecorder.setCamera(mCamera); CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.setOutputFormat(camcorderProfile.fileFormat); mMediaRecorder.setVideoEncodingBitRate(camcorderProfile.videoBitRate); mMediaRecorder.setVideoEncoder(camcorderProfile.videoCodec); mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); mMediaRecorder.setOutputFile(innerSDcard + File.separator + "infisight" + File.separator + "Recorders" + File.separator + "temporary" + File.separator + nowTime + ".mp4"); try{ // 准备录制(prepare为耗时操作,会造成主界面的ANR,如果可以,尽量放在子线程中)(导致开始录像时画面卡顿的原因) mMediaRecorder.prepare(); }catch (Exception e){ } mMediaRecorder.start(); MainActivity.progressDialog.dismiss(); } } /** * 打开摄像头 */ public void openCamera(){ int cameraCount = android.hardware.Camera.getNumberOfCameras(); android.hardware.Camera.CameraInfo cameraInfo =new android.hardware.Camera.CameraInfo(); int cameraUse =0; for(int camIdx=0;camIdx<cameraCount;camIdx++){ Camera.getCameraInfo(camIdx,cameraInfo); try{ cameraUse++; mCamera = Camera.open(camIdx); break; }catch (Exception e){ } } if(cameraUse == 0){ Toast.makeText(this, "无法搜索到摄像设备", Toast.LENGTH_SHORT).show(); } } /** * 停止录像 */ private void stopRecord(){ btn_start.setVisibility(View.VISIBLE); btn_stop.setVisibility(View.VISIBLE); if(mMediaRecorder!=null){ isRecording = false; RecordUtils.putData(BackgroundRecoder.this,isRecording); //停止录制 mMediaRecorder.stop(); mMediaRecorder.reset(); // 释放资源 mMediaRecorder.release(); mMediaRecorder =null; } } @Override public void onDestroy() { try{ if(mMediaRecorder!=null){ //停止录制 mMediaRecorder.stop(); mMediaRecorder.reset(); //释放资源 mMediaRecorder.release(); mMediaRecorder = null; } }catch (Exception e){ e.printStackTrace(); return; } btn_start.setVisibility(View.VISIBLE); btn_stop.setVisibility(View.INVISIBLE); if(mCamera!=null){ mCamera.release(); mCamera = null; } if (mWindowManager != null && mRecorderView.getVisibility() == View.VISIBLE) { mWindowManager.removeView(mRecorderView); } stopForeground(true); super.onDestroy(); } @Override public void surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; // 如果之前状态为录制中,继续开启录像 if (true) { handler.sendEmptyMessageDelayed(LAUNCH_RECORD, 500); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mSurfaceHolder = holder; } @Override public void surfaceDestroyed(SurfaceHolder holder) { mSurfaceView = null; mSurfaceHolder = null; mMediaRecorder = null; } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
Demo 下载地址:http://download.csdn.net/download/pigseesunset/9711129
相关文章推荐
- Android MediaRecorder 后台视频录制
- Android MediaRecorder的总结还有录制视屏(详解)
- Android MediaRecorder视频录制,多分辨率调节
- android中使用MediaRecorder进行视频录制笔记
- Android 中使用MediaRecorder进行录像详解(视频录制)
- Android MediaRecorder录制音频
- Android之多媒体--使用MediaRecorder录制音频
- android中使用MediaRecorder进行视频录制笔记
- Android MediaRecorder视频录制,多分辨率调节
- Android 中使用MediaRecorder进行录像详解(视频录制)
- 初学Android,多媒体之使用MediaRecorder录制音频(七十八)
- Android 中使用MediaRecorder进行录像详解(视频录制)
- 从头学Android之多媒体--使用MediaRecorder录制音频
- android多媒体部分学习笔记六----音频录制 mediaRecorder
- Android 中使用MediaRecorder进行录像详解(视频录制)
- Android调用系统摄像头--使用MediaRecorder--2--使用MediaRecorder进行录制
- Android调用系统摄像头--使用MediaRecorder--2--使用MediaRecorder进行录制
- Android 中使用MediaRecorder进行录像详解(视频录制)
- android多媒体部分学习笔记七------音频录制 mediaRecorder
- Android MediaRecorder录制音频