Android跟着官网学相机

Android使用相机

有两种方式:

  1. 使用已经存在的Apps
  2. 构建自己的相机App

基础步骤

安卓系统提供了android.hardware.caemra2API和camera intent去拍摄图片或者视频

以下是相关的类:

  • android.hardware.camera2

    这个包提供api去控制相机设备。可以通过它使用拍照片和视频。

  • Camera

    这个类提供已经过时的控制相机设备的api。

  • SurfaceView

    这个类被用于提供给用户一个实时的相机预览。

  • MediaRecorder

    这个类被用来从相机记录视频。

  • Intent

    MediaStroe.ACTION_IMAGE_CAPTUREMediaStore.ACTION_VIDEO_CAPTURE能被用来拍图片和视频,通过直接使用系统的相机。

权限说明


使用相机就需要生命该权限


这个声明是为了让GooglePlay在展示App时,避免不支持相机的设备。

还有:(如果需要)

  • 储存权限
  • 录制权限
  • 定位权限

建立一个自己的相机

通常步骤:

  1. 检测和访问相机
  2. 创建一个预览相机视图的类,继承SurfaceView
  3. 建立一个预览布局
  4. 为拍照设置监听
  5. 拍照并且保存到文件
  6. 释放相机

检测和访问相机

检查设备是否有相机

private boolean checkCameraHardware(Context context) {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

获取相机实例


    private Camera getCameraInstance() {
        Camera camera = null;
        try {
            camera = Camera.open();
        } catch (Exception e) {

        }
        return camera;
    }

在Android2.3以上版本,可以通过使用Camera.open(int)去得到前置或者后置相机

创建实时预览View

通过继承SurfaceView能够实时显示从相机返回的数据

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        //添加一个SurfaceHolder.CallBack,能够在SurfaceView被创建和销毁时通知我们
        mHolder = getHolder();
        mHolder.addCallback(this);
        //声明Surface使用的数据由其他数据提供
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //Surface已经被创建,现在让相机开始预览
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.e("TAG", e.getMessage());
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        //如果预览窗口被改变和旋转
        //确保停止之前,重新确定大小和格式
        if (mHolder.getSurface() == null) {
            //预览视图不存在,则结束
            return;
        }

        //在发生改变之前,停止预览
        try {
            mCamera.stopPreview();
        } catch (Exception e) {

        }

        //设置预览的尺寸和旋转

        holder.setFixedSize(width, height);
        holder.setFormat(format);

        //开始预览伴随新的设置
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {

        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
}

创建布局



    

    

绑定实时预览到Activity

public class MainActivity extends AppCompatActivity {
    private Camera mCamera;
    private CameraPreview mCameraPreview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (!checkCameraHardware(this)) {
            Toast.makeText(this, "No Camera", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);
        FrameLayout preView = (FrameLayout) findViewById(R.id.camera_preview);
        preView.addView(mCameraPreview);
    }

    private Camera getCameraInstance() {
        Camera camera = null;
        try {
            camera = Camera.open();
        } catch (Exception e) {
            Log.e("TAG", e.getMessage());
        }
        return camera;
    }

    private boolean checkCameraHardware(Context context) {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }
}

拍照并储存

   private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            File picFile = getOutputFile(MEDIA_TYPE_IMAGE);
            if (picFile == null) {
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(picFile);
                fos.write(data);
                fos.close();
                Toast.makeText(MainActivity.this, "take photo", Toast.LENGTH_SHORT).show();
            } catch (FileNotFoundException e) {
                Log.i("TAG", "file not found");
            } catch (IOException e) {
                Log.i("TAG", e.getMessage());
            }
        }
    };

    private File getOutputFile(int type) {
        //为了安全,应先检查SD卡是否存在
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)) {
            return null;
        }
        File mediaDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "CAMERA LEARN");

        if (!mediaDir.exists()) {
            if (!mediaDir.mkdir()) {
                Log.i("TAG", "make dir failed");
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;

        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(mediaDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
        } else if (type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }
findViewById(R.id.button_capture).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.takePicture(null, null, pictureCallback);
            }
        });

现在之后能成功拍照保存,但是相机实时显示的方向有问题,明晚继续学习。_

你可能感兴趣的:(Android跟着官网学相机)