美文网首页viewandroid工具
Android Camera2 拍照入门学习

Android Camera2 拍照入门学习

作者: 英勇青铜5 | 来源:发表于2016-09-25 14:52 被阅读27388次

    学习资料:


    2017 月 12 月 16 号
    补充一个学习资料


    20170513 16:25

    注意权限,注意权限,注意权限

    5.0在配置文件申明一下就好,6.0以上的系统需要考虑动态权限问题

    评论里2个同学说因为权限问导致了黑屏,排查代码却没有发现问题,对刚刚接触安卓不久的同学造成困扰,还耽搁了不少时间,抱歉了

    具体的相机设置、预览控件大小以及样张的参数之类的,需要根据自己的手机、系统做些相应调整。我测试手机是5.1系统,使用博客中的代码只是简单地拍了个照片测试了下,除了照片样张质量一般外,暂时没有发现其他问题。我并没有在项目中实际开发过拍照相关的功能,这里我也是简单地学习下。若哪位同学发现代码里的问题,请留言指出,免得造成误导浪费时间


    Android 5.0(21)之后,android.hardware.Camera被废弃(下面称为Camera1),还有一个android.graphics.Camera,这个android.graphics.Camera不是用来照相的,是用来处理图像的,可以做出3D的图像效果之类的,之前的Camera1则由android.hardware.Camera2来代替

    Camera2支持RAW输出,可以调节曝光,对焦模式,快门等,功能比原先Camera强大


    1. Camera1使用

    使用步骤:

    1. 调用Camera.open(),打开相机,默认为后置,可以根据摄像头ID来指定打开前置还是后置
    2. 调用Camera.getParameters()得到一个Camera.Parameters对象
    3. 使用步骤2得到的Camera.Parameters对象,对拍照参数进行设置
    4. 调用Camera.setPreviewDispaly(SurfaceHolder holder),指定使用哪个SurfaceView来显示预览图片
    5. 调用Camera.startPreview()方法开始预览取景
    6. 调用Camera.takePicture()方法进行拍照
    7. 拍照结束后,调用Camera.stopPreview()结束取景预览,之后再replease()方法释放资源

    这几个步骤从疯狂Android讲义中学到


    1.1 简单使用

    使用SurfaceView进行取景的预览,点击屏幕进行拍照,用ImageView来展示拍的照片

    取景 拍照预览

    想买关于操作系统和C的书看,知乎很多人推荐这两本,就买了。然而,深入理解操作系统买早了,啃不动,看不懂

    布局文件:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <SurfaceView
            android:id="@+id/surface_view_camera2_activity"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <ImageView
            android:id="@+id/iv_show_camera2_activity"
            android:layout_width="180dp"
            android:layout_height="320dp"
            android:visibility="gone"
            android:layout_centerInParent="true"
            android:scaleType="centerCrop" />
    </RelativeLayout>
    

    Activity代码:

    public class CameraActivity extends AppCompatActivity implements View.OnClickListener {
    
        private SurfaceView mSurfaceView;
        private SurfaceHolder mSurfaceHolder;
        private Camera mCamera;
        private ImageView iv_show;
        private int viewWidth, viewHeight;//mSurfaceView的宽和高
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_camera2);
            initView();
        }
    
        /**
         * 初始化控件
         */
        private void initView() {
            iv_show = (ImageView) findViewById(R.id.iv_show_camera2_activity);
            //mSurfaceView
            mSurfaceView = (SurfaceView) findViewById(R.id.surface_view_camera2_activity);
            mSurfaceHolder = mSurfaceView.getHolder();
            // mSurfaceView 不需要自己的缓冲区
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            // mSurfaceView添加回调
            mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
                    // 初始化Camera
                    initCamera();
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
                    // 释放Camera资源
                    if (mCamera != null) {
                        mCamera.stopPreview();
                        mCamera.release();
                    }
                }
            });
            //设置点击监听
            mSurfaceView.setOnClickListener(this);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            if (mSurfaceView != null) {
                viewWidth = mSurfaceView.getWidth();
                viewHeight = mSurfaceView.getHeight();
            }
        }
    
        /**
         * SurfaceHolder 回调接口方法
         */
        private void initCamera() {
            mCamera = Camera.open();//默认开启后置
            mCamera.setDisplayOrientation(90);//摄像头进行旋转90°
            if (mCamera != null) {
                try {
                    Camera.Parameters parameters = mCamera.getParameters();
                    //设置预览照片的大小
                    parameters.setPreviewFpsRange(viewWidth, viewHeight);
                    //设置相机预览照片帧数
                    parameters.setPreviewFpsRange(4, 10);
                    //设置图片格式
                    parameters.setPictureFormat(ImageFormat.JPEG);
                    //设置图片的质量
                    parameters.set("jpeg-quality", 90);
                    //设置照片的大小
                    parameters.setPictureSize(viewWidth, viewHeight);
                    //通过SurfaceView显示预览
                    mCamera.setPreviewDisplay(mSurfaceHolder);
                    //开始预览
                    mCamera.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 点击回调方法
         */
        @Override
        public void onClick(View v) {
            if (mCamera == null) return;
            //自动对焦后拍照
            mCamera.autoFocus(autoFocusCallback);
        }
    
    
        /**
         * 自动对焦 对焦成功后 就进行拍照
         */
        Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if (success) {//对焦成功
                  
                    camera.takePicture(new Camera.ShutterCallback() {//按下快门
                        @Override
                        public void onShutter() {
                          //按下快门瞬间的操作
                        }
                    }, new Camera.PictureCallback() {
                        @Override
                        public void onPictureTaken(byte[] data, Camera camera) {//是否保存原始图片的信息
    
                        }
                    }, pictureCallback);
                }
            }
        };
        /**
         * 获取图片
         */
        Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                final Bitmap resource = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (resource == null) {
                    Toast.makeText(CameraActivity.this, "拍照失败", Toast.LENGTH_SHORT).show();
                }
                final Matrix matrix = new Matrix();
                matrix.setRotate(90);
                final Bitmap bitmap = Bitmap.createBitmap(resource, 0, 0, resource.getWidth(), resource.getHeight(), matrix, true);
                if (bitmap != null && iv_show != null && iv_show.getVisibility() == View.GONE) {
                    mCamera.stopPreview();
                    iv_show.setVisibility(View.VISIBLE);
                    mSurfaceView.setVisibility(View.GONE);
                    Toast.makeText(CameraActivity.this, "拍照", Toast.LENGTH_SHORT).show();
                    iv_show.setImageBitmap(bitmap);
                }
            }
        };
    }
    

    权限:

    <uses-permission android:name="android.permission.CAMERA" />
    

    在获得图片后,想要显示的效果是照片是竖直显示,resource显示的却是逆时针旋转了90°,照片是横着的,就使用matrix.setRotate(90)进行旋转


    2. Camera2

    Camera2拍照示意图

    这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送 Capture 请求,而摄像头会返回 CameraMetadata。这一切建立在一个叫作 CameraCaptureSession 的会话中。

    camera2中主要的类

    以上从极客学院android.hardware.camera2 使用指南摘抄

    • CameraManaer 摄像头管理器,用于检测摄像头,打开系统摄像头,调用CameraManager.getCameraCharacteristics(String)可以获取指定摄像头的相关特性
    • CameraCharacteristics 摄像头的特性
    • CameraDevice 摄像头,类似android.hardware.Camera也就是Camera1Camera
    • CameraCaptureSession 这个对象控制摄像头的预览或者拍照,setRepeatingRequest()开启预览,capture()拍照,CameraCaptureSession提供了StateCallback、CaptureCallback两个接口来监听CameraCaptureSession的创建和拍照过程。
    • CameraRequest和CameraRequest.Builder,预览或者拍照时,都需要一个CameraRequest对象。CameraRequest表示一次捕获请求,用来对z照片的各种参数设置,比如对焦模式、曝光模式等。CameraRequest.Builder用来生成CameraRequest对象。

    以上从肾虚将军的android camera2 详解说明摘抄


    2.1 简单使用

    使用的依然是SurfaceView来进行展示预览

    主要思路:

    1. 获得摄像头管理器CameraManager mCameraManagermCameraManager.openCamera()来打开摄像头
    2. 指定要打开的摄像头,并创建openCamera()所需要的CameraDevice.StateCallback stateCallback
    3. CameraDevice.StateCallback stateCallback中调用takePreview(),这个方法中,使用CaptureRequest.Builder创建预览需要的CameraRequest,并初始化了CameraCaptureSession,最后调用了setRepeatingRequest(previewRequest, null, childHandler)进行了预览
    4. 点击屏幕,调用takePicture(),这个方法内,最终调用了capture(mCaptureRequest, null, childHandler)
    5. new ImageReader.OnImageAvailableListener(){}回调方法中,将拍照拿到的图片进行展示

    代码:

    public class Camera2Activity extends AppCompatActivity implements View.OnClickListener {
        private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
    
        ///为了使照片竖直显示
        static {
            ORIENTATIONS.append(Surface.ROTATION_0, 90);
            ORIENTATIONS.append(Surface.ROTATION_90, 0);
            ORIENTATIONS.append(Surface.ROTATION_180, 270);
            ORIENTATIONS.append(Surface.ROTATION_270, 180);
        }
    
        private SurfaceView mSurfaceView;
        private SurfaceHolder mSurfaceHolder;
        private ImageView iv_show;
        private CameraManager mCameraManager;//摄像头管理器
        private Handler childHandler, mainHandler;
        private String mCameraID;//摄像头Id 0 为后  1 为前
        private ImageReader mImageReader;
        private CameraCaptureSession mCameraCaptureSession;
        private CameraDevice mCameraDevice;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_camera2);
            initVIew();
        }
    
        /**
         * 初始化
         */
        private void initVIew() {
            iv_show = (ImageView) findViewById(R.id.iv_show_camera2_activity);
            //mSurfaceView
            mSurfaceView = (SurfaceView) findViewById(R.id.surface_view_camera2_activity);
            mSurfaceView.setOnClickListener(this);
            mSurfaceHolder = mSurfaceView.getHolder();
            mSurfaceHolder.setKeepScreenOn(true);
            // mSurfaceView添加回调
            mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
                    // 初始化Camera
                    initCamera2();
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
                    // 释放Camera资源  
                    if (null != mCameraDevice) {    
                        mCameraDevice.close(); 
                        Camera2Activity.this.mCameraDevice = null;
                    }
                }
            });
        }
    
        /**
         * 初始化Camera2
         */
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        private void initCamera2() {
            HandlerThread handlerThread = new HandlerThread("Camera2");
            handlerThread.start();
            childHandler = new Handler(handlerThread.getLooper());
            mainHandler = new Handler(getMainLooper());
            mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;//后摄像头
            mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG,1);
            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如,写入本地
                @Override
                public void onImageAvailable(ImageReader reader) {
                    mCameraDevice.close();
                    mSurfaceView.setVisibility(View.GONE);
                    iv_show.setVisibility(View.VISIBLE);
                    // 拿到拍照照片数据
                    Image image = reader.acquireNextImage();
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] bytes = new byte[buffer.remaining()];
                    buffer.get(bytes);//由缓冲区存入字节数组
                    final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                    if (bitmap != null) {
                        iv_show.setImageBitmap(bitmap);
                    }
                }
            }, mainHandler);
            //获取摄像头管理
            mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            try {
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                //打开摄像头
                mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * 摄像头创建监听
         */
        private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(CameraDevice camera) {//打开摄像头
                mCameraDevice = camera;
                //开启预览
                takePreview();
            }
    
            @Override
            public void onDisconnected(CameraDevice camera) {//关闭摄像头
                if (null != mCameraDevice) {
                    mCameraDevice.close();
                    Camera2Activity.this.mCameraDevice = null;
                }
            }
    
            @Override
            public void onError(CameraDevice camera, int error) {//发生错误
                Toast.makeText(Camera2Activity.this, "摄像头开启失败", Toast.LENGTH_SHORT).show();
            }
        };
    
        /**
         * 开始预览
         */
        private void takePreview() {
            try {
                // 创建预览需要的CaptureRequest.Builder
                final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                // 将SurfaceView的surface作为CaptureRequest.Builder的目标
                previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
                // 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
                mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③
                {
                    @Override
                    public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                        if (null == mCameraDevice) return;
                        // 当摄像头已经准备好时,开始显示预览
                        mCameraCaptureSession = cameraCaptureSession;
                        try {
                            // 自动对焦
                            previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                            // 打开闪光灯
                            previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                            // 显示预览
                            CaptureRequest previewRequest = previewRequestBuilder.build();
                            mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }
    
                    @Override
                    public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                        Toast.makeText(Camera2Activity.this, "配置失败", Toast.LENGTH_SHORT).show();
                    }
                }, childHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 点击事件
         */
        @Override
        public void onClick(View v) {
            takePicture();
        }
    
        /**
         * 拍照
         */
        private void takePicture() {
            if (mCameraDevice == null) return;
           // 创建拍照需要的CaptureRequest.Builder
            final CaptureRequest.Builder captureRequestBuilder;
            try {
                captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                // 将imageReader的surface作为CaptureRequest.Builder的目标
                captureRequestBuilder.addTarget(mImageReader.getSurface());
                // 自动对焦
                captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                // 自动曝光
                captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                // 获取手机方向
                int rotation = getWindowManager().getDefaultDisplay().getRotation();
                // 根据设备方向计算设置照片的方向
                captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
                //拍照
                CaptureRequest mCaptureRequest = captureRequestBuilder.build();
                mCameraCaptureSession.capture(mCaptureRequest, null, childHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    }
    

    布局代码以及权限与Camera1中一样,效果一样

    预览时,是将mSurfaceHolder.getSurface()作为目标
    显示拍照结果时,是将mImageReader.getSurface()作为目标


    3. 最后

    Camera2的功能很强大,暂时也只是学习了最基本的思路

    住的地方,没有桌子,于是坐地上,趴在床上敲代码,腰疼。逛淘宝买桌子去

    感谢极客学院和肾虚将军的学习资料

    共勉 : )

    相关文章

      网友评论

      • 8b62b957ddb4:您好 最近在看camera2 有个问题想请教一下 怎么调整预览角度 camera1 里面设置 setDisplayOrientation 就可以了 那么2 有什么方法可以设置么
        8b62b957ddb4:@英勇青铜5 谢谢~ 麻烦了
        英勇青铜5:@gunnerbai 抱歉,不知道。从写过这篇博客,我就没在工作中用过
      • aea2d0dabdf1:检查相机权限前,是不是要先请求一下?
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA},1);
        英勇青铜5:@liuwei159528 根据系统来吧,不过现在手机系统基本都6.0了,可以考虑用下开源的权限框架来处理
      • 初级工程师丙:学习了,请问怎么实现快门的效果?就是拍照的时候带上声音
        英勇青铜5:@初级工程师丙 具体api我不知道,系统应该提供了方法
      • lovesosoi:你好,问个问题,预览中变形了怎么办
        檀香_2cd5:可以通过照片的高宽比,去设置预览照片的宽高。
      • Android_Romance:有自己写一个按钮 设置闪光灯吗 比如点击开启开启闪光灯 那么闪光灯要在 预览拍照都要亮 总共有不开启闪光灯 开启闪光灯 自动 三种状态 来回切换 有做吗
        英勇青铜5:@Android_Romance 没有,目前没做过拍照相关开发
      • 5b5f5b43714e:请问博主又没有测试过闪光灯的功能?我用三星S6,honor5c测下来都不能打开闪光灯,三星晚上拍就整个卡住,荣耀倒没卡住,但是没有开出闪光灯来
        5b5f5b43714e:@英勇青铜5 哦哦好的,谢谢啦
        英勇青铜5:@QQ去冰 没有,我并没有做过这方面的开发。写这篇博客时,只是偶然间知道了有camera2 这样一个东西,就了解下
      • 阿南北去:楼主,这个camera2的回调机制,可不可能用于视频录制时的水印添加呢?你觉得有没有实现的可能,或者有没有相关的经验可以指点一下,谢谢
        英勇青铜5: @阿南北去 额。。。我不知道
      • 9df2a6e99159:你好,想问下如何解决Camera2预览时的拉伸问题呢
        英勇青铜5: @海边的卡夫卡Fu 额。。。抱歉,我也不知道
      • 吃着冰淇凌望着蓝天:想咨询下作者是怎么整理出来camera2的使用逻辑,写出一个完整的代码?因为我查了很多网上的camera2的博客,简直扯淡,代码又不给全,逻辑混乱;但查看官网的介绍发现还是比较乱,因为都只是罗列了单个的用法,并没有给出demo,所以比较困惑。
        英勇青铜5: @吃着冰淇凌望着蓝天 有些问题,身边人也不晓得,就只能自己慢慢瞎捣鼓喽,肯定是没啥效率的
        吃着冰淇凌望着蓝天: @英勇青铜5 但其实我不太支持这样的方法,觉得效率比较低,而且思路会有些乱的,当然仅属个人意见。
        英勇青铜5: @吃着冰淇凌望着蓝天 你是说学习过程嘛???额。。我也是看看博客,然后自己试。连猜带蒙的。记得这里花了一个周末整理的,有时候遇到不会的凌乱的,也多点耐心吧,很多东西我看不懂就先丢在那,过段时间再试试能不能看懂
      • 若无初见:老问题,预览的时候变形卡顿都需要优化。camera2不知道是怎么做的,看来得好好研究下。
        英勇青铜5: @若无初见 嗦嘎
        若无初见:@英勇青铜5 重新设置surfaceview的大小。因为我把他放到了fragment中,不设置大小就会出现问题。
        英勇青铜5: @若无初见 😃😃
      • CrazyMO_:对于cameraId来说,严格来说并非永远都是0后,1 前,更多的是cameraId主要是通过 String cameraId : manager.getCameraIdList() 遍历设备的摄像头,然后 Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
        if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
        //满足这个条件才是前置的
        }

        如果更严格些应该进行判断。
        英勇青铜5: @CrazyMO_ 多谢指出问题,回头修改下
      • 2bc5f6503fe8:哥们你这种写法会导致拍照时预览界面卡顿一下,如果连续拍照预览界面就卡死了
        英勇青铜5: @peinhu 这是不是连拍没有对截图的bitmap做处理的原因?bitmap太多,太占内存,导致卡顿
        2bc5f6503fe8:@英勇青铜5 这个问题貌似一定会存在,原因是Java层处理图片时大循环比较耗时,就算用android自带的相机应用也会有一点点的卡顿,连拍我是直接截取预览图像,只要100ms左右不卡顿。
        英勇青铜5: @peinhu 额。。。。我当时写只是了解api来着,并没有实际开发用过。。。有啥问题,我也不知道😂😂😂。能说下,你有啥优化或者怎么处理的嘛
      • a84073ea719a:博主你好。我按照你说的步骤去做,但是显示黑屏和“配置失败”。这可能是什么原因呢?我的系统是flyme(android 5.0.1),manifest里面也写了权限了.
        英勇青铜5: @Tau_ed07 😂😂😂你先排查下问题吧
        a84073ea719a:@英勇青铜5 android官方的Camera2Basic有点复杂看不懂。博主的代码就简洁很多,可是跑不了:sob:
        英勇青铜5: @Tau_ed07 😂😂😂啊,这个传闻flyme又称bugme,bug检测者,果然名不虚传。估计是我代码里哪有bug吧,这个真抱歉,我不知道。。。你查出来原因,说一下吧
      • f40983146a82:超感谢!!!!!!!比心
        英勇青铜5:@OwO一二三四五 //设置点击监 mSurfaceView.setOnClickListener(this);这句话,是整个SurfaceView设置了点击监听
        f40983146a82:@英勇青铜5 谢谢你百忙中抽空回复我~可是我有个问题还没理解,为什么没有按钮监听也能拍照呢?
        英勇青铜5:@Amo_858a :grin:
      • 三棵猴面包树:能不能给源码参考参考 github上的项目导入AS半小时都不能成功导入,我就是想看看哪种简单的实现源码。太复杂难懂。谢谢
        三棵猴面包树:@英勇青铜5 好的谢谢
        英勇青铜5: @三棵猴面包树 这个,不好意思啊,换电脑了,代码没了。博客里基本是全本的代码了,只有一点没有
      • 620febfe2057: @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 请问这个主要是干嘛的啊 为什么我的报错啊
        英勇青铜5:@七囍_c7d1 如果有一些正在被占用的资源,就释放掉吧
        620febfe2057:@英勇青铜5 那我在onDestroy用写什么么?
        英勇青铜5:字面意思就是要求5.0以上的版本才能使用
      • boboyuwu:什么是RAW输出啊
        boboyuwu:@英勇青铜5 好的非常感谢
        英勇青铜5: @boboyuwu 可以理解成不经过压缩,拍照得到的原始图像数据格式,jpeg和png是已经压缩过的
      • 认真的阿平有点宅:请教一下 如果用模拟器的话 是不是就不能运行 我用的模拟器一进去是黑屏的
        英勇青铜5: @捏你小肥脸 😂😂😂
        捏你小肥脸:大神 学习了
        英勇青铜5: @认真的阿平有点宅 我也不是很清楚。。。我是拿自己日常用的手机测的。。。
      • Fourier:请教一个问题
        在camera中,拍完照存入mediaStore需要发一个ACTION_NEW_PICTURE的广播。在camera2中还需要手动发送吗?
        英勇青铜5: @魏魏魏魏 这个真心抱歉了,我一会在开头说一下。写这个博客时,我手机只有5.0,当时就没考虑权限的事,耽搁你时间真是抱歉
        魏魏魏魏:大哥,你的代码有个bug,对初学者有影响。bug就是你没有写动态申请权限,导致APP黑屏不能解决,还要研究代码,,,,
        英勇青铜5: @Fourier 不确定,不过应该需要吧
      • 娃嘻嘻:谢谢!!
        英勇青铜5: @娃嘻嘻 😀😀😀
      • seraphzxz:深入理解操作系统,确实难啃。
        英勇青铜5: @seraphzxz 翻了下,感觉过个2年看比较好。现在看的还是大学的教材
      • 牛儿人生:博主,你好,我是新手一枚。请教一下:该导入哪些头文件和类?
        英勇青铜5: @牛儿人生 使用camera2的话,就import 这个android.hardware.Camera2包。我在开头有提到,嗯,还得注意权限,5.0和6.0也有些不同,我在博客里没提。😀
        牛儿人生:@英勇青铜5博主,是的,我是刚刚转到安卓上面来的,想把之前C++的程序移植到安卓上来的。我的表达能力不好,我其实是想问该import哪些东西?在AS中,有个按下Alt + Enter自动补充的功能,但是有些是多选的,我就不知道该选哪个了。
        英勇青铜5: @牛儿人生 这个,同学,你说的导入头文件是啥意思?就是为了可以使用camera2的api吗?这个倒是不用导入的,只要android sdk没有问题,就直接可以用,个人感觉可以理解成是android 标准库里的。同学,你之前工作多是使用c/c ++吗?😀,android开发中,第三方的库需要额外导入的,在实现一个需求前,确定使用库和类是android sdk中官方提供的还是第三方的
      • 道貌岸然的大师兄:太喜欢你写的文章了
        英勇青铜5: @道貌岸然的大师兄 😂😂😂😂😂😂😂
        道貌岸然的大师兄:每天看你写的 魔怔了怎么办ლ(╹◡╹ლ)
        英勇青铜5:@道貌岸然的大师兄 哈哈,受宠若惊。以后再写,就多用心写了:smile:
      • Sia_Coding:camera2的再多点就好了:joy:
        英勇青铜5: @Sia_Coding 😂😂😂当时也是简单看看
      • 下雨天的小白鞋:为什么我的调不出来相机呢?黑的?
        英勇青铜5: @下雨天的小白鞋 😀😀😀都经常犯这个错。没想到,竟然有女孩子看我博客,啊,我可以吹一年了
        下雨天的小白鞋:@英勇青铜5 哦 可以了,我忘了给应用开权限 哈哈哈
        英勇青铜5: @下雨天的小白鞋 camera2吗?手机系统多少啊?我测试是5.1的
      • dodo_lihao:学习了
        英勇青铜5:@dodo_lihao :smile:

      本文标题:Android Camera2 拍照入门学习

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