首页 > 系统 > Android > 正文

Android仿最新微信相机功能

2019-10-22 18:10:23
字体:
来源:转载
供稿:网友

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

大致完成的功能如下:

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

效果图如下: 

Android,微信相机

相关代码如下:

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

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


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表