android简单的自定义相机
项目需求
公司手环有一个功能是点击手环(手环发送命令给手机)手机自动拍照,如果是调用系统相机不知道代码中怎么自动点击拍照键(毕竟系统功能全,知道的同学还望告知一二),所以只好自己写个最简单的相机了,此相机只拍照没其他功能(技术太菜了其他不会整),虽然功能简单,坑也不少啊!
代码
public class CameraActivity extends BaseActivity implements SurfaceHolder.Callback, View.OnClickListener {
@BindView(R.id.surfaceView)
SurfaceView surfaceView;
//照片缩略图
@BindView(R.id.camera_photo)
FullPhotoView cameraPhoto;
//闪光灯图片
@BindView(R.id.flash)
ImageView flash;
//导航栏
@BindView(R.id.common_top_bar)
CommonTopBar mCommonTopBar;
private SurfaceHolder mHolder;
private int mCameraId = 0;
private Camera mCamera;
//屏幕宽高
private int screenWidth;
//延迟时间
private boolean isview = false;
private int picHeight;
//闪光灯图标
private static final int[] FLASH_ICONS = {
R.drawable.ic_flash_off,
R.drawable.ic_flash_on,
R.drawable.ic_flash_auto,
};
//闪光灯模式 0:关闭 1: 开启 2: 自动
private int light_num = 2;
private static final String[] FLASH_OPTIONS = {
Camera.Parameters.FLASH_MODE_OFF,
Camera.Parameters.FLASH_MODE_TORCH,
Camera.Parameters.FLASH_MODE_AUTO,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
//状态栏工具
StatusBarUtil.setColor(this, getResources().getColor(R.color.transparent_22000000), 0);
initView();
EventBus.getDefault().register(this);
}
private void initView() {
mHolder = surfaceView.getHolder();
mHolder.addCallback(this);
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
}
@Override
public void initParams() {
super.initParams();
mCommonTopBar.setUpNavigateMode();
mCommonTopBar.setTitle(R.string.activity_camera);
mCommonTopBar.setUpImgOption(R.drawable.ic_party_mode_white_24dp, new View.OnClickListener() {
@Override
public void onClick(View view) {
switchCamera();
}
});
}
@OnClick({R.id.camera_take, R.id.flash})
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.camera_take:
takePhoto();
break;
//闪光灯
case R.id.flash:
if (mCameraId == 1) { //前置
Toast.makeText(mContext, "请切换为后置摄像头开启闪光灯", Toast.LENGTH_SHORT).show();
return;
}
Camera.Parameters parameters = mCamera.getParameters();
light_num = (light_num + 1) % 3;
parameters.setFlashMode(FLASH_OPTIONS[light_num]);
flash.setImageResource(FLASH_ICONS[light_num]);
mCamera.setParameters(parameters);
break;
}
}
//前后相机切换
public void switchCamera() {
releaseCamera();
mCameraId = (mCameraId + 1) % mCamera.getNumberOfCameras();
mCamera = getCamera(mCameraId);
if (mHolder != null) {
startPreview(mCamera, mHolder);
}
}
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
mCamera = getCamera(mCameraId);
if (mHolder != null) {
startPreview(mCamera, mHolder);
}
}
}
@Override
protected void onStop() {
super.onStop();
releaseCamera();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
//获取相机
private Camera getCamera(int id) {
Camera camera = null;
try {
camera = Camera.open(id);
} catch (Exception e) {
}
return camera;
}
//开始预览
private void startPreview(Camera camera, SurfaceHolder holder) {
try {
setCamera(camera);
camera.setPreviewDisplay(holder);
//亲测的一个方法 基本覆盖所有手机 将预览矫正
CameraUtil.getInstance().setCameraDisplayOrientation(this, mCameraId, camera);
camera.startPreview();
isview = true;
} catch (IOException e) {
e.printStackTrace();
}
}
private void takePhoto() {
if (isview) {
switch (light_num) {
case 0:
//关闭
CameraUtil.getInstance().turnLightOff(mCamera);
break;
case 1:
CameraUtil.getInstance().turnLightOn(mCamera);
break;
case 2:
//自动
CameraUtil.getInstance().turnLightAuto(mCamera);
break;
}
takePicture();
isview = false;
}
}
private void takePicture() {
mCamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
BleLog.e("onPictureTaken:" + data.length);
isview = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//旋转方向
Matrix matrix = new Matrix();
matrix.preRotate(90);
if (mCameraId != 0) {
matrix.preRotate(180);
}
Bitmap rotaBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap bit = GetRoundedCornerBitmap(Bitmap.createScaledBitmap(rotaBitmap, cameraPhoto.getWidth(), cameraPhoto.getHeight(), true));
cameraPhoto.setImageBitmap(bit);
final Bitmap saveBitmap = CameraUtil.getInstance().setTakePicktrueOrientation(mCameraId, bitmap);
new Handler().post(new Runnable() {
@Override
public void run() {
cameraPhoto.setUri(Util.savePic(mContext, saveBitmap));
}
});
startPreview(mCamera, mHolder);
}
});
}
//转圆角矩形
public Bitmap GetRoundedCornerBitmap(Bitmap bitmap) {
try {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
final float roundPx = 15;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.BLACK);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, src, rect, paint);
return output;
} catch (Exception e) {
return bitmap;
}
}
//相机参数设置
private void setCamera(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// Autofocus mode is supported 自动对焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
//这里第三个参数为最小尺寸 getPropPreviewSize方法会对从最小尺寸开始升序排列 取出所有支持尺寸的最小尺寸
Camera.Size previewSize = CameraUtil.getInstance().getPropSizeForHeight(parameters.getSupportedPreviewSizes(), screenWidth);
parameters.setPreviewSize(previewSize.width, previewSize.height);
Camera.Size pictrueSize = CameraUtil.getInstance().getPropSizeForHeight(parameters.getSupportedPictureSizes(), screenWidth);
parameters.setPictureSize(pictrueSize.width, pictrueSize.height);
camera.setParameters(parameters);
/**
* 设置surfaceView的尺寸 因为camera默认是横屏,所以取得支持尺寸也都是横屏的尺寸
* 我们在startPreview方法里面把它矫正了过来,但是这里我们设置设置surfaceView的尺寸的时候要注意 previewSize.height<previewSize.width
* previewSize.width才是surfaceView的高度
* 一般相机都是屏幕的宽度 这里设置为屏幕宽度 高度自适应 你也可以设置自己想要的大小
*/
picHeight = screenWidth * previewSize.width / previewSize.height;
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(screenWidth, picHeight);
//这里当然可以设置拍照位置 比如居中 我这里就置顶了
//params.gravity = Gravity.CENTER;
surfaceView.setLayoutParams(params);
}
//释放资源
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startPreview(mCamera, holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.stopPreview();
startPreview(mCamera, holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
//接收到手环的拍照指令
@Subscribe(threadMode = ThreadMode.MAIN)
public void getBleData(byte[] data) {
if (data[0] == 0x07 && data[2] == 0x06) {
takePhoto();
}
}
}
public class CameraUtil {
private static CameraUtil myCamPara = null;
private CameraUtil() {
}
public static CameraUtil getInstance() {
if (myCamPara == null) {
myCamPara = new CameraUtil();
}
return myCamPara;
}
//保证预览方向正确
public void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
public Bitmap setTakePicktrueOrientation(int id, Bitmap bitmap) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(id, info);
bitmap = rotaingImageView(id, info.orientation, bitmap);
return bitmap;
}
/**
* 把相机拍照返回照片转正
* @param angle 旋转角度
* @return bitmap 图片
*/
public Bitmap rotaingImageView(int id, int angle, Bitmap bitmap) {
//旋转图片 动作
Matrix matrix = new Matrix();
matrix.postRotate(angle);
//加入翻转 把相机拍照返回照片转正
if (id == 1) {
matrix.postScale(-1, 1);
}
// 创建新的图片
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizedBitmap;
}
/**
* 获取所有支持的返回视频尺寸
*/
public Size getPropSizeForHeight(List<Size> list, int minHeight) {
Collections.sort(list, new CameraAscendSizeComparatorForHeight());
int i = 0;
for (Size s : list) {
if ((s.height >= minHeight)) {
break;
}
i++;
}
if (i == list.size()) {
i = 0;//如果没找到,就选最小的size
}
return list.get(i);
}
//升序 按照高度
public class CameraAscendSizeComparatorForHeight implements Comparator<Size> {
public int compare(Size lhs, Size rhs) {
if (lhs.height == rhs.height) {
return 0;
} else if (lhs.height > rhs.height) {
return 1;
} else {
return -1;
}
}
}
//打开闪关灯
public void turnLightOn(Camera mCamera) {
if (mCamera == null) {
return;
}
Camera.Parameters parameters = mCamera.getParameters();
if (parameters == null) {
return;
}
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes == null) {
return;
}
String flashMode = parameters.getFlashMode();
if (!Camera.Parameters.FLASH_MODE_ON.equals(flashMode)) {
if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
}
}
}
//自动模式闪光灯
public void turnLightAuto(Camera mCamera) {
if (mCamera == null) {
return;
}
Camera.Parameters parameters = mCamera.getParameters();
if (parameters == null) {
return;
}
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes == null) {
return;
}
String flashMode = parameters.getFlashMode();
if (!Camera.Parameters.FLASH_MODE_AUTO.equals(flashMode)) {
if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
}
}
}
// 关闭闪光灯
public void turnLightOff(Camera mCamera) {
if (mCamera == null) {
return;
}
Camera.Parameters parameters = mCamera.getParameters();
if (parameters == null) {
return;
}
List<String> flashModes = parameters.getSupportedFlashModes();
String flashMode = parameters.getFlashMode();
if (flashModes == null) {
return;
}
if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
}
}
}
}