使用Camera拍照并保存相片,是调用硬件摄像头进行拍照,相当于自己写一个照相机程序。
有四个步骤:
添加使用照相机的权限和写SD卡的权限
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.UUID;
public class CustomPhoto extends AppCompatActivity {
private Camera camera;
private Preview preview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_custom_photo);
//隐藏窗口标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//设置全屏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
//创建Preview对象
preview = new Preview(this);
setContentView(preview);
}
//检查是否支持照相机
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)){
return true;
}else {
return false;
}
}
@Override
protected void onResume() {
super.onResume();
//0.添加权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
System.out.println("ok");
}else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},1);
}
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED){
System.out.println("OK");
}else {
ActivityCompat.requestPermissions(this,
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}
//1.打开照相机
camera = Camera.open();
preview.setCamera(camera);
}
@Override
protected void onPause() {
super.onPause();
if (camera != null) {
//将camera释放掉,不然其他应用不能使用照相机
camera.release();
//把字段置空,当垃圾回收机制检测到这个字段为空,就会回收这块资源
camera = null;
preview.setCamera(null);
}
}
//回调监听,预览的视图
class Preview extends ViewGroup implements SurfaceHolder.Callback,View.OnClickListener{
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.Size previewSize;
List supportPreviewSizes;
Camera mCamera;
Context context;
public Preview(Context context) {
super(context);
this.context = context;
//2.创建SurfaceView对象
surfaceView = new SurfaceView(context);
surfaceView.setOnClickListener(this);
//2.1把SurfaceView添加到视图中
addView(surfaceView);
//3.添加回调监听
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
supportPreviewSizes = mCamera.getParameters().getSupportedPictureSizes();
//布局变化时重新调整布局
requestLayout();
}
}
//5.1往SD卡存文件
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCamera.startPreview();
String name = "/sdcard/DCIM/"+ UUID.randomUUID()+".jpg";
File pictureFile = new File(name);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
}catch (Exception e) {
e.printStackTrace();
}
}
};
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
//将Camera和SurfaceView关联起来,通知Camera把所有的信息显示到SurfaceView上
mCamera.setPreviewDisplay(holder);
}
}catch (Exception e) {
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//4.预览图片
Camera.Parameters parameters = mCamera.getParameters();
//4.1设置预览尺寸
parameters.setPictureSize(previewSize.width,previewSize.height);
mCamera.setParameters(parameters);
//4.5开始预览
mCamera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
//Camera停止预览
mCamera.stopPreview();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//4.2调整实际预览的尺寸
//试图发生改变并且子视图大于0
if (changed && getChildCount()>0) {
//获取子视图
final View child = getChildAt(0);
int width = r - l;
int height = b -t;
int previewWidth = width;
int previewHeight = height;
if (previewSize != null) {
//预览的窗口大小=实际图像的大小,就不会失帧
previewWidth = previewSize.width;
previewHeight = previewSize.height;
}
//通过判断长宽比,让手机屏幕的宽高比大于采集图像的宽高比,使图像居中
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width-scaledChildWidth)/2,0,(width+scaledChildWidth)/2,height);
}else {
//当图像比屏幕宽时
final int scaleChildHeight = previewHeight * width /previewWidth;
child.layout(0,(height-scaleChildHeight)/2,width,(height+scaleChildHeight)/2);
}
}
}
//4.3选一个最优尺寸
private Camera.Size getOptimalPreviewSize(List sizes,int w,int h) {
double ASPECT_TOLERANCE = 0.1;
double targetRadio = (double)w/h;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double)size.width / size.height;
//选择实际图像的宽高比和预览窗口的宽高比小于0.1的尺寸
if (Math.abs(ratio - targetRadio) > ASPECT_TOLERANCE) {
continue;
}
//选择采集图像高度和实际窗口尽可能一致,尽能保证图像不被放大或缩小
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
//选择采集图像高度和实际窗口尽可能一致,尽能保证图像不被放大或缩小
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
//4.4测量窗口
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = resolveSize(getSuggestedMinimumWidth(),widthMeasureSpec);
int height = resolveSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width,height);
if (supportPreviewSizes != null) {
previewSize = getOptimalPreviewSize(supportPreviewSizes,width,height);
}
}
@Override
public void onClick(View v) {
//5.拍照
mCamera.takePicture(null,null,mPictureCallback);
Toast.makeText(context,"拍照完成",Toast.LENGTH_LONG).show();
}
}
}