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

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

以上是 Android仿最新微信相机功能 的全部内容, 来源链接: utcz.com/p/240607.html

回到顶部