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

Android仿微信录制小视频

2018-05-07 17:13 756 查看

先上张图片看看效果

简单叙述下

  • 首先通过Camera类调用系统相机
  • 通过surfaceview绘制出来
  • 通过MediaRecorder来录制视频
  • 闪光灯 和 切换摄像头 需要重新配置Camera的参数
  • Camera预览界面画面拉升的原因是因为Surfaceview的大小与设定的比例不一致的

**本次版本更新了 切换前置摄像头录制视频问题
Android部分手机录制视频适配IOS手机问题 (OPPO手机部分不适配 目前启用的H264格式)**

完整的代码

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.tongxun.atongmu.dialog.CommonDialog;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class CircleViedoActivity extends Activity implements View.OnClickListener,MediaRecorder.OnErrorListener {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private ProgressBar mProgressBar;
private Button shoot_button;
private ImageView circle_light_btn;
private ImageView circle_change_camera_btn;
private TextView circle_camera_time;
private MediaRecorder mMediaRecorder;
private Camera mCamera;
private Timer mTimer;// 计时器
private OnRecordFinishListener mOnRecordFinishListener;// 录制完成回调接口
private int mWidth;// 视频分辨率宽度
private int mHeight;// 视频分辨率高度
private boolean isOpenCamera;// 是否一开始就打开摄像头
private int mRecordMaxTime;// 一次拍摄最长时间
private int mTimeCount;// 时间计数
private int mNumberOfCameras=0;//手机摄像头的数量
Bitmap bitmap;//图片缩略图
private int screenWidth;
public static File mVecordFile = null;// 文件
private boolean isOpenFlash=false;
private boolean isBackCamera=true;
private int mbackCamera;
private int mfrontCamera;
private CommonDialog commonDialog;
private static final int MOVICE_SUCCESS=1000;//录制完成
private static final int MOVICE_FILE=1001;//录制失败
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_super_video);
init_datas();
init_view();
set_datas();
init_event();
}
private void init_datas() {
isOpenCamera=true;//默认一开始就打开相机
mRecordMaxTime=10;//设置录制的时间
//获取手机摄像头的数量
Camera.CameraInfo cameraInfo=new Camera.CameraInfo();
mNumberOfCameras=Camera.getNumberOfCameras();
for(int camidx=0;camidx<mNumberOfCameras;camidx++){
Camera.getCameraInfo(camidx, cameraInfo);
if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_BACK){
mbackCamera=camidx;
}else if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
mfrontCamera=camidx;
}
}
}
private void init_view() {
mWidth=640;
mHeight=480;
//获取屏幕的宽度
screenWidth = getWindowManager().getDefaultDisplay().getWidth();
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);//预览界面
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);//进度条
shoot_button = (Button) findViewById(R.id.shoot_button);//拍摄按钮
circle_camera_time= (TextView) findViewById(R.id.circle_camera_time);
circle_change_camera_btn= (ImageView) findViewById(R.id.circle_change_camera_btn);//切换摄像头
circle_light_btn= (ImageView) findViewById(R.id.circle_light_btn);//开启闪光灯
ViewGroup.LayoutParams params=mSurfaceView.getLayoutParams();
params.height=(screenWidth*4)/3;
params.width=screenWidth;
mSurfaceView.setLayoutParams(params);
top_model2_left_img= (ImageView)findViewById(R.id.top_model2_left_img);
top_model2_left_img.setOnClickListener(this);
top_model2_right_img= (ImageView)findViewById(R.id.top_model2_right_img);
top_model2_right_img.setVisibility(View.INVISIBLE);
top_model2_txt= (TextView)findViewById(R.id.top_model2_txt);
top_model2_txt.setText("视频录制");
}
private void set_datas() {
mSurfaceHolder = mSurfaceView.getHolder();
mProgressBar.setMax(mRecordMaxTime);// 设置进度条最大量
mSurfaceHolder.setKeepScreenOn(true);//设置屏幕常亮
mSurfaceHolder.addCallback(new CustomCallBack());
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
circle_camera_time.setText("");
}
private void init_event() {
circle_light_btn.setOnClickListener(this);
circle_change_camera_btn.setOnClickListener(this);
shoot_button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
record(new OnRecordFinishListener() {
@Override
public void onRecordFinish() {
//录制时间达到最大值
handler.sendEmptyMessage(MOVICE_SUCCESS);
}
});
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (mTimeCount > 1 && mTimeCount<10) { //防止达到最大值up事件
//录制时间大于一秒
handler.sendEmptyMessage(MOVICE_SUCCESS);
} else if(mTimeCount<=1) {
//删除小于一秒的视频
if (getmVecordFile() != null) {
getmVecordFile().delete();
}
handler.sendEmptyMessage(MOVICE_FILE);
}
}
return true;
}
});
}
@Override
protected void onResume() {
super.onResume();
if(mCamera!=null){
freeCameraResource();
}
try {
initCamera();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// mRecorderView.stop();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//停止拍摄
stopRecord();
switch (msg.what){
case MOVICE_SUCCESS:
String msgs = "确认上传吗?";
commonDialog = new CommonDialog(CircleViedoActivity.this, new CommonDialog.GoCommonDialog() {
@Override
public void go() {
finishActivity();
commonDialog.dismiss();
}
@Override
public void cancel() {
//删除没有上传的视频
if (getmVecordFile() != null) {
getmVecordFile().delete();
}
commonDialog.dismiss();
}
}, msgs, "确定", "取消");
commonDialog.show();
break;
case MOVICE_FILE:
Toast.makeText(CircleViedoActivity.this, "视频录制时间太短", Toast.LENGTH_SHORT).show();
break;
}
}
};
private void finishActivity() {
stop();
Bitmap bitmap = null;
if (getmVecordFile() != null) {
//得到文件 File类型
File mfile = getmVecordFile();
bitmap = getVideoThumbnail(mfile.toString());
}
/**
* 部分Android手机缩略图拉不到,找到一种解决办法不是太满意 有没有大神提供思路
*/
// VideoPlayerActivity.startActivity(this, mRecorderView.getVecordFile().toString());
Intent intent = new Intent();
intent.putExtra("bitmap",bitmap);
setResult(RESULT_OK,intent);
finish();
}
@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();
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.circle_light_btn:
//开启关闭闪光灯 默认关闭
if(isOpenFlash){
isOpenFlash=false;
circle_light_btn.setImageResource(R.drawable.camera_light);
}else {
isOpenFlash=true;
circle_light_btn.setImageResource(R.drawable.camera_no_light);
}
try {
initCamera();
} catch (IOException e) {
e.printStackTrace();
}
break;
case R.id.circle_change_camera_btn:
if(isBackCamera){
isBackCamera=false;
}else {
isBackCamera=true;
}
try {
initCamera();
} catch (IOException e) {
e.printStackTrace();
}
break;
case R.id.top_model2_left_img:
stop();
finish();
break;
}
}
private class CustomCallBack implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!isOpenCamera)
return;
try {
initCamera();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
/**
* 初始化摄像头
*/
private void initCamera() throws IOException {
if (mCamera != null) {
freeCameraResource();
}
try {
if(isBackCamera){
mCamera = Camera.open(mbackCamera);//打开后摄像头
setCameraParams(isOpenFlash);
}else {
mCamera=Camera.open(mfrontCamera);//打开前摄像头
}
} catch (Exception e) {
e.printStackTrace();
freeCameraResource();
}
if (mCamera == null)
return;
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
mCamera.unlock();
}
/**
* 设置摄像头为竖屏
*/
private void setCameraParams(Boolean isOpenFlash) {
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
//获取预览的各种分辨率
List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
params.set("orientation", "portrait");//竖屏录制
params.setPreviewSize(mWidth, mHeight);//默认640*480
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//持续对焦
if(isBackCamera){
if(isOpenFlash){
//开启闪光灯
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}else {
//关闭闪光灯
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
}else {
}
mCamera.setParameters(params);
}
}
/**
* 释放摄像头资源
*/
private void freeCameraResource() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.lock();
mCamera.release();
mCamera = null;
}
}
private void createRecordDir() {
File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "ATOMImg/video/");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
File vecordDir = sampleDir;
// 创建文件
try {
mVecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式
} catch (IOException e) {
}
}
/**
* 初始化
*/
private void initRecord() throws IOException {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.reset();
if (mCamera != null)
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setOnErrorListener(this);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 视频源
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 音频源
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 视频输出格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 音频格式
mMediaRecorder.setVideoSize(mWidth, mHeight);// 设置分辨率:
// mMediaRecorder.setVideoFrameRate(16);// 这个我把它去掉了,感觉没什么用
mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);// 设置帧频率,然后就清晰了
if(isBackCamera) {
mMediaRecorder.setOrientationHint(90);// 输出旋转90度,保持竖屏录制
}else {
mMediaRecorder.setOrientationHint(270);
}mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 视频录制格式
----------
/**
这里是配置摄像头的重点 因为我们录制视频需要适配IOS开发和Android不同版本的手机 而IOS和Android通配的视频格式不多 我们这里采用H264格式 它的兼容范围更广阔 主要解决的就是部分OPPO手机不适配问题
*/
----------
// mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
mMediaRecorder.setOutputFile(mVecordFile.getAbsolutePath());
mMediaRecorder.prepare();
try {
mMediaRecorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 录制完成回调接口
*/
public interface OnRecordFinishListener {
public void onRecordFinish();
}
/**
* 录制
* @param onRecordFinishListener
*/
public void record(final OnRecordFinishListener onRecordFinishListener) {
this.mOnRecordFinishListener = onRecordFinishListener;
createRecordDir();//创建目录
try {
if (!isOpenCamera)// 如果未打开摄像头,则打开
initCamera();//初始化摄像头
initRecord();//初始化录制参数
mTimeCount = 0;// 时间计数器重新赋值
mTimer = new Timer();//创建一个定时器
mTimer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
mTimeCount++;
mProgressBar.setProgress(mTimeCount);// 设置进度条
// handler.sendEmptyMessage(TIME_CHANGW);
runOnUiThread(new Runnable() {
@Override
public void run() {
circle_camera_time.setText(mTimeCount + "″");
}
});
if (mTimeCount == mRecordMaxTime) {// 达到指定时间,停止拍摄
//录制完成调用录制回调接口
if (mOnRecordFinishListener != null)
mOnRecordFinishListener.onRecordFinish();
}
}
}, 0, 1000);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 停止拍摄
*/
public void stop() {
stopRecord();
releaseRecord();
freeCameraResource();
}
/**
* 停止录制
*/
public void stopRecord() {
mProgressBar.setProgress(0);
circle_camera_time.setText("");
if (mTimer != null)
mTimer.cancel();
if (mMediaRecorder != null) {
// 设置后不会崩
mMediaRecorder.setOnErrorListener(null);
mMediaRecorder.setPreviewDisplay(null);
try {
mMediaRecorder.stop();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 获取的视频的位置
* @return
*/
public File getmVecordFile() {
return mVecordFile;
}
/**
* 释放资源
*/
private void releaseRecord() {
if (mMediaRecorder != null) {
mMediaRecorder.setOnErrorListener(null);
try {
mMediaRecorder.release();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
mMediaRecorder = null;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
stop();
finish();
return false;
}else {
return super.onKeyDown(keyCode, event);
}
}
/**
* 获取视频缩略图
* @param filePath
* @return
*/
public Bitmap getVideoThumbnail(String filePath) {
Bitmap bitmap = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(filePath);
bitmap = retriever.getFrameAtTime();
}
catch(IllegalArgumentException e) {
e.printStackTrace();
}
catch (RuntimeException e) {
e.printStackTrace();
}
finally {
try {
retriever.release();
}
catch (RuntimeException e) {
e.printStackTrace();
}
}
return bitmap;
}
@Override
protected void onDestroy() {
super.onDestroy();
if(bitmap!=null){
try {
bitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
bitmap=null;
}
}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

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