Android实现拍照功能与图片存储

xml文件作为载体

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TakePhoto_Activity"
    android:orientation="vertical"
    android:background="@drawable/longhu">


    <!--该组件用来展示摄像头捕获到的内容-->
    <TextureView
        android:id="@+id/textureview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="150dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="610dp"
        android:layout_marginLeft="145dp"
        android:background="@android:color/transparent"
        android:onClick="capture"
        android:text="拍照"
        android:textColor="#ffffff"
        android:textSize="30sp"/>

</RelativeLayout>

实现功能最重要

package com.example.inform_learning;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.Size;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.SparseArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@RequiresApi(api=Build.VERSION_CODES.LOLLIPOP)
public class TakePhoto_Activity extends AppCompatActivity {

    TextureView mPreViewView;
    HandlerThread cameraThread;
    Handler mCameraHandler;

    CameraManager cameraManager;
    android.util.Size mPreViewSize;
    android.util.Size mCaptureSize;   //最佳的拍照尺寸

    String mCameraid;
    CameraDevice mcameraDevice;
    CaptureRequest.Builder mCaptureRequestBuilder;
    CaptureRequest mCaptureRequest;
    CameraCaptureSession mcameraCaptureSession;

    ImageReader mimageReader;
    private static final SparseArray ORIENTATION = new SparseArray();

    static {
        ORIENTATION.append(Surface.ROTATION_0,90);
        ORIENTATION.append(Surface.ROTATION_90,0);
        ORIENTATION.append(Surface.ROTATION_180,270);
        ORIENTATION.append(Surface.ROTATION_270,180);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_photo_);

        mPreViewView=findViewById(R.id.textureview);
    }

    //实现具体功能
    @Override
    protected void onResume() {
        super.onResume();

        startCameraThread();
        if (!mPreViewView.isAvailable()) {
            mPreViewView.setSurfaceTextureListener(textureListener);
        }else {
            startPreView();
        }
    }

    TextureView.SurfaceTextureListener textureListener=new TextureView.SurfaceTextureListener() {
        @RequiresApi(api=Build.VERSION_CODES.M)
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
            //当SurfaceTexture可用时,设置相机的参数,打开摄像头
            setupCamera(i, i1);
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

        }
    };

    //设置摄像头的参数
    @RequiresApi(api=Build.VERSION_CODES.LOLLIPOP)
    private void setupCamera(int width, int height) {
        cameraManager=(CameraManager) getSystemService(Context.CAMERA_SERVICE);

        //拿到摄像头的id
        try {
            for (String cameraID : cameraManager.getCameraIdList()) {
                CameraCharacteristics characteristics=cameraManager.getCameraCharacteristics(cameraID);

                Integer facing=characteristics.get(CameraCharacteristics.LENS_FACING);
                if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
                    continue;
                }
                StreamConfigurationMap map=characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                //找到摄像头能够输出的最符合能够显示界面分辨率的最小值
                if (map != null) {
//                   mPreViewSize=getOptimalSize(map.getOutputSizes(SurfaceTexture.class),width,height);
                   mCaptureSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<android.util.Size>() {
                       @Override
                       public int compare(android.util.Size size, android.util.Size t1) {
                           return Long.signum(size.getWidth()*size.getHeight() - t1.getWidth()*t1.getHeight());
                       }
                   });
                }

                //建立图片缓冲区
                setupImageReader();

                mCameraid=cameraID;
                break;
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Size getOptimalSize(Size[] sizeMap, int width, int height) {
        List<Size> sizeList = new ArrayList<Size>();

        for (Size option : sizeMap) {
            if (width > height) {  //横屏
                sizeList.add(option);
            } else {
                sizeList.add(option);
            }
        }

            if (sizeList.size() > 1){
//            return Collections.min(sizeList, new Comparator<Size>() {
//                @Override
//                public int compare(android.util.Size size, android.util.Size t1) {
//                   return Long.signum();
//                }
//            })  ;
        }

        return sizeMap[0];
    }

    //打开摄像头
    @RequiresApi(api=Build.VERSION_CODES.M)
    private void openCamera() {

        String [] permissions = {Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};

        int i = 0;
        for (String permission:permissions){
            if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                this.requestPermissions(permissions,i++);
            }
        }

        try {
            cameraManager.openCamera(mCameraid, mStateCallBack, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    CameraDevice.StateCallback mStateCallBack = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            mcameraDevice = cameraDevice;
            startPreView();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            mcameraDevice.close();
            mcameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {
            mcameraDevice.close();
            mcameraDevice = null;
        }
    };

    //开始预览
    private void startPreView() {
        //建立图形缓冲区
        SurfaceTexture surfaceTexture = mPreViewView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(mPreViewView.getWidth(),mPreViewView.getHeight());

        //得到界面的显示对象
        Surface previewSurface = new Surface(surfaceTexture);
        try {
            mCaptureRequestBuilder = mcameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mCaptureRequestBuilder.addTarget(previewSurface);

            //建立通道
            mcameraDevice.createCaptureSession(Arrays.asList(previewSurface,mimageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    try {
                        mCaptureRequest = mCaptureRequestBuilder.build();
                        mcameraCaptureSession = cameraCaptureSession;
                        mcameraCaptureSession.setRepeatingRequest(mCaptureRequest,null,mCameraHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

                }
            }, mCameraHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

    }

    //打开摄像头的线程
    private void startCameraThread() {
         cameraThread = new HandlerThread("CameraThread");
         cameraThread.start();
         mCameraHandler = new Handler(cameraThread.getLooper());
    }

    //开始拍照
    public void capture(View view){
        //获取摄像头的请求
        CaptureRequest.Builder mCameraBuilder =null;
        try {
            mCameraBuilder=mcameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        mCameraBuilder.addTarget(mimageReader.getSurface());

        //获取摄像头方向
        int rotation = getWindowManager().getDefaultDisplay().getRotation();

        //设置拍照方向
        mCameraBuilder.set(CaptureRequest.JPEG_ORIENTATION, (Integer) ORIENTATION.get(rotation));
        CameraCaptureSession.CaptureCallback mCaptureCallBack = new CameraCaptureSession.CaptureCallback(){
            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {

                Toast.makeText(getApplicationContext(),"拍照结束",Toast.LENGTH_LONG).show();
                unLockFocus();
                super.onCaptureCompleted(session, request, result);
            }
        };

        try {
            mcameraCaptureSession.stopRepeating();
            mcameraCaptureSession.capture(mCameraBuilder.build(),mCaptureCallBack,mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

        //获取图像的缓冲区


        //获取文件的存储权限及操作


    }

    private void unLockFocus(){
        try {
            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mcameraCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(),null,mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    //建立图片缓冲区
    private void setupImageReader(){
        mimageReader = ImageReader.newInstance(mCaptureSize.getWidth(),mCaptureSize.getHeight(),ImageFormat.JPEG,2);
        mimageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader imageReader) {
                mCameraHandler.post(new ImageSaver(imageReader.acquireLatestImage()));
            }
        },mCameraHandler);
    };

    private class  ImageSaver implements Runnable{

        Image mimage;

        public ImageSaver(Image image){
            mimage = image;
        }

        @Override
        public void run() {
            ByteBuffer buffer = mimage.getPlanes()[0].getBuffer();
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);

            String path =Environment.getExternalStorageDirectory() + "/DCIM/CameraV2/";
            File mImageFile = new File(path);
            if (!mImageFile.exists()){
                mImageFile.mkdir();
            }

            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String filename = path + "IMG_" + timeStamp + ".jpg";

            try {
                FileOutputStream fos = new FileOutputStream(filename);
                fos.write(data,0,data.length);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }
}

其实说实在的,有的代码我没看懂,将近400行代码只为实现一个功能未免有点牵强,但是总要学习的,多加运用,尝试理解。

记得申请权限

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

摄像头权限和sd卡存储访问权限

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值