最近在项目中遇到了视频的拍摄上传及本地预览功能,特地记录一下
1、基于本地视频的预览采用cardview进行显示,因此需要引入相应的jar包,我这里AS使用的是
compile 'com.android.support:cardview-v7:26.+'
compile 'com.android.support:design:26.+'
2、新建一个录制视频的界面如图
3、接下来则是代码实现(文末有全部代码)
第一步当然是检查设备是否有摄像头,如果都没有摄像头,还谈什么视频拍摄呢
private boolean checkCameraHardware(Context context){
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
ToastUtils.showToast(context, "successfully detact camera!");
return true;
}
else {
ToastUtils.showToast(context, "not detact camera!!!");
return false;
}
}
核心设置如下
/**
* 创建MediaRecorder实例,并为之设定基本属性
* @return
*/
private boolean prepareVideoRecorder(){
try {
recorder = new MediaRecorder();
mCamera.unlock();
recorder.setCamera(mCamera);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
// recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Set output file format
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// 这两项需要放在setOutputFormat之后
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
recorder.setVideoSize(640, 480);
recorder.setVideoFrameRate(30); //这是重点,帧值设置得越大,占内存越大,30基本上是满足了一般的视频要求,60的话上传就费劲了
recorder.setVideoEncodingBitRate(3 * 1024 * 1024);
recorder.setOrientationHint(90);
//设置记录会话的最大持续时间(毫秒)
recorder.setMaxDuration(30 * 1000);
recorder.setPreviewDisplay(previewView.getHolder().getSurface());
result_path = getOutputMediaPath();
recorder.setOutputFile(result_path);
recorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
注:此功能需要的权限有
Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE
完整代码如下
public class Activity_VideoCamera extends Activity {
private Camera mCamera;
private CameraPreviewView previewView;
private MediaRecorder recorder;
private boolean isrecording = false;
private Button btn, btn_cancel, btn_sure;
private TextView tv_time;
Handler startTimehandler;
private long baseTimer;
private Timer timer;
private String result_path ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
if (Build.VERSION.SDK_INT >= 23){
CommonUtils.requestLocPermissions(this);
CommonUtils.requestPermissions(this);
CommonUtils.requestVideoPermissions(this);
}
if (!checkCameraHardware(this)) {
return;
};
mCamera = getCameraInstance();
mCamera.setDisplayOrientation(90);
previewView = new CameraPreviewView(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(previewView);
btn = (Button) findViewById(R.id.btn);
btn_sure = (Button) findViewById(R.id.btn_sure);
btn_cancel = (Button) findViewById(R.id.btn_cancel);
tv_time = (TextView) findViewById(R.id.tv_time);
initEvent();
startTimehandler = new Handler(){
public void handleMessage(android.os.Message msg) {
if (null != tv_time) {
tv_time.setText("录制时间:" + (String) msg.obj);
}
}
};
}
private void initEvent(){
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isrecording) {
releaseMediaRecoder();
//mCamera.lock();
btn.setText("拍摄");
isrecording = false;
timer.cancel();
}
else {
if (prepareVideoRecorder()) {
recorder.start();
btn.setText("Stop");
isrecording = true;
tv_time.setText("录制时间:00:00:00");
startTimer();
}
else {
releaseMediaRecoder();
timer.cancel();
}
}
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
File file = new File(result_path);
file.delete();
finish();
}catch (Exception e){
e.printStackTrace();
}
}
});
btn_sure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("path", result_path);
Activity_VideoCamera.this.setResult(RESULT_OK, intent);
Activity_VideoCamera.this.finish();
}
});
}
public void startTimer(){
baseTimer = SystemClock.elapsedRealtime();
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
int time = (int)((SystemClock.elapsedRealtime() - baseTimer) / 1000);
String hh = new DecimalFormat("00").format(time / 3600);
String mm = new DecimalFormat("00").format(time % 3600 / 60);
String ss = new DecimalFormat("00").format(time % 60);
String timeFormat = new String(hh + ":" + mm + ":" + ss);
Message msg = new Message();
msg.obj = timeFormat;
startTimehandler.sendMessage(msg);
}
}, 0, 1000L);
}
@Override
protected void onPause() {
super.onPause();
releaseMediaRecoder();
releaseCamera();
}
private void releaseMediaRecoder(){
if (recorder != null) {
recorder.reset();
recorder.release();
recorder = null;
mCamera.lock();
}
}
private void releaseCamera(){
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
/**
* 创建MediaRecorder实例,并为之设定基本属性
* @return
*/
private boolean prepareVideoRecorder(){
try {
recorder = new MediaRecorder();
mCamera.unlock();
recorder.setCamera(mCamera);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
// recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Set output file format
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// 这两项需要放在setOutputFormat之后
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
recorder.setVideoSize(640, 480);
recorder.setVideoFrameRate(30);
recorder.setVideoEncodingBitRate(3 * 1024 * 1024);
recorder.setOrientationHint(90);
//设置记录会话的最大持续时间(毫秒)
recorder.setMaxDuration(30 * 1000);
recorder.setPreviewDisplay(previewView.getHolder().getSurface());
result_path = getOutputMediaPath();
recorder.setOutputFile(result_path);
recorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 获取输出video文件目录
* @return
*/
private String getOutputMediaPath() {
java.util.Date date = new java.util.Date();
String timeTemp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date.getTime());
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
Log.e("Error", "getOutputMediaPath file path---"+
mediaStorageDir.getPath() + File.separator +
"VID_" + timeTemp+ ".mp4");
return mediaStorageDir.getPath() + File.separator +
"VID_" + timeTemp + ".mp4";
}
public class CameraPreviewView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder holder;
public CameraPreviewView(Context context, Camera camera) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (holder.getSurface() == null) {
return;
}
try {
if(mCamera != null) {
holder.removeCallback(this);
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.lock();
mCamera.release();
mCamera = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 获取camera实例
* @return
*/
public static Camera getCameraInstance(){
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
return camera;
}
/**
* 检测手机有无摄像头
* @param context
* @return
*/
private boolean checkCameraHardware(Context context){
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
ToastUtils.showToast(context, "successfully detact camera!");
return true;
}
else {
ToastUtils.showToast(context, "not detact camera!!!");
return false;
}
}
}
在预览界面就简单了,在onresultActivity方法中实现如下代码
if (data != null) {
final String filepath = data.getExtras().getString("path");
final VideoView videoView = new VideoView(context);
Uri uri = Uri.parse(filepath);
videoView.setLayoutParams(layoutParams);
videoView.setVideoURI(uri);
videoView.setMediaController(new MediaController(context));
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// videoView.start();
}
});
ll_pics.addView(videoView,ll_pics.getChildCount() - 1);
Log.e(TAG, "onActivityResult: " + filepath);
file = new File(filepath);
Log.e(TAG, "filename----"+ file.getName());
// receiveHandler.sendEmptyMessage(HANDLE_UPLOAD_IMG);//实现上传方法
}
实现上传的代码我这里就不展示了,如有不足望见谅