使用摄像头预览和拍照(Camera1)

参考文章:
https://blog.csdn.net/u011418943/article/details/107256406
https://blog.csdn.net/xiaodongvtion/article/details/110951754

Camera1的类android.hardware.Camera。Camera类常用的方法:

方法

描述

getParameters()

获取摄像头参数

setParameters()

设置摄像头参数

setPreviewDisplay()

为摄像头指定一个显示预览画面的SurfaceView

open()

打开摄像头

startPreview()

开始预览

stopPreview()

停止预览

release()

释放摄像头资源

takePicture()

进行拍照

1 代码

MainActivity.java

public class MainActivity extends Activity {
    public final static String TAG = "CameraPreview";
    private Camera camera;
    private boolean isPreview = false;


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


        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.CAMERA}, 1);
        }
        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }


        // 设置全屏显示
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);


        // 判断手机是否安装SD卡
        if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
            Toast.makeText(this, "请安装SD卡!", Toast.LENGTH_SHORT).show();
        }


        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        // 设置该SurfaceHolder自己不维护缓冲
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


        ImageButton preview = (ImageButton) findViewById(R.id.preview);
        preview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 如果相机为非预览模式,则打开相机
                if (!isPreview) {
                    camera = Camera.open();
                    isPreview = true;
                }
                try {
                    // 设置用于显示预览的SurfaceView
                    camera.setPreviewDisplay(surfaceHolder);


                    Camera.Parameters parameters = camera.getParameters();
                    // 测试Camera.Parameters
                    // (1)setPictureFormat======================================
                    // PixelFormat.JPEG:jpeg
                    // parameters.setPictureFormat(PixelFormat.JPEG);     // 指定图片为JPEG图片
                    // parameters.set("jpeg-quality", 80);                // 设置图片的质量
                    // PixelFormat.YCbCr_420_SP:NV21,等价于ImageFormat.NV21
                    parameters.setPictureFormat(PixelFormat.YCbCr_420_SP);
                    // (2)setWhiteBalance======================================
                    // auto
                    String whiteBalance = parameters.getWhiteBalance();
                    Log.d(TAG, "whiteBalance:" + whiteBalance);
                    // WHITE_BALANCE_INCANDESCENT:偏蓝
                    // WHITE_BALANCE_FLUORESCENT:偏淡蓝
                    // WHITE_BALANCE_WARM_FLUORESCENT:偏淡蓝
                    // WHITE_BALANCE_DAYLIGHT:日光,正常
                    // WHITE_BALANCE_CLOUDY_DAYLIGHT:阴天,偏黄
                    // WHITE_BALANCE_TWILIGHT:暮光,偏黄
                    // WHITE_BALANCE_SHADE:偏黄
                    parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
                    whiteBalance = parameters.getWhiteBalance();
                    Log.d(TAG, "whiteBalance:" + whiteBalance);
                    // (3)setExposureCompensation======================================曝光补偿
                    int minEx = parameters.getMinExposureCompensation();
                    int maxEx = parameters.getMaxExposureCompensation();
                    float stepEx = parameters.getExposureCompensationStep();
                    Log.d(TAG, "minEx:" + minEx + " maxEx:" + maxEx + " stepEx:" + stepEx);
                    parameters.setExposureCompensation(6);
                    // (4)setAutoExposureLock======================================
                    boolean isAELS = parameters.isAutoExposureLockSupported();
                    Log.d(TAG, "isAES:" + isAELS);
                    boolean getAELS = parameters.getAutoExposureLock();
                    Log.d(TAG, "getAES:" + getAELS);
                    parameters.setAutoExposureLock(false);
                    getAELS = parameters.getAutoExposureLock();
                    Log.d(TAG, "getAES:" + getAELS);
                    // (5)setAutoWhiteBalanceLock======================================
                    boolean isAWBLS = parameters.isAutoWhiteBalanceLockSupported();
                    Log.d(TAG, "isAWBLS:" + isAWBLS);
                    boolean getAWBL = parameters.getAutoWhiteBalanceLock();
                    Log.d(TAG, "getAWBL:" + getAWBL);
                    parameters.setAutoWhiteBalanceLock(false);
                    getAWBL = parameters.getAutoWhiteBalanceLock();
                    Log.d(TAG, "getAWBL:" + getAWBL);
                    // (5)setFocusMode======================================
                    String fm = parameters.getFocusMode();
                    Log.d(TAG, "fm:" + fm);
                    // FOCUS_MODE_AUTO:聚焦
                    // FOCUS_MODE_INFINITY:不聚焦
                    // FOCUS_MODE_MACRO:聚焦
                    // FOCUS_MODE_CONTINUOUS_VIDEO:跟随预览的物体远近自动聚焦,afcb返回fail
                    // FOCUS_MODE_CONTINUOUS_PICTURE:跟随预览的物体远近自动聚焦,afcb返回fail
                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    fm = parameters.getFocusMode();
                    Log.d(TAG, "fm:" + fm);
                    camera.setParameters(parameters);


                    camera.startPreview();
                    // AF:自动对焦
                    camera.autoFocus(afcb);
                    camera.setDisplayOrientation(90);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });


        ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto);
        takePicture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (camera != null) {
                    camera.takePicture(null, null, jpeg);
                }
            }
        });
    }


    final Camera.AutoFocusCallback afcb = new Camera.AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            if(success) {
                // success表示对焦成功
                Log.d(TAG, "afcb: success");
                //camera.setOneShotPreviewCallback(null);
            }
            else {
                // 未对焦成功
                Log.d(TAG, "afcb: fail");
            }
        }
    };


    // 照片回调函数,实现将照片保存到系统图库中
    final Camera.PictureCallback jpeg = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 根据拍照所得的数据创建位图
            final Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
            camera.stopPreview();
            isPreview = false;
            Log.d(TAG, "Environment.getExternalStorageDirectory():" + Environment.getExternalStorageDirectory());
            //获取sd卡根目录
            File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/");
            if (!appDir.exists()) {      // 如果该目录不存在就创建该目录
                appDir.mkdir();
            }
            String fileName = System.currentTimeMillis() + ".jpg";
            File file = new File(appDir, fileName);
            // 保存拍到的图片
            try {
                FileOutputStream fos = new FileOutputStream(file);  // 创建一个文件输出流对象
                boolean ret = bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);  // 将图片内容压缩为JPEG格式输出到输出流对象中
                Log.d(TAG, "bm.compress ret:" + ret);
                fos.flush();
                fos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


            //将照片插入到系统图库
            try {
                MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),
                        file.getAbsolutePath(), fileName, null);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }


            // 最后通知图库更新
            MainActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                    Uri.parse("file://" + "")));
            Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show();
            resetCamera();
        }
    };


    // 创建resetCamera()方法,实现重新预览功能
    private void resetCamera() {
        if (!isPreview) {
            camera.startPreview();
            isPreview = true;
        }
    }


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

查看手机是否安装SD卡:

adb shell mount

adb shell df -h

手机内部存储相册路径:/storage/emulated/0/DCIM/Camera/

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">


    <!--SurfaceView组件-->
    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!--拍照按钮-->
    <ImageButton
        android:id="@+id/takephoto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|top"
        android:layout_marginTop="@dimen/margin_top"
        android:background="@color/btn_background"
        android:src="@drawable/camera" />
    <!--预览按钮-->
    <ImageButton
        android:id="@+id/preview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:layout_marginBottom="@dimen/margin_bottom"
        android:background="@color/btn_background"
        android:src="@drawable/preview" />


</FrameLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.hyh.camerapreview">


    <!-- 授予程序可以向SD卡中保存文件的权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 授予程序使用摄像头的权限 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera.autofocus"/>
    <uses-feature android:name="android.hardware.camera"/>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.CameraPreview"
        android:requestLegacyExternalStorage="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>


</manifest>

2 遇到的问题

2.1 预览时图片拉伸

需要设置预览方向

camera.setDisplayOrientation(90);

2.2 拍照时不能保存相片

java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/1638007179710.jpg: open failed: ENOENT (No such file or directory)

android:requestLegacyExternalStorage="true"

原因是Android10弃用了管理分区外部储存

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/121598264