美文网首页Android开发Android知识
Android跟着官网学相机

Android跟着官网学相机

作者: stefanJi | 来源:发表于2017-06-01 00:00 被阅读0次

    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能被用来拍图片和视频,通过直接使用系统的相机。

    权限说明

    <uses-permission android:name="android.permission.CAMERA" />
    使用相机就需要生命该权限

    <uses-feature android:name="android.hardware.camera2" />
    这个声明是为了让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) {
    
        }
    }
    

    创建布局

    <FrameLayout 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:id="@+id/camera_preview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <Button
            android:id="@+id/button_capture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="20dp"
            android:text="Capture" />
    
    </FrameLayout>
    

    绑定实时预览到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跟着官网学相机

        本文链接:https://www.haomeiwen.com/subject/anksfxtx.html