Android 相机Camera API 使用

前面Android调用相机应用拍照及FileProvider使用讲了调用系统已有的相机应用来拍照,其流程还是非常简单的,只要发送一个action为
MediaStore.ACTION_IMAGE_CAPTURE的intent即可。所以一般情况下,你的应用如需要用到拍照功能,直接使调用系统相机应用即可。
除了可以调用系统相机应用来拍照,我们还可以直接控制手机的摄像头来进行拍照,因为Android已经提供了Camera的API。
Camera官方文档:
https://developer.android.com/reference/android/hardware/Camera.html
Camera这个类在API level 21 已经被弃用了,用Camera2代替了。
 
  
Camera2官方文档:
https://developer.android.com/reference/android/hardware/camera2/package-summary.html
Camera2 API使用比Camera API使用稍微复杂点,但是既然是替代Camera的 ,那肯定是有优势的。
这里就简单介绍一下Camera的使用,关于Camera2的使用,最后给出已有项目的链接,可以参考写写demo。
因为平时几乎没有用Camera,这里只是简单记录一下,熟悉一下API。
官方文档:
https://developer.android.com/guide/topics/media/camera.html
直接看代码吧
主界面布局:


    

    

FrameLayout是来放置surfaceView的,surfaceView的作用就是来实时绘制camera的预览数据,前面Android视图SurfaceView的使用一文已经简单的介绍过SurfaceView了,Camera必须要有一个预览的View,可以用SurfaceView,也可以使用TextureView。
关于TextureView的官方文档:
https://developer.android.com/reference/android/view/TextureView.html
接着看:
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        if(checkCameraHardware(this)){
            // Create an instance of Camera
            mCamera = getCameraInstance();
            // Create our Preview view and set it as the content of our activity.
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mPreview);
        }
    }

 /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }

 /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
       // getNumberOfCameras()-1. 2个  0代表后置(默认) 1代表前置
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }

首先检查手机是否带有camera。
然后就获取Camera对象,通过open()方法,这个方法可以带参数的,参数表示打开哪个摄像头,因为现在手机可能不只一个摄像头,通过
getNumberOfCameras
函数可以获取有多个摄像头。
这里的CameraPreview是SurfaceView的子类。
看看CameraPreview类:
package cj.com.camerademo;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

/**
 * 
 */
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
    private String tag = "camerademo";
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Activity context;
    public CameraPreview(Activity context,Camera camera){
        super(context);
        this.context = context;
        mCamera = camera;
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            Camera.Parameters parameters = mCamera.getParameters();
            android.hardware.Camera.CameraInfo info =
                    new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(0, info);
            int rotation = context.getWindowManager().getDefaultDisplay()
                    .getRotation();
            Log.d(tag, "rotation ="+rotation);
            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;
            Log.d(tag, "info.orientation ="+info.orientation);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                result = (info.orientation + degrees) % 360;
                parameters.setRotation(result);//设置存储的图片显示
                result = (360 - result) % 360;  // compensate the mirror  前置默认270

            } else {  // back-facing
                parameters.setRotation((info.orientation - degrees)%360);
                result = (info.orientation - degrees + 360) % 360;  //后置默认90

            }

            Log.d(tag, "result ="+result);

            mCamera.setDisplayOrientation(result);//设置预览显示
            mCamera.setParameters(parameters);

            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(tag, "Error setting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // If your preview can change or rotate, take care of those events here.
                // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
            // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(tag, "Error starting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
}

主要是在SurfaceView的绘制区域创建好了之后,对Camera进行一些操作:
 
  
public CameraPreview(Activity context,Camera camera){
        super(context);
        this.context = context;
        mCamera = camera;
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
mCamera.setPreviewDisplay(holder);
            Camera.Parameters parameters = mCamera.getParameters();
            android.hardware.Camera.CameraInfo info =
                    new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(0, info);
            int rotation = context.getWindowManager().getDefaultDisplay()
                    .getRotation();
            Log.d(tag, "rotation ="+rotation);
            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;
            Log.d(tag, "info.orientation ="+info.orientation);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                result = (info.orientation + degrees) % 360;
                parameters.setRotation(result);//设置存储的图片显示
                result = (360 - result) % 360;  // compensate the mirror  前置默认270

            } else {  // back-facing
                parameters.setRotation((info.orientation - degrees)%360);
                result = (info.orientation - degrees + 360) % 360;  //后置默认90

            }

            Log.d(tag, "result ="+result);

            mCamera.setDisplayOrientation(result);//设置预览显示
            mCamera.setParameters(parameters);

            mCamera.startPreview();

mCamera.setPreviewDisplay(holder);这句代码很关键,表示Camera的预览会显示在该holder对应的SurfaceView上。
后面对camera的一些参数设置一下,参数有很多,这里我只是设置一下预览时显示的方向参数和存储的方向参数,保证了预览和存储的都是正方向位置。
getCameraInfo(0, info);表示获取第一个摄像头的相关信息
最后不要忘了mCamera.startPreview();
点击button进行拍照:
public void click(View view){
        Log.d(tag,"click");
        // get an image from the camera
        mCamera.takePicture(null, null, mPicture);
    }


    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            try {
                File pictureFile = createImageFile();
                if (pictureFile == null){
                    Log.d(tag, "Error creating media file, check storage permissions: ");
                    return;
                }
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
               // mCamera.startPreview();
            } catch (FileNotFoundException e) {
                Log.d(tag, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(tag, "Error accessing file: " + e.getMessage());
            }
        }
    };

将把获取的照片储存到相应文件中。
关于Camera2,参考下面的
https://github.com/googlesamples/android-Camera2Basic



 
  


你可能感兴趣的:(Android开发)