前言
对于拍照功能来说,Android 由于版本不同可以使用不同的书写方式,光API就有Camera和Camera2两套,其余的区别还有
API Level | Camera API | Preview View |
---|---|---|
9-13 | Camera1 | SurfaceView |
14-20 | Camera1 | TextureView |
21-23 | Camera2 | TextureView |
24 | Camera2 | SurfaceView |
虽然Android能够向下兼容,但是谁不想使用更新的API和技术,另一方面,Camera API调用起来也不方便,所以对Camera调用的封装势在必行。
github上面有一些,但是使用时经常出现兼容性,适配等问题,直到发现了Google自己封装的CameraView,地址:
https://github.com/google/cameraview
但是使用的时候,你会发现一个问题我怎么设置我拍出照片的分辨率?
官方提供了Ratio,宽高比的属性,但是没有提供设置分辨率的API和属性。
下面我就会介绍怎么修改代码来实现这个,当然你要是不想自己改,可以直接使用我修改好的,地址:
https://github.com/DiskyZhs/CameraView
直接作为lib导入就可以了。
修改源码
查看源码结构
你会发现找到CameraViewImp这个CameraView的接口封装,这里面封装了CameraView对外的接口封装,如下
abstract class CameraViewImpl {
protected final Callback mCallback;
protected final PreviewImpl mPreview;
CameraViewImpl(Callback callback, PreviewImpl preview) {
mCallback = callback;
mPreview = preview;
}
View getView() {
return mPreview.getView();
}
/**
* @return {@code true} if the implementation was able to start the camera session.
*/
abstract boolean start();
abstract void stop();
abstract boolean isCameraOpened();
abstract void setFacing(int facing);
abstract int getFacing();
abstract Set<AspectRatio> getSupportedAspectRatios();
/**
* @return {@code true} if the aspect ratio was changed.
*/
abstract boolean setAspectRatio(AspectRatio ratio);
abstract AspectRatio getAspectRatio();
abstract void setAutoFocus(boolean autoFocus);
abstract boolean getAutoFocus();
abstract void setFlash(int flash);
abstract int getFlash();
abstract void takePicture();
abstract void setDisplayOrientation(int displayOrientation);
interface Callback {
void onCameraOpened();
void onCameraClosed();
void onPictureTaken(byte[] data);
}
}
我们添加接口
/**
* 设置拍摄出来照片的分辨率
*/
abstract void setPictureSize(int width,int height);
然后修改Camer1.java文件,实现Camera1 API下面接口的实现 ,如下:
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.cameraview;
import android.annotation.SuppressLint;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Build;
import android.support.v4.util.SparseArrayCompat;
import android.view.SurfaceHolder;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.atomic.AtomicBoolean;
@SuppressWarnings("deprecation")
class Camera1 extends CameraViewImpl {
private static final int INVALID_CAMERA_ID = -1;
private static final SparseArrayCompat<String> FLASH_MODES = new SparseArrayCompat<>();
static {
FLASH_MODES.put(Constants.FLASH_OFF, Camera.Parameters.FLASH_MODE_OFF);
FLASH_MODES.put(Constants.FLASH_ON, Camera.Parameters.FLASH_MODE_ON);
FLASH_MODES.put(Constants.FLASH_TORCH, Camera.Parameters.FLASH_MODE_TORCH);
FLASH_MODES.put(Constants.FLASH_AUTO, Camera.Parameters.FLASH_MODE_AUTO);
FLASH_MODES.put(Constants.FLASH_RED_EYE, Camera.Parameters.FLASH_MODE_RED_EYE);
}
private int mCameraId;
private final AtomicBoolean isPictureCaptureInProgress = new AtomicBoolean(false);
Camera mCamera;
private Camera.Parameters mCameraParameters;
private final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();
private final SizeMap mPreviewSizes = new SizeMap();
private final SizeMap mPictureSizes = new SizeMap();
private AspectRatio mAspectRatio;
private boolean mShowingPreview;
private boolean mAutoFocus;
private int mFacing;
private int mFlash;
private int mDisplayOrientation;
/**
* 自定义的设置
*/
private Size mSettingPictureSize;
/**
* 自定义的预览的分辨率
*/
private Size mSettingPreviewSize;
Camera1(Callback callback, PreviewImpl preview) {
super(callback, preview);
preview.setCallback(new PreviewImpl.Callback() {
@Override
public void onSurfaceChanged() {
if (mCamera != null) {
setUpPreview();
adjustCameraParameters();
}
}
});
}
@Override
boolean start() {
chooseCamera();
openCamera();
if (mPreview.isReady()) {
setUpPreview();
}
mShowingPreview = true;
mCamera.startPreview();
return true;
}
@Override
void stop() {
if (mCamera != null) {
mCamera.stopPreview();
}
mShowingPreview = false;
releaseCamera();
}
// Suppresses Camera#setPreviewTexture
@SuppressLint("NewApi")
void setUpPreview() {
try {
if (mPreview.getOutputClass() == SurfaceHolder.class) {
final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14;
if (needsToStopPreview) {
mCamera.stopPreview();
}
mCamera.setPreviewDisplay(mPreview.getSurfaceHolder());
if (needsToStopPreview) {
mCamera.startPreview();
}
} else {
mCamera.setPreviewTexture((SurfaceTexture) mPreview.getSurfaceTexture());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
boolean isCameraOpened() {
return mCamera != null;
}
@Override
void setFacing(int facing) {
if (mFacing == facing) {
return;
}
mFacing = facing;
if (isCameraOpened()) {
stop();
start();
}
}
@Override
int getFacing() {
return mFacing;
}
@Override
Set<AspectRatio> getSupportedAspectRatios() {
return mPreviewSizes.ratios();
}
@Override
boolean setAspectRatio(AspectRatio ratio) {
if (mAspectRatio == null || !isCameraOpened()) {
// Handle this later when camera is opened
mAspectRatio = ratio;
return true;
} else if (!mAspectRatio.equals(ratio)) {
final Set<Size> sizes = mPreviewSizes.sizes(ratio);
if (sizes == null) {
throw new UnsupportedOperationException(ratio + " is not supported");
} else {
mAspectRatio = ratio;
adjustCameraParameters();
return true;
}
}
return false;
}
@Override
AspectRatio getAspectRatio() {
return mAspectRatio;
}
@Override
void setAutoFocus(boolean autoFocus) {
if (mAutoFocus == autoFocus) {
return;
}
if (setAutoFocusInternal(autoFocus)) {
mCamera.setParameters(mCameraParameters);
}
}
@Override
boolean getAutoFocus() {
if (!isCameraOpened()) {
return mAutoFocus;
}
String focusMode = mCameraParameters.getFocusMode();
return focusMode != null && focusMode.contains("continuous");
}
@Override
void setFlash(int flash) {
if (flash == mFlash) {
return;
}
if (setFlashInternal(flash)) {
mCamera.setParameters(mCameraParameters);
}
}
@Override
int getFlash() {
return mFlash;
}
@Override
void takePicture() {
if (!isCameraOpened()) {
throw new IllegalStateException(
"Camera is not ready. Call start() before takePicture().");
}
if (getAutoFocus()) {
mCamera.cancelAutoFocus();
mCamera.autoFocus(new