首页 > 系统 > Android > 正文

Android仿最新微信相机功能

2019-12-12 00:50:11
字体:
来源:转载
供稿:网友

最近在开发即时通讯这个模块的时候使用到了自定义的相机,需求与微信一样,要求相机能长按和轻点,当时在网上找自定义相机的资源,很少,所以,我在这里把我的一些开发经验贴出来,供大家学习。

大致完成的功能如下:

  • 长按拍摄视频,轻点拍照
  • 前后摄像头的切换
  • 闪光的的开启,关闭,自动
  • 图片的压缩
  • 自动聚焦,手动聚焦

效果图如下:

相关代码如下:

package com.ses.im.app.chat.newcamera;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.graphics.PointF;import android.graphics.SurfaceTexture;import android.hardware.Camera;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.Surface;import android.view.TextureView;import android.view.View;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import com.ses.im.app.chat.R;import java.io.File;import java.util.concurrent.TimeUnit;import rx.Observable;import rx.Subscriber;import rx.Subscription;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;/** * * 拍摄界面 */public class CameraActivity extends AppCompatActivity implements View.OnClickListener { /** * 获取相册 */ public static final int REQUEST_PHOTO = 1; /** * 获取视频 */ public static final int REQUEST_VIDEO = 2; /** * 最小录制时间 */ private static final int MIN_RECORD_TIME = 1 * 1000; /** * 最长录制时间 */ private static final int MAX_RECORD_TIME = 15 * 1000; /** * 刷新进度的间隔时间 */ private static final int PLUSH_PROGRESS = 100; private Context mContext; /** * TextureView */ private TextureView mTextureView; /** * 带手势识别 */ private CameraView mCameraView; /** * 录制按钮 */ private CameraProgressBar mProgressbar; /** * 顶部像机设置 */ private RelativeLayout rl_camera; /** * 关闭,选择,前后置 */ private ImageView iv_close, iv_facing; private RelativeLayout iv_choice; private RelativeLayout cancel; /** * 闪光 */ private TextView tv_flash; /** * camera manager */ private CameraManager cameraManager; /** * player manager */ private MediaPlayerManager playerManager; /** * true代表视频录制,否则拍照 */ private boolean isSupportRecord; /** * 视频录制地址 */ private String recorderPath; /** * 图片地址 */ private String photoPath; /** * 录制视频的时间,毫秒 */ private int recordSecond; /** * 获取照片订阅, 进度订阅 */ private Subscription takePhotoSubscription, progressSubscription; /** * 是否正在录制 */ private boolean isRecording; /** * 是否为点了拍摄状态(没有拍照预览的状态) */ private boolean isPhotoTakingState; public static void lanuchForPhoto(Activity context) { Intent intent = new Intent(context, CameraActivity.class); context.startActivityForResult(intent, REQUEST_PHOTO); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; setContentView(R.layout.activity_camera); initView(); initDatas(); } private void initView() { mTextureView = (TextureView) findViewById(R.id.mTextureView); mCameraView = (CameraView) findViewById(R.id.mCameraView); mProgressbar = (CameraProgressBar) findViewById(R.id.mProgressbar); rl_camera = (RelativeLayout) findViewById(R.id.rl_camera); iv_close = (ImageView) findViewById(R.id.iv_close); iv_close.setOnClickListener(this); iv_choice = (RelativeLayout) findViewById(R.id.iv_choice); iv_choice.setOnClickListener(this); iv_close.setOnClickListener(this); iv_facing = (ImageView) findViewById(R.id.iv_facing); iv_facing.setOnClickListener(this); iv_close.setOnClickListener(this); tv_flash = (TextView) findViewById(R.id.tv_flash); tv_flash.setOnClickListener(this); cancel= (RelativeLayout) findViewById(R.id.cancel); cancel.setOnClickListener(this); } protected void initDatas() { cameraManager = CameraManager.getInstance(getApplication()); playerManager = MediaPlayerManager.getInstance(getApplication()); cameraManager.setCameraType(isSupportRecord ? 1 : 0); tv_flash.setVisibility(cameraManager.isSupportFlashCamera() ? View.VISIBLE : View.GONE); setCameraFlashState(); iv_facing.setVisibility(cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); rl_camera.setVisibility(cameraManager.isSupportFlashCamera()  || cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); final int max = MAX_RECORD_TIME / PLUSH_PROGRESS; mProgressbar.setMaxProgress(max); /**  * 拍照,拍摄按钮监听  */ mProgressbar.setOnProgressTouchListener(new CameraProgressBar.OnProgressTouchListener() {  @Override  public void onClick(CameraProgressBar progressBar) {  cameraManager.takePhoto(callback);  isSupportRecord = false;  }  @Override  public void onLongClick(CameraProgressBar progressBar) {  isSupportRecord = true;  cameraManager.setCameraType(1);  rl_camera.setVisibility(View.GONE);  recorderPath = FileUtils.getUploadVideoFile(mContext);  cameraManager.startMediaRecord1(recorderPath);  isRecording = true;  progressSubscription = Observable.interval(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()).take(max).subscribe(new Subscriber<Long>() {   @Override   public void onCompleted() {   stopRecorder(true);   }   @Override   public void onError(Throwable e) {   }   @Override   public void onNext(Long aLong) {   mProgressbar.setProgress(mProgressbar.getProgress() + 1);   }  });  }  @Override  public void onZoom(boolean zoom) {  cameraManager.handleZoom(zoom);  }  @Override  public void onLongClickUp(CameraProgressBar progressBar) {//  isSupportRecord = false;  cameraManager.setCameraType(0);  stopRecorder(true);  if (progressSubscription != null) {   progressSubscription.unsubscribe();  }  }  @Override  public void onPointerDown(float rawX, float rawY) {  if (mTextureView != null) {   mCameraView.setFoucsPoint(new PointF(rawX, rawY));  }  } }); /**  *点击预览图聚焦   */ mCameraView.setOnViewTouchListener(new CameraView.OnViewTouchListener() {  @Override  public void handleFocus(float x, float y) {  cameraManager.handleFocusMetering(x, y);  }  @Override  public void handleZoom(boolean zoom) {  cameraManager.handleZoom(zoom);  } }); } /** * 设置闪光状态 */ private void setCameraFlashState() { int flashState = cameraManager.getCameraFlash(); switch (flashState) {  case 0: //自动  tv_flash.setSelected(true);  tv_flash.setText("自动");  break;  case 1://open  tv_flash.setSelected(true);  tv_flash.setText("开启");  break;  case 2: //close  tv_flash.setSelected(false);  tv_flash.setText("关闭");  break; } } /** * 是否显示录制按钮 * @param isShow */ private void setTakeButtonShow(boolean isShow) { if (isShow) {  mProgressbar.setVisibility(View.VISIBLE);  rl_camera.setVisibility(cameraManager.isSupportFlashCamera()   || cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); } else {  mProgressbar.setVisibility(View.GONE);  rl_camera.setVisibility(View.GONE); } } /** * 停止拍摄 */ private void stopRecorder(boolean play) { isRecording = false; cameraManager.stopMediaRecord(); recordSecond = mProgressbar.getProgress() * PLUSH_PROGRESS;//录制多少毫秒 mProgressbar.reset(); if (recordSecond < MIN_RECORD_TIME) {//小于最小录制时间作废  if (recorderPath != null) {  FileUtils.delteFiles(new File(recorderPath));  recorderPath = null;  recordSecond = 0;  }  setTakeButtonShow(true); } else if (play && mTextureView != null && mTextureView.isAvailable()){  setTakeButtonShow(false);  mProgressbar.setVisibility(View.GONE);  iv_choice.setVisibility(View.VISIBLE);  cancel.setVisibility(View.VISIBLE);  iv_close.setVisibility(View.GONE);  cameraManager.closeCamera();  playerManager.playMedia(new Surface(mTextureView.getSurfaceTexture()), recorderPath); } } @Override protected void onResume() { super.onResume(); if (mTextureView.isAvailable()) {  if (recorderPath != null) {//优先播放视频  iv_choice.setVisibility(View.VISIBLE);  setTakeButtonShow(false);  playerManager.playMedia(new Surface(mTextureView.getSurfaceTexture()), recorderPath);  } else {  iv_choice.setVisibility(View.GONE);  setTakeButtonShow(true);  cameraManager.openCamera(mTextureView.getSurfaceTexture(),   mTextureView.getWidth(), mTextureView.getHeight());  } } else {  mTextureView.setSurfaceTextureListener(listener); } } @Override protected void onPause() { if (progressSubscription != null) {  progressSubscription.unsubscribe(); } if (takePhotoSubscription != null) {  takePhotoSubscription.unsubscribe(); } if (isRecording) {  stopRecorder(false); } cameraManager.closeCamera(); playerManager.stopMedia(); super.onPause(); } @Override protected void onDestroy() { mCameraView.removeOnZoomListener(); super.onDestroy(); } @Override public void onClick(View v) { int i = v.getId(); if (i == R.id.iv_close) {//  if (recorderPath != null) {//有拍摄好的正在播放,重新拍摄//  FileUtils.delteFiles(new File(recorderPath));//  recorderPath = null;//  recordSecond = 0;//  playerManager.stopMedia();//  setTakeButtonShow(true);//  iv_choice.setVisibility(View.GONE);//  cameraManager.openCamera(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight());//  } else if (isPhotoTakingState) {//  isPhotoTakingState = false;//  iv_choice.setVisibility(View.GONE);//  setTakeButtonShow(true);//  cameraManager.restartPreview();//  } else {  finish();//  } } else if (i == R.id.iv_choice) {//拿到图片或视频路径  Intent intent=new Intent();  if(isSupportRecord){  intent.putExtra("videopath", recorderPath);  setResult(3, intent);  finish();  }else{  intent.putExtra("videopath", photoPath);  setResult(3, intent);  finish();  } } else if (i == R.id.tv_flash) {  cameraManager.changeCameraFlash(mTextureView.getSurfaceTexture(),   mTextureView.getWidth(), mTextureView.getHeight());  setCameraFlashState(); } else if (i == R.id.iv_facing) {  cameraManager.changeCameraFacing(mTextureView.getSurfaceTexture(),   mTextureView.getWidth(), mTextureView.getHeight()); }else if(i == R.id.cancel){  if (recorderPath != null) {//有拍摄好的正在播放,重新拍摄  FileUtils.delteFiles(new File(recorderPath));  recorderPath = null;  recordSecond = 0;  playerManager.stopMedia();  setTakeButtonShow(true);  iv_choice.setVisibility(View.GONE);  cancel.setVisibility(View.GONE);  iv_close.setVisibility(View.VISIBLE);  cameraManager.openCamera(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight());  } else if (isPhotoTakingState) {  isPhotoTakingState = false;  iv_choice.setVisibility(View.GONE);  cancel.setVisibility(View.GONE);  iv_close.setVisibility(View.VISIBLE);  setTakeButtonShow(true);  cameraManager.restartPreview();  } } } /** * camera回调监听 */ private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {  if (recorderPath != null) {  iv_choice.setVisibility(View.VISIBLE);  setTakeButtonShow(false);  playerManager.playMedia(new Surface(texture), recorderPath);  } else {  setTakeButtonShow(true);  iv_choice.setVisibility(View.GONE);  cameraManager.openCamera(texture, width, height);  } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {  return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture texture) { } }; private Camera.PictureCallback callback = new Camera.PictureCallback() { @Override public void onPictureTaken(final byte[] data, Camera camera) {  setTakeButtonShow(false);  takePhotoSubscription = Observable.create(new Observable.OnSubscribe<Boolean>() {  @Override  public void call(Subscriber<? super Boolean> subscriber) {   if (!subscriber.isUnsubscribed()) {   photoPath = FileUtils.getUploadPhotoFile(mContext);   isPhotoTakingState = FileUtils.savePhoto(photoPath, data, cameraManager.isCameraFrontFacing());   subscriber.onNext(isPhotoTakingState);   }  }  }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Boolean>() {  @Override  public void onCompleted() {  }  @Override  public void onError(Throwable e) {  }  @Override  public void onNext(Boolean aBoolean) {   if (aBoolean != null && aBoolean) {   iv_choice.setVisibility(View.VISIBLE);   cancel.setVisibility(View.VISIBLE);   iv_close.setVisibility(View.GONE);   } else {   setTakeButtonShow(true);   }  }  }); } };}

相机管理类:

package com.ses.im.app.chat.newcamera;import android.app.Application;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.SurfaceTexture;import android.hardware.Camera;import android.media.CamcorderProfile;import android.media.MediaRecorder;import android.util.Log;import android.widget.Toast;import com.ses.im.app.chat.util.AppConfig;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;/** *  * 相机管理类 */public final class CameraManager { private Application context; /** * camera */ private Camera mCamera; private Camera.Parameters mParameters; /** * 视频录制 */ private MediaRecorder mMediaRecorder; /** * 相机闪光状态 */ private int cameraFlash; /** * 前后置状态 */ private int cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; /** * 是否支持前置摄像,是否支持闪光 */ private boolean isSupportFrontCamera, isSupportFlashCamera; /** * 录制视频的相关参数 */ private CamcorderProfile mProfile; /** * 0为拍照, 1为录像 */ private int cameraType; private CameraManager(Application context) { this.context = context; isSupportFrontCamera = CameraUtils.isSupportFrontCamera(); isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context); if (isSupportFrontCamera) {  cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK); } if (isSupportFlashCamera) {  cameraFlash = CameraUtils.getCameraFlash(context); } } private static CameraManager INSTANCE; public static CameraManager getInstance(Application context) { if (INSTANCE == null) {  synchronized (CameraManager.class) {  if (INSTANCE == null) {   INSTANCE = new CameraManager(context);  }  } } return INSTANCE; } /** * 打开camera */ public void openCamera(SurfaceTexture surfaceTexture, int width, int height) { if (mCamera == null) {  mCamera = Camera.open(cameraFacing);//打开当前选中的摄像头  mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH);  try {  mCamera.setDisplayOrientation(90);//默认竖直拍照  mCamera.setPreviewTexture(surfaceTexture);  initCameraParameters(cameraFacing, width, height);  mCamera.startPreview();  } catch (Exception e) {  LogUtils.i(e);  if (mCamera != null) {   mCamera.release();   mCamera = null;  }  } } } /** * 开启预览,前提是camera初始化了 */ public void restartPreview() { if (mCamera == null) return; try {  Camera.Parameters parameters = mCamera.getParameters();  int zoom = parameters.getZoom();  if (zoom > 0) {  parameters.setZoom(0);  mCamera.setParameters(parameters);  }  mCamera.startPreview(); } catch (Exception e) {  LogUtils.i(e);  if (mCamera != null) {  mCamera.release();  mCamera = null;  } } } private void initCameraParameters(int cameraId, int width, int height) { Camera.Parameters parameters = mCamera.getParameters(); if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {  List<String> focusModes = parameters.getSupportedFocusModes();  if (focusModes != null) {  if (cameraType == 0) {   if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {   parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);   }  } else {   if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {   parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);   }  }  } } parameters.setRotation(90);//设置旋转代码, switch (cameraFlash) {  case 0:  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);  break;  case 1:  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);  break;  case 2:  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);  break; } List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes(); List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes(); if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) {  /**  for (Camera.Size size : pictureSizes) {  LogUtils.i("pictureSize " + size.width + " " + size.height);  }  for (Camera.Size size : pictureSizes) {  LogUtils.i("previewSize " + size.width + " " + size.height);  }*/  Camera.Size optimalPicSize = getOptimalCameraSize(pictureSizes, width, height);  Camera.Size optimalPreSize = getOptimalCameraSize(previewSizes, width, height);//  Camera.Size optimalPicSize = getOptimalSize(pictureSizes, width, height);//  Camera.Size optimalPreSize = getOptimalSize(previewSizes, width, height);  LogUtils.i("TextureSize "+width+" "+height+" optimalSize pic " + optimalPicSize.width + " " + optimalPicSize.height + " pre " + optimalPreSize.width + " " + optimalPreSize.height);  parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height);  parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height);  mProfile.videoFrameWidth = optimalPreSize.width;  mProfile.videoFrameHeight = optimalPreSize.height;  mProfile.videoBitRate = 5000000;//此参数主要决定视频拍出大小 } mCamera.setParameters(parameters); } /** * 释放摄像头 */ public void closeCamera() { this.cameraType = 0; if (mCamera != null) {  try {  mCamera.stopPreview();  mCamera.release();  mCamera = null;  } catch (Exception e) {  LogUtils.i(e);  if (mCamera != null) {   mCamera.release();   mCamera = null;  }  } } } /** * 集合不为空 * * @param list * @param <E> * @return */ private <E> boolean isEmpty(List<E> list) { return list == null || list.isEmpty(); } /** * * @param sizes 相机support参数 * @param w * @param h * @return 最佳Camera size */ private Camera.Size getOptimalCameraSize(List<Camera.Size> sizes, int w, int h){ sortCameraSize(sizes); int position = binarySearch(sizes, w*h); return sizes.get(position); } /** * * @param sizes * @param targetNum 要比较的数 * @return */ private int binarySearch(List<Camera.Size> sizes,int targetNum){ int targetIndex; int left = 0,right; int length = sizes.size(); for (right = length-1;left != right;){  int midIndex = (right + left)/2;  int mid = right - left;  Camera.Size size = sizes.get(midIndex);  int midValue = size.width * size.height;  if (targetNum == midValue){  return midIndex;  }  if (targetNum > midValue){  left = midIndex;  }else {  right = midIndex;  }  if (mid <= 1){  break;  } } Camera.Size rightSize = sizes.get(right); Camera.Size leftSize = sizes.get(left); int rightNum = rightSize.width * rightSize.height; int leftNum = leftSize.width * leftSize.height; targetIndex = Math.abs((rightNum - leftNum)/2) > Math.abs(rightNum - targetNum) ? right : left; return targetIndex; } /** * 排序 * @param previewSizes */ private void sortCameraSize(List<Camera.Size> previewSizes){ Collections.sort(previewSizes, new Comparator<Camera.Size>() {  @Override  public int compare(Camera.Size size1, Camera.Size size2) {  int compareHeight = size1.height - size2.height;  if (compareHeight == 0){   return (size1.width == size2.width ? 0 :(size1.width > size2.width ? 1:-1));  }  return compareHeight;  } }); } /** * 获取最佳预览相机Size参数 * * @return */ private Camera.Size getOptimalSize(List<Camera.Size> sizes, int w, int h) { Camera.Size optimalSize = null; float targetRadio = h / (float) w; float optimalDif = Float.MAX_VALUE; //最匹配的比例 int optimalMaxDif = Integer.MAX_VALUE;//最优的最大值差距 for (Camera.Size size : sizes) {  float newOptimal = size.width / (float) size.height;  float newDiff = Math.abs(newOptimal - targetRadio);  if (newDiff < optimalDif) { //更好的尺寸  optimalDif = newDiff;  optimalSize = size;  optimalMaxDif = Math.abs(h - size.width);  } else if (newDiff == optimalDif) {//更好的尺寸  int newOptimalMaxDif = Math.abs(h - size.width);  if (newOptimalMaxDif < optimalMaxDif) {   optimalDif = newDiff;   optimalSize = size;   optimalMaxDif = newOptimalMaxDif;  }  } } return optimalSize; } /** * 缩放 * @param isZoomIn */ public void handleZoom(boolean isZoomIn) { if (mCamera == null) return; Camera.Parameters params = mCamera.getParameters(); if (params == null) return; if (params.isZoomSupported()) {  int maxZoom = params.getMaxZoom();  int zoom = params.getZoom();  if (isZoomIn && zoom < maxZoom) {  zoom++;  } else if (zoom > 0) {  zoom--;  }  params.setZoom(zoom);  mCamera.setParameters(params); } else {  LogUtils.i("zoom not supported"); } } /** * 更换前后置摄像 */ public void changeCameraFacing(SurfaceTexture surfaceTexture, int width, int height) { if(isSupportFrontCamera) {  Camera.CameraInfo cameraInfo = new Camera.CameraInfo();  int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数  for(int i = 0; i < cameraCount; i++) {  Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息  if(cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //现在是后置,变更为前置   if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位为前置   closeCamera();   cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;   CameraUtils.setCameraFacing(context, cameraFacing);   openCamera(surfaceTexture, width, height);   break;   }  } else {//现在是前置, 变更为后置   if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位   closeCamera();   cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;   CameraUtils.setCameraFacing(context, cameraFacing);   openCamera(surfaceTexture, width, height);   break;   }  }  } } else { //不支持摄像机  Toast.makeText(context, "您的手机不支持前置摄像", Toast.LENGTH_SHORT).show(); } } /** * 改变闪光状态 */ public void changeCameraFlash(SurfaceTexture surfaceTexture, int width, int height) { if (!isSupportFlashCamera) {  Toast.makeText(context, "您的手机不支闪光", Toast.LENGTH_SHORT).show();  return; } if(mCamera != null) {  Camera.Parameters parameters = mCamera.getParameters();  if(parameters != null) {  int newState = cameraFlash;  switch (cameraFlash) {   case 0: //自动   parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);   newState = 1;   break;   case 1://open   parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);   newState = 2;   break;   case 2: //close   parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);   newState = 0;   break;  }  cameraFlash = newState;  CameraUtils.setCameraFlash(context, newState);  mCamera.setParameters(parameters);  } } } /** * 拍照 */ public void takePhoto(Camera.PictureCallback callback) { if (mCamera != null) {  try {  mCamera.takePicture(null, null, callback);  } catch(Exception e) {  Toast.makeText(context, "拍摄失败", Toast.LENGTH_SHORT).show();  } } } /** * 开始录制视频 */// public void startMediaRecord(String savePath) {// if (mCamera == null || mProfile == null) return;// mCamera.unlock();// if (mMediaRecorder == null) {//  mMediaRecorder = new MediaRecorder();// }// if (isCameraFrontFacing()) {//  mMediaRecorder.setOrientationHint(270);//  Log.i("wujie","front");// }else// {//  Log.i("wujie","back");//  mMediaRecorder.setOrientationHint(90);// }// mMediaRecorder.reset();// mMediaRecorder.setCamera(mCamera);// mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);// mMediaRecorder.setProfile(mProfile);// mMediaRecorder.setOutputFile(savePath);// try {//  mMediaRecorder.prepare();//  mMediaRecorder.start();// } catch (Exception e) {//  e.printStackTrace();//// }// } /** * 开始录制视频 */ public void startMediaRecord1(String savePath) { if (mCamera == null) {  return; } if (mMediaRecorder == null) {  mMediaRecorder = new MediaRecorder(); } else {  mMediaRecorder.reset(); } if (isCameraFrontFacing()) {  mMediaRecorder.setOrientationHint(270);  Log.i("wujie","front"); }else {  Log.i("wujie","back");  mMediaRecorder.setOrientationHint(90); } mParameters = mCamera.getParameters(); mCamera.unlock(); mMediaRecorder.setCamera(mCamera); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置录像参数 mMediaRecorder.setProfile(CamcorderProfile.get(AppConfig.VIDEOSIZE)); try {  mMediaRecorder.setOutputFile(savePath);  mMediaRecorder.prepare();  mMediaRecorder.start(); } catch (Exception e) { } } /** * 停止录制 */ public void stopMediaRecord() { this.cameraType = 0; stopRecorder(); releaseMediaRecorder(); } private void releaseMediaRecorder() { if (mMediaRecorder != null) {  try {  mMediaRecorder.reset();  mMediaRecorder.release();  mMediaRecorder = null;  mCamera.lock();  } catch (Exception e) {  e.printStackTrace();  LogUtils.i(e);  } } } private void stopRecorder() { if (mMediaRecorder != null) {  try {  mMediaRecorder.stop();  } catch (Exception e) {  e.printStackTrace();  LogUtils.i(e);  } } } public boolean isSupportFrontCamera() { return isSupportFrontCamera; } public boolean isSupportFlashCamera() { return isSupportFlashCamera; } public boolean isCameraFrontFacing() { return cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT; } /** * 设置对焦类型 * @param cameraType */ public void setCameraType(int cameraType) { this.cameraType = cameraType; if (mCamera != null) {//拍摄视频时  if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) {  Camera.Parameters parameters = mCamera.getParameters();  List<String> focusModes = parameters.getSupportedFocusModes();  if (focusModes != null) {   if (cameraType == 0) {   if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);   }   } else {   if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);   }   }  }  } } } public int getCameraFlash() { return cameraFlash; } /** * 对焦 * @param x * @param y */ public void handleFocusMetering(float x, float y) { if(mCamera!=null){  Camera.Parameters params = mCamera.getParameters();  Camera.Size previewSize = params.getPreviewSize();  Rect focusRect = calculateTapArea(x, y, 1f, previewSize);  Rect meteringRect = calculateTapArea(x, y, 1.5f, previewSize);  mCamera.cancelAutoFocus();  if (params.getMaxNumFocusAreas() > 0) {  List<Camera.Area> focusAreas = new ArrayList<>();  focusAreas.add(new Camera.Area(focusRect, 1000));  params.setFocusAreas(focusAreas);  } else {  LogUtils.i("focus areas not supported");  }  if (params.getMaxNumMeteringAreas() > 0) {  List<Camera.Area> meteringAreas = new ArrayList<>();  meteringAreas.add(new Camera.Area(meteringRect, 1000));  params.setMeteringAreas(meteringAreas);  } else {  LogUtils.i("metering areas not supported");  }  final String currentFocusMode = params.getFocusMode();  params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);  mCamera.setParameters(params);  mCamera.autoFocus(new Camera.AutoFocusCallback() {  @Override  public void onAutoFocus(boolean success, Camera camera) {   Camera.Parameters params = camera.getParameters();   params.setFocusMode(currentFocusMode);   camera.setParameters(params);  }  }); } } private Rect calculateTapArea(float x, float y, float coefficient, Camera.Size previewSize) { float focusAreaSize = 300; int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue(); int centerX = (int) (x / previewSize.width - 1000); int centerY = (int) (y / previewSize.height - 1000); int left = clamp(centerX - areaSize / 2, -1000, 1000); int top = clamp(centerY - areaSize / 2, -1000, 1000); RectF rectF = new RectF(left, top, left + areaSize, top + areaSize); return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom)); } private int clamp(int x, int min, int max) { if (x > max) {  return max; } if (x < min) {  return min; } return x; }}

自定义拍摄,拍照按钮:

package com.ses.im.app.chat.newcamera;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.os.Bundle;import android.os.Parcelable;import android.support.v4.view.GestureDetectorCompat;import android.support.v4.view.MotionEventCompat;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import com.ses.im.app.chat.R;/** * 自定义拍照,拍摄按钮 */public class CameraProgressBar extends View { /** * 默认缩小值 */ public static final float DEF_SCALE = 0.75F; /** * 默认缩小值 */ private float scale = DEF_SCALE; /** * 内圆颜色 */ private int innerColor = Color.GRAY; /** * 背景颜色 */ private int backgroundColor = Color.WHITE; /** * 外圆颜色 */ private int outerColor = Color.parseColor("#e9e9e9"); /** * 进度颜色 */ private int progressColor = Color.parseColor("#0ebffa"); /** * 进度宽 */ private int progressWidth = 15; /** * 内圆宽度 */ private int innerRadio = 10; /** * 进度 */ private int progress; /** * 最大进度 */ private int maxProgress = 100; /** * paint */ private Paint backgroundPaint, progressPaint, innerPaint; /** * 圆的中心坐标点, 进度百分比 */ private float sweepAngle; /** * 手识识别 */ private GestureDetectorCompat mDetector; /** * 是否为长按录制 */ private boolean isLongClick; /** * 是否产生滑动 */ private boolean isBeingDrag; /** * 滑动单位 */ private int mTouchSlop; /** * 记录上一次Y轴坐标点 */ private float mLastY; /** * 是否长按放大 */ private boolean isLongScale; public CameraProgressBar(Context context) { super(context); init(context, null); } public CameraProgressBar(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public CameraProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); if (attrs != null) {  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CameraProgressBar);  innerColor = a.getColor(R.styleable.CameraProgressBar_innerColor, innerColor);  outerColor = a.getColor(R.styleable.CameraProgressBar_outerColor, outerColor);  progressColor = a.getColor(R.styleable.CameraProgressBar_progressColor, progressColor);  innerRadio = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_innerRadio, innerRadio);  progressWidth = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_progressWidth, progressWidth);  progress = a.getInt(R.styleable.CameraProgressBar_progresscamera, progress);  scale = a.getFloat(R.styleable.CameraProgressBar_scale, scale);  isLongScale = a.getBoolean(R.styleable.CameraProgressBar_isLongScale, isLongScale);  maxProgress = a.getInt(R.styleable.CameraProgressBar_maxProgress, maxProgress);  a.recycle(); } backgroundPaint = new Paint(); backgroundPaint.setAntiAlias(true); backgroundPaint.setColor(backgroundColor); progressPaint = new Paint(); progressPaint.setAntiAlias(true); progressPaint.setStrokeWidth(progressWidth); progressPaint.setStyle(Paint.Style.STROKE); innerPaint = new Paint(); innerPaint.setAntiAlias(true); innerPaint.setStrokeWidth(innerRadio); innerPaint.setStyle(Paint.Style.STROKE); sweepAngle = ((float) progress / maxProgress) * 360; mDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {  @Override  public boolean onSingleTapConfirmed(MotionEvent e) {  isLongClick = false;  if (CameraProgressBar.this.listener != null) {   CameraProgressBar.this.listener.onClick(CameraProgressBar.this);  }  return super.onSingleTapConfirmed(e);  }  @Override  public void onLongPress(MotionEvent e) {  isLongClick = true;  postInvalidate();  mLastY = e.getY();  if (CameraProgressBar.this.listener != null) {   CameraProgressBar.this.listener.onLongClick(CameraProgressBar.this);  }  } }); mDetector.setIsLongpressEnabled(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (width > height) {  setMeasuredDimension(height, height); } else {  setMeasuredDimension(width, width); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); float circle = width / 2.0f; if (/*isLongScale && */!isLongClick) {  canvas.scale(scale, scale, circle, circle); } //画内圆 float backgroundRadio = circle - progressWidth - innerRadio; canvas.drawCircle(circle, circle, backgroundRadio, backgroundPaint); //画内外环 float halfInnerWidth = innerRadio / 2.0f + progressWidth; RectF innerRectF = new RectF(halfInnerWidth, halfInnerWidth, width - halfInnerWidth, width - halfInnerWidth); canvas.drawArc(innerRectF, -90, 360, true, innerPaint); progressPaint.setColor(outerColor); float halfOuterWidth = progressWidth / 2.0f; RectF outerRectF = new RectF(halfOuterWidth, halfOuterWidth, getWidth() - halfOuterWidth, getWidth() - halfOuterWidth); canvas.drawArc(outerRectF, -90, 360, true, progressPaint); progressPaint.setColor(progressColor); canvas.drawArc(outerRectF, -90, sweepAngle, false, progressPaint); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isLongScale) {  return super.onTouchEvent(event); } this.mDetector.onTouchEvent(event); switch(MotionEventCompat.getActionMasked(event)) {  case MotionEvent.ACTION_DOWN:  isLongClick = false;  isBeingDrag = false;  break;  case MotionEvent.ACTION_MOVE:  if (isLongClick) {   float y = event.getY();   if (isBeingDrag) {   boolean isUpScroll = y < mLastY;   mLastY = y;   if (this.listener != null) {    this.listener.onZoom(isUpScroll);   }   } else {   isBeingDrag = Math.abs(y - mLastY) > mTouchSlop;   }  }  break;  case MotionEvent.ACTION_UP:  case MotionEvent.ACTION_CANCEL:  isBeingDrag = false;  if (isLongClick) {   isLongClick = false;   postInvalidate();   if (this.listener != null) {   this.listener.onLongClickUp(this);   }  }  break;  case MotionEvent.ACTION_POINTER_DOWN:  if (isLongClick) {   if (this.listener != null) {   this.listener.onPointerDown(event.getRawX(), event.getRawY());   }  }  break; } return true; } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); Parcelable superData = super.onSaveInstanceState(); bundle.putParcelable("superData", superData); bundle.putInt("progress", progress); bundle.putInt("maxProgress", maxProgress); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { Bundle bundle = (Bundle) state; Parcelable superData = bundle.getParcelable("superData"); progress = bundle.getInt("progress"); maxProgress = bundle.getInt("maxProgress"); super.onRestoreInstanceState(superData); } /** * 设置进度 * @param progress */ public void setProgress(int progress) { if (progress <= 0) progress = 0; if (progress >= maxProgress) progress = maxProgress; if (progress == this.progress) return; this.progress = progress; this.sweepAngle = ((float) progress / maxProgress) * 360; postInvalidate(); } /** * 还原到初始状态 */ public void reset() { isLongClick = false; this.progress = 0; this.sweepAngle = 0; postInvalidate(); } public int getProgress() { return progress; } public void setLongScale(boolean longScale) { isLongScale = longScale; } public void setMaxProgress(int maxProgress) { this.maxProgress = maxProgress; } private OnProgressTouchListener listener; public void setOnProgressTouchListener(OnProgressTouchListener listener) { this.listener = listener; } /** * 进度触摸监听 */ public interface OnProgressTouchListener { /**  * 单击  * @param progressBar  */ void onClick(CameraProgressBar progressBar); /**  * 长按  * @param progressBar  */ void onLongClick(CameraProgressBar progressBar); /**  * 移动  * @param zoom true放大  */ void onZoom(boolean zoom); /**  * 长按抬起  * @param progressBar  */ void onLongClickUp(CameraProgressBar progressBar); /**  * 触摸对焦  * @param rawX  * @param rawY  */ void onPointerDown(float rawX, float rawY); }}

预览试图页:

package com.ses.im.app.chat.newcamera;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PointF;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.support.v4.view.MotionEventCompat;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewParent;import java.util.concurrent.TimeUnit;import rx.Observable;import rx.Subscriber;import rx.Subscription;/** * 相机预览页 */public class CameraView extends View { /** * 动画时长 */ private static final int ANIM_MILS = 600; /** * 动画每多久刷新一次 */ private static final int ANIM_UPDATE = 30; /** * focus paint */ private Paint paint, clearPaint; private int paintColor = Color.GREEN; /** * 进度订阅 */ private Subscription subscription; /** * focus rectf */ private RectF rectF = new RectF(); /** * focus size */ private int focusSize = 120; private int lineSize = focusSize / 4; /** * 上一次两指距离 */ private float oldDist = 1f; /** * 画笔宽 */ private float paintWidth = 6.0f; /** * s */ private float scale; public CameraView(Context context) { super(context); init(); } public CameraView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CameraView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { paint = new Paint(); paint.setColor(paintColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(paintWidth); clearPaint = new Paint(); clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } @Override public boolean onTouchEvent(MotionEvent event) { int action = MotionEventCompat.getActionMasked(event); if (event.getPointerCount() == 1 && action == MotionEvent.ACTION_DOWN) {  float x = event.getX();  float y = event.getY();  setFoucsPoint(x, y);  if (listener != null) {  listener.handleFocus(x, y);  } } else if (event.getPointerCount() >= 2){  switch (event.getAction() & MotionEvent.ACTION_MASK) {  case MotionEvent.ACTION_POINTER_DOWN:   oldDist = getFingerSpacing(event);   break;  case MotionEvent.ACTION_MOVE:   float newDist = getFingerSpacing(event);   if (newDist > oldDist) {   if (this.listener != null) {    this.listener.handleZoom(true);   }   } else if (newDist < oldDist) {   if (this.listener != null) {    this.listener.handleZoom(false);   }   }   oldDist = newDist;   break;  } } return true; } /** * 计算两点触控距离 * @param event * @return */ private float getFingerSpacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } /** * 设置坐标点(坐标为rawX, rawY) */ public void setFoucsPoint(PointF pointF) { PointF transPointF = transPointF(pointF, this); setFoucsPoint(transPointF.x, transPointF.y); } /** * 设置当前触摸点 * @param x * @param y */ private void setFoucsPoint(float x, float y) { if (subscription != null) {  subscription.unsubscribe(); } rectF.set(x - focusSize, y - focusSize, x + focusSize, y + focusSize); final int count = ANIM_MILS / ANIM_UPDATE; subscription = Observable.interval(ANIM_UPDATE, TimeUnit.MILLISECONDS).take(count).subscribe(new Subscriber<Long>() {  @Override  public void onCompleted() {  scale = 0;  postInvalidate();  }  @Override  public void onError(Throwable e) {  scale = 0;  postInvalidate();  }  @Override  public void onNext(Long aLong) {  float current = aLong== null ? 0 : aLong.longValue();  scale = 1 - current / count;  if (scale <= 0.5f) {   scale = 0.5f;  }  postInvalidate();  } }); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (scale != 0) {  float centerX = rectF.centerX();  float centerY = rectF.centerY();  canvas.scale(scale, scale, centerX, centerY);  canvas.drawRect(rectF, paint);  canvas.drawLine(rectF.left, centerY, rectF.left + lineSize, centerY, paint);  canvas.drawLine(rectF.right, centerY, rectF.right - lineSize, centerY, paint);  canvas.drawLine(centerX, rectF.top, centerX, rectF.top + lineSize, paint);  canvas.drawLine(centerX, rectF.bottom, centerX, rectF.bottom - lineSize, paint); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (subscription != null) {  subscription.unsubscribe(); } } /** * 根据raw坐标转换成屏幕中所在的坐标 * @param pointF * @return */ private PointF transPointF(PointF pointF, View view) { pointF.x -= view.getX(); pointF.y -= view.getY(); ViewParent parent = view.getParent(); if (parent instanceof View) {  return transPointF(pointF, (View) parent); } else {  return pointF; } } private OnViewTouchListener listener; public void setOnViewTouchListener(OnViewTouchListener listener) { this.listener = listener; } public void removeOnZoomListener() { this.listener = null; } public interface OnViewTouchListener { /**  * 对焦  * @param x  * @param y  */ void handleFocus(float x, float y); /**  * 缩放  * @param zoom true放大反之  */ void handleZoom(boolean zoom); }}

视频管理类:

package com.ses.im.app.chat.newcamera;import android.app.Application; import android.media.MediaPlayer; import android.view.Surface;/** * Created by you on 2016/10/24. * 由于拍摄跟播放都关联TextureView,停止播放时要释放mediaplayer */public class MediaPlayerManager {private Application app;private MediaPlayer mPlayer;private MediaPlayerManager(Application app) { this.app = app;}private static MediaPlayerManager INSTANCE;public static MediaPlayerManager getInstance(Application app) { if (INSTANCE == null) { synchronized (CameraManager.class) {  if (INSTANCE == null) {  INSTANCE = new MediaPlayerManager(app);  } } } return INSTANCE;}/** * 播放Media */public void playMedia(Surface surface, String mediaPath) { try { if (mPlayer == null) {  mPlayer = new MediaPlayer();  mPlayer.setDataSource(mediaPath); } else {  if (mPlayer.isPlaying()) {  mPlayer.stop();  }  mPlayer.reset();  mPlayer.setDataSource(mediaPath); } mPlayer.setSurface(surface); mPlayer.setLooping(true); mPlayer.prepareAsync(); mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {  @Override  public void onPrepared(MediaPlayer mp) {  mp.start();  } }); } catch (Exception e) { LogUtils.i(e); }}/** * 停止播放Media */public void stopMedia() { try { if (mPlayer != null) {  if (mPlayer.isPlaying()) {  mPlayer.stop();  }  mPlayer.release();  mPlayer = null; } } catch (Exception e) { LogUtils.i(e); }}}

由于本人上传的demo被csdn弄丢了,想要做微信相机的可以参考陈嘉桐的demo

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表