温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android仿微信录制小视频

发布时间:2020-10-26 04:30:41 来源:脚本之家 阅读:195 作者:Anro丶 栏目:移动开发

本文实例为大家分享了Android仿微信录制小视频的具体代码,供大家参考,具体内容如下

先上张图片看看效果

Android仿微信录制小视频

简单叙述下

  • 首先通过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;
 }

 }
}

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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI