您的位置:首页 > 移动开发 > Android开发

使用MediaRecorder实现简单的录像功能

2017-03-06 11:33 375 查看

效果



代码

package com.javen.devicemange.CrazyOne.media;

import android.Manifest;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
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.ImageButton;
import android.widget.TextView;

import com.javen.devicemange.R;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by Administrator on 2017/3/2 0002.
* 使用MediaRecorder实现简单的录像功能
*/

public class MediaRecordVideo extends AppCompatActivity implements View.OnClickListener {
private SurfaceView mCameraPreview;
private SurfaceHolder mSurfaceHolder;
private ImageButton mShutter;
private TextView mMinutePrefix;
private TextView mMinuteText;
private TextView mSecondPrefix;
private TextView mSecondText;

private Camera mCamera;
private MediaRecorder mRecorder;

private final static int CAMERA_ID = 0;

private boolean mIsRecording = false;
private boolean mIsSufaceCreated = false;

private static final String TAG = "GsonUtils";

private Handler mHandler = new Handler();
private int width;
private int height;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mediarecordvideo);
//申请权限
requestPermission();
mCameraPreview = (SurfaceView) findViewById(R.id.camera_preview);
mMinutePrefix = (TextView) findViewById(R.id.timestamp_minute_prefix);
mMinuteText = (TextView) findViewById(R.id.timestamp_minute_text);
mSecondPrefix = (TextView) findViewById(R.id.timestamp_second_prefix);
mSecondText = (TextView) findViewById(R.id.timestamp_second_text);
mShutter = (ImageButton) findViewById(R.id.record_shutter);
Log.d(TAG, "mShutter=" + mShutter);

/***1.定义一个SurfaceView用来显示预览***/
mSurfaceHolder = mCameraPreview.getHolder();
mSurfaceHolder.addCallback(mSurfaceCallback);
// mSurfaceView 不需要自己的缓冲区
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

//获取SurfaceView的宽高
width = mCameraPreview.getWidth();
height = mCameraPreview.getHeight();
Log.d("GsonUtils", "width=" + width);
Log.d("GsonUtils", "height=" + height);
mShutter.setOnClickListener(this);
}

/**
* 申请权限
*/
private void requestPermission() {
String[] needPermission = {
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
ActivityCompat.requestPermissions(this, needPermission, 1);
}

@Override
protected void onPause() {
super.onPause();
if (mIsRecording) {
//先停止记录
stopRecording();
}
//停止预览
stopPreview();
}

/***
* 2.在SurfaceHolder的回调中用Camera对象启动预览
***/
private SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsSufaceCreated = false;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSufaceCreated = true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
startPreview();
}
};

/**
* 启动预览
*/
private void startPreview() {
//保证只有一个Camera对象
//当mCamera存在的,或者mIsSufaceCreated还存在
if (mCamera != null || !mIsSufaceCreated) {
Log.d(TAG, "startPreview will return");
return;
}
//打开相机
mCamera = Camera.open(CAMERA_ID);

Camera.Parameters parameters = mCamera.getParameters();
//获取最佳的预览尺寸
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
//设置预览的尺寸
parameters.setPreviewSize(size.width, size.height);
}

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
//设置视频每秒20帧
parameters.setPreviewFrameRate(20);

//设置相机预览方向
mCamera.setDisplayOrientation(90);

mCamera.setParameters(parameters);

try {
//让surfaceView来预览Camera
mCamera.setPreviewDisplay(mSurfaceHolder);
//mCamera.setPreviewCallback(mPreviewCallback);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
//开始预览
mCamera.startPreview();
}

private void stopPreview() {
//释放Camera对象
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(null);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}

mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}

/**
* 获取最佳的预览尺寸
*
* @param width
* @param height
* @param parameters
* @return
*/
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;

for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
//如果系统相机所支持的尺寸小于传入的尺寸,
if (size.width <= width && size.height <= height) {
//第一次初始化,就选用系统相机的尺寸
if (result == null) {
result = size;
} else {
//获取上一次的面积区域
int resultArea = result.width * result.height;
//遍历下一次的面积区域
int newArea = size.width * size.height;
//选用面积区域大的尺寸
if (newArea > resultArea) {
result = size;
}
}
}
}

return result;
}

@Override
public void onClick(View v) {
if (mIsRecording) {
stopRecording();
} else {
/***3.然后调用MediaRecorder来录像***/
initMediaRecorder();
startRecording();

//开始录像后,每隔1s去更新录像的时间戳,开启任务
mHandler.postDelayed(mTimestampRunnable, 1000);
}
}

/**
* 初始化MediaRecorder
*/
private void initMediaRecorder() {
mRecorder = new MediaRecorder();//实例化
mCamera.unlock();
//给Recorder设置Camera对象,保证录像跟预览的方向保持一致
mRecorder.setCamera(mCamera);
mRecorder.setOrientationHint(90);  //改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置从麦克风采集声音
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从摄像头采集图像
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);  // 设置视频的输出格式 为MP4
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // 设置音频的编码格式
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频的编码格式
mRecorder.setVideoSize(176, 144);  // 设置视频大小
mRecorder.setVideoFrameRate(20); // 设置帧率
//        mRecorder.setMaxDuration(10000); //设置最大录像时间为10s
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());

String videoPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + "VideoRecorder".toString();
Log.d("GsonUtils", "videoPath=" + videoPath);
//设置视频存储路径sd卡:movies/VideoRecorder
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + "VideoRecorder");
if (!file.exists()) {
//多级文件夹的创建
file.mkdirs();
}
//获取到当前时间状态
Date date = new Date();
date.setTime(System.currentTimeMillis());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm");
String currentTime = simpleDateFormat.format(date);
Log.d("GsonUtils", "currentTime=" + currentTime);
mRecorder.setOutputFile(file.getPath() + File.separator + "VID_" + currentTime + ".mp4");
}

/**
* 开始记录
*/
private void startRecording() {
if (mRecorder != null) {
try {
mRecorder.prepare();
mRecorder.start();
} catch (Exception e) {
mIsRecording = false;
Log.e(TAG, e.getMessage());
}
}

mShutter.setImageDrawable(getResources().getDrawable(R.drawable.btn_radio_on));
//标记为已经在记录中
mIsRecording = true;
}

/**
* 停止记录
*/
private void stopRecording() {
if (mCamera != null) {
mCamera.lock();
}

if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}

mShutter.setImageDrawable(getResources().getDrawable(R.drawable.btn_radio_off_));
mIsRecording = false;
//移除runnable的任务
mHandler.removeCallbacks(mTimestampRunnable);

//将录像时间还原
mMinutePrefix.setVisibility(View.VISIBLE);
mMinuteText.setText("0");
mSecondPrefix.setVisibility(View.VISIBLE);
mSecondText.setText("0");

//重启预览
startPreview();
}

private Runnable mTimestampRunnable = new Runnable() {
@Override
public void run() {
updateTimestamp();
//每隔1s开启runnable任务
mHandler.postDelayed(this, 1000);
}
};

/**
* 动态的刷新时间分秒
*/
private void updateTimestamp() {
int second = Integer.parseInt(mSecondText.getText().toString());
int minute = Integer.parseInt(mMinuteText.getText().toString());
second++;
Log.d(TAG, "second: " + second);

if (second < 10) {
mSecondText.setText(String.valueOf(second));
} else if (second >= 10 && second < 60) {
//超过10s,隐藏十位上的秒。
mSecondPrefix.setVisibility(View.GONE);
mSecondText.setText(String.valueOf(second));
} else if (second >= 60) {
//超过60s,显示十位上的秒。
mSecondPrefix.setVisibility(View.VISIBLE);
mSecondText.setText("0");

minute++;
mMinuteText.setText(String.valueOf(minute));
} else if (minute >= 10) {
mMinutePrefix.setVisibility(View.GONE);
}
}
}


布局

AndroidManifest.xml

<!--授予程序相机,读写sd卡的权限-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<!--硬件支持-->
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>


。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 安卓