自己才疏学浅工作中总是写相机这一块,所以就总结了一下,如有错误请纠正。
setUp0 相关权限(1)
<!--相机访问权限-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
setUp0 相关权限6.0 (2)
public class CheckPermissionsUtil {
private static final String TAG = "zhangxin";
Context mContext;
public CheckPermissionsUtil(Context mContext) {
this.mContext = mContext;
}
private String[] needPermissions = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.WAKE_LOCK,
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.WRITE_SETTINGS
};
private boolean checkPermission(String... needPermissions) {
for (String permission : needPermissions) {
if (ActivityCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
private void requestPermission(Activity activity, int code, String... needPermissions) {
ActivityCompat.requestPermissions(activity, needPermissions, code);
Log.i(TAG, "request Permission...");
}
public void requestAllPermission(Activity activity) {
if (Build.VERSION.SDK_INT >= 23) {
Log.i(TAG, "request All Permission...");
for (String permission : needPermissions) {
if (!checkPermission(permission)) {
requestPermission(activity, 0, permission);
}
}
}
}
}
setup1 先写一个转换类
public class DisplayUtil {
private static final String TAG = "zhangxin";
/**
* dip转px
* @param context
* @param dipValue
* @return
*/
public static int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(dipValue * scale + 0.5f);
}
/**
* px转dip
* @param context
* @param pxValue
* @return
*/
public static int px2dip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(pxValue / scale + 0.5f);
}
/**
* 获取屏幕宽度和高度,单位为px
* @param context
* @return
*/
public static Point getScreenMetrics(Context context){
DisplayMetrics dm =context.getResources().getDisplayMetrics();
int w_screen = dm.widthPixels;
int h_screen = dm.heightPixels;
Log.i(TAG, "Screen---Width = " + w_screen + " Height = " + h_screen + " densityDpi = " + dm.densityDpi);
return new Point(w_screen, h_screen);
}
/**
* 获取屏幕长宽比
* @param context
* @return
*/
public static float getScreenRate(Context context){
Point P = getScreenMetrics(context);
float H = P.y;
float W = P.x;
return (H/W);
}
}
setUp2 相机预览大小最适尺寸
public class CamParaUtil {
private static final String TAG = "zhangxin";
private CameraSizeComparator sizeComparator = new CameraSizeComparator();
private static CamParaUtil myCamPara = null;
private CamParaUtil(){
}
public static CamParaUtil getInstance(){
if(myCamPara == null){
myCamPara = new CamParaUtil();
return myCamPara;
}
else{
return myCamPara;
}
}
public Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width >= minWidth) && equalRate(s, th)){
Log.i(TAG, "PreviewSize:w = " + s.width + "h = " + s.height);
break;
}
i++;
}
if(i == list.size()){
i = 0;//如果没找到,就选最小的size
}
return list.get(i);
}
public Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width >= minWidth) && equalRate(s, th)){
Log.i(TAG, "PictureSize : w = " + s.width + "h = " + s.height);
break;
}
i++;
}
if(i == list.size()){
i = 0;//如果没找到,就选最小的size
}
return list.get(i);
}
public boolean equalRate(Size s, float rate){
float r = (float)(s.width)/(float)(s.height);
if(Math.abs(r - rate) <= 0.03)
{
return true;
}
else{
return false;
}
}
public class CameraSizeComparator implements Comparator<Camera.Size>{
public int compare(Size lhs, Size rhs) {
// TODO Auto-generated method stub
if(lhs.width == rhs.width){
return 0;
}
else if(lhs.width > rhs.width){
return 1;
}
else{
return -1;
}
}
}
/**打印支持的previewSizes
* @param params
*/
public void printSupportPreviewSize(Camera.Parameters params){
List<Size> previewSizes = params.getSupportedPreviewSizes();
for(int i=0; i< previewSizes.size(); i++){
Size size = previewSizes.get(i);
Log.i(TAG, "previewSizes:width = "+size.width+" height = "+size.height);
}
}
/**打印支持的pictureSizes
* @param params
*/
public void printSupportPictureSize(Camera.Parameters params){
List<Size> pictureSizes = params.getSupportedPictureSizes();
for(int i=0; i< pictureSizes.size(); i++){
Size size = pictureSizes.get(i);
Log.i(TAG, "pictureSizes:width = "+ size.width
+" height = " + size.height);
}
}
/**打印支持的聚焦模式
* @param params
*/
public void printSupportFocusMode(Camera.Parameters params){
List<String> focusModes = params.getSupportedFocusModes();
for(String mode : focusModes){
Log.i(TAG, "focusModes--" + mode);
}
}
}
setUp3 相机工具类
public class CameraInterface {
private static final String TAG = "zhangxin";
private Context context;
private Camera.Parameters parameters;
private boolean isPreview = false;
private float mPreviewRate = -1f;
private boolean autoFoucs;
private int mCameraId = -1;
private Camera camera;
private static CameraInterface cameraInterface;
public interface CameraOpenCallback {
public void cameraHasOpen();
}
public CameraInterface() {
}
public static CameraInterface getInstance() {
if (cameraInterface == null) {
cameraInterface = new CameraInterface();
}
return cameraInterface;
}
/*打开相机*/
public void doOpenCamera(CameraOpenCallback callback, int mCameraId) {
Log.i(TAG, "日志输出-->: 打开相机");
camera = Camera.open(mCameraId);
this.mCameraId = mCameraId;
if (callback != null) {
callback.cameraHasOpen();
}
}
/*开启预览*/
public void doStartPreview(SurfaceHolder holder, float mPreviewRate) {
Log.i(TAG, "日志输出-->: 开始预览");
if (isPreview) {
camera.stopPreview();
return;
}
if (camera != null) {
parameters = camera.getParameters();
/*设置拍照存储格式*/
parameters.setPictureFormat(PixelFormat.JPEG);
CamParaUtil.getInstance().printSupportPictureSize(parameters);
CamParaUtil.getInstance().printSupportPreviewSize(parameters);
/*设置预览和拍照大小*/
Camera.Size picSize = CamParaUtil.getInstance().getPropPictureSize(parameters.getSupportedPictureSizes(), mPreviewRate, 800);
Camera.Size preSize = CamParaUtil.getInstance().getPropPreviewSize(parameters.getSupportedPreviewSizes(), mPreviewRate, 800);
camera.setDisplayOrientation(90);
/*定焦*/
CamParaUtil.getInstance().printSupportFocusMode(parameters);
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains("continuous-video")) {
parameters.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
Log.e(TAG, "输出信息-->: 开启对焦成功");
}
camera.setParameters(parameters);
try {
camera.setPreviewDisplay(holder);
/*开启预览*/
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "输出信息-->: 开启预览失败" + e.getMessage());
}
isPreview = true;
autoFoucs = true;
camera.autoFocus(autoFocusCallback);
this.mPreviewRate = mPreviewRate;
parameters = camera.getParameters(); //重新get一次
Log.i(TAG, "最终设置:PreviewSize--With = " + parameters.getPreviewSize().width + "Height = " + parameters.getPreviewSize().height);
Log.i(TAG, "最终设置:PictureSize--With = " + parameters.getPictureSize().width + "Height = " + parameters.getPictureSize().height);
}
}
/*停止预览*/
public void doStopCamera() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
isPreview = false;
mPreviewRate = -1f;
camera.release();
;
camera = null;
}
}
/*拍照*/
public void doTakePicture() {
if (isPreview && (camera != null)) {
camera.takePicture(mShutterCallback /*或者null*/, null, mJpegPictureCallback);
}
}
/*获取Camera.Parameters实例*/
public Camera.Parameters getCameraParams() {
if (camera != null) {
parameters = camera.getParameters();
return parameters;
}
return null;
}
/*获取Camera实例*/
public Camera getCameraDevice() {
return camera;
}
/*获取CameraId*/
public int getmCameraId() {
return mCameraId;
}
/*自动对焦*/
Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success)
Log.e(TAG, "输出信息-->: 对焦成功" + success);
else {
Log.e(TAG, "输出信息-->: 对焦失败" + success);
camera.autoFocus(autoFocusCallback);
}
}
};
/*为了实现拍照的快门声音及拍照保存照片需要下面三个回调变量*/
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
//快门按下的回调,在这里我们可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。
{
public void onShutter() {
// TODO Auto-generated method stub
Log.i(TAG, "myShutterCallback:onShutter...");
}
};
Camera.PictureCallback mRawCallback = new Camera.PictureCallback()
// 拍摄的未压缩原数据的回调,可以为null
{
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.i(TAG, "myRawCallback:onPictureTaken...");
}
};
Camera.PictureCallback mJpegPictureCallback = new Camera.PictureCallback()
//对jpeg图像数据的回调,最重要的一个回调
{
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.i(TAG, "myJpegCallback:onPictureTaken...");
Bitmap b = null;
if (null != data) {
b = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
camera.stopPreview();
isPreview = false;
}
//保存图片到sdcard
if (null != b) {
//设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。
//图片竟然不能旋转了,故这里要旋转下
Bitmap rotaBitmap = ImageUtil.getRotateBitmap(b, 90.0f);
FileUtil.saveBitmap(rotaBitmap);
}
//再次进入预览
camera.startPreview();
isPreview = true;
}
};
/*坐标转换*/
public 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));
}
public int clamp(int x, int min, int max) {
if (x > max) {
return max;
}
if (x < min) {
return min;
}
return x;
}
/*设置对焦区域*/
public void doFouce(MotionEvent event, Camera camera) {
Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1.5f, parameters.getPreviewSize());
camera.cancelAutoFocus();
if (parameters.getMaxNumFocusAreas() > 0) {
List<Camera.Area> fouce = new ArrayList<>();
fouce.add(new Camera.Area(focusRect, 800));
parameters.setFocusAreas(fouce);
} else {
Log.e(TAG, "输出信息-->: 不支持测光");
}
final String currentFocusMode = parameters.getFocusMode();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
camera.setParameters(parameters);
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
Camera.Parameters params = camera.getParameters();
params.setFocusMode(currentFocusMode);
camera.setParameters(params);
}
});
}
/*计算两指尖距离*/
public 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);
}
/*设置缩放*/
public void doZoom(boolean isZoomIn,Camera camera){
if (parameters.isZoomSupported()){
int MaxZoom = parameters.getMaxZoom();
int zoom = parameters.getZoom();
if (isZoomIn && zoom <MaxZoom){
zoom++;
}else if (zoom >0 ){
zoom--;
}
parameters.setZoom(zoom);
camera.setParameters(parameters);
}else {
Log.e(TAG, "输出信息-->: 缩放失败" );
}
}
}
setUp4 相机预览界面
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "zhangxin";
private Context context;
private SurfaceHolder holder;
private float oldDist = 1f;
private FoucsView mFoucsView;
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e(TAG, "surfaceCreated: ");
try {
CameraInterface.getInstance().doOpenCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG, "surfaceChanged: ");
try {
CameraInterface.getInstance().doStartPreview(holder, 1.333f);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed: ");
CameraInterface.getInstance().doStopCamera();
}
public SurfaceHolder getSurfaceHolder() {
return holder;
}
/*手指监听*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount() == 1) {
CameraInterface.getInstance().doFouce(event,CameraInterface.getInstance().getCameraDevice());
}else {
switch (event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = CameraInterface.getInstance().getFingerSpacing(event);
break;
case MotionEvent.ACTION_MOVE:
float newDist = CameraInterface.getInstance().getFingerSpacing(event);
if (newDist > oldDist){
CameraInterface.getInstance().doZoom(true,CameraInterface.getInstance().getCameraDevice());
}else {
CameraInterface.getInstance().doZoom(false,CameraInterface.getInstance().getCameraDevice());
}
oldDist = newDist;
break;
}
}
return true;
}
}
setUp5 相机调用activity
public class CameraActivity extends AppCompatActivity{
private static final String TAG = "zhangxin";
float previewRate = -1f;
@BindView(R.id.camera_surfaceview)
CameraSurfaceView cameraSurfaceview;
@BindView(R.id.btn_take_Photo)
Button btnTakePhoto;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
CheckPermissionsUtil checkPermissionsUtil = new CheckPermissionsUtil(this);
checkPermissionsUtil.requestAllPermission(this);
ButterKnife.bind(this);
initViewParams();
}
private void initViewParams() {
ViewGroup.LayoutParams params = cameraSurfaceview.getLayoutParams();
Point p = DisplayUtil.getScreenMetrics(this);
params.width = p.x;
params.height = p.y;
previewRate = DisplayUtil.getScreenRate(this); //默认全屏的比例预览
cameraSurfaceview.setLayoutParams(params);
}
@OnClick(R.id.btn_take_Photo)
public void takePhoto(){
takePicture();
}
private void takePicture() {
CameraInterface.getInstance().doTakePicture();
}
private void switchCamera() {
int newId = (CameraInterface.getInstance().getmCameraId() + 1) % 2;
CameraInterface.getInstance().doStopCamera();
CameraInterface.getInstance().doOpenCamera(null, newId);
CameraInterface.getInstance().doStartPreview(cameraSurfaceview.getSurfaceHolder(), previewRate);
}
setUp6 布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.alva.zx.camera.zcamera.CameraSurfaceView
android:id="@+id/camera_surfaceview"
android:layout_width="0dip"
android:layout_height="0dip" />
<Button
android:id="@+id/btn_take_Photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:text="拍照" />
</FrameLayout>
</RelativeLayout>
网友评论