Android 自定义相机Demo 入门学习

Android 自定义相机Demo

本文是参考网上一些自定义相机示例,再结合自己对相机的功能需求写的,基本上包含了很多基本功能,比如相机对焦、闪光灯,以及在手机预览界面上绘制自己想要绘制的图案。

话不多说,先上一张图:
相机应用界面

应用是在Android Studio中开发的,java程序如下:

//主程序
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

@SuppressLint("NewApi")
public class CameraActivity extends AppCompatActivity {
    protected static final String TAG = "main";
    private Camera mCamera;
    private CameraPreview mPreview;
    private static int Cur_State = 0;
    public ImageView imgDu;
    public File pictureFile;
    Draw draw;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        imgDu = (ImageView) findViewById(R.id.img1);  
        mCamera = getCameraInstance();
        draw = new Draw(CameraActivity.this);

        // 创建预览类,并与Camera关联,最后添加到界面布局中
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);

        preview.addView(mPreview);
        preview.addView(draw);

        Button captureButton = (Button) findViewById(R.id.button_capture);  //button_capture

        captureButton.setOnClickListener(new View.OnClickListener() {
            @SuppressWarnings("deprecation")
            @Override
            public void onClick(View v) {
                Camera.Parameters parameters = mCamera.getParameters();
                // 设置相片格式
                parameters.setJpegQuality(100);  //生成图像的质量
                mCamera.setParameters(parameters);
                parameters.setPictureFormat(ImageFormat.JPEG);
                // 设置预览大小
                parameters.setPreviewSize(800, 480);
                parameters.setPictureSize(4160, 3120); //生成图像的风辨率
                mCamera.setParameters(parameters);
                parameters.setRotation(90);  //生成的图像旋转90度
                mCamera.setParameters(parameters);
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
                mCamera.autoFocus(new Camera.AutoFocusCallback() {
                    @Override
                    public void onAutoFocus(boolean success, Camera camera) {
                        // 从Camera捕获图片
                        mCamera.takePicture(null, null, mPicture);
                    }
                });
                /*if (Cur_State < 2) {
                    switch (Cur_State) {
                        case 0:
                            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                            mCamera.setParameters(parameters);
                            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                                @Override
                                public void onAutoFocus(boolean success, Camera camera) {
                                    // 从Camera捕获图片
                                    mCamera.takePicture(null, null, mPicture);

                                }
                            });
                            Cur_State++;
                            break;
                        case 1:
                            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//FLASH_MODE_OFF
                            mCamera.setParameters(parameters);
                            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                                @Override
                                public void onAutoFocus(boolean success, Camera camera) {
                                    // 从Camera捕获图片
                                    mCamera.takePicture(null, null, mPicture);

                                }
                            });
                            Cur_State++;
                            break;
                    }
                } else {
                    Cur_State = 0;
                }*/

        }
        });
    }
    /** 检测设备是否存在Camera硬件 */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            // 存在
            return true;
        } else {
            // 不存在
            return false;
        }
    }
    /** 打开一个Camera */
    public static Camera getCameraInstance() {
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e) {
            Log.d(TAG, "打开Camera失败失败");
        }
        return c;
    }

    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera arg1) {
            //将拍照得到的数据信息存储到本地
            File tempFile=new File("/sdcard/temp.png");
            try {
                FileOutputStream fos=new FileOutputStream(tempFile);
                fos.write(data);
                fos.close();

    //注意,,,然后将这个照片的数据信息传送给要进行展示的Activity即可,这部
    //分代码是我自己需要的,你使用时需要将他去掉修改成你的。
                Intent intent=new Intent(CameraActivity.this,MainActivity.class);
                intent.putExtra("PicturePath", tempFile.getAbsolutePath());
                startActivity(intent);
                //拍照结束之后销毁当前的Activity,进入到图片展示界面
                CameraActivity.this.finish();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    @Override
    protected void onDestroy() {
        // 回收Camera资源
        if(mCamera!=null){
            mCamera.stopPreview();
            mCamera.release();
            mCamera=null;
        }
        super.onDestroy();
    }
}
/**
 * 定义一个预览类  预览界面设置
 */
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;

@SuppressLint("NewApi")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "main";
    private SurfaceHolder mHolder;
    @SuppressWarnings("deprecation")
    private Camera mCamera;

    @SuppressWarnings("deprecation")
    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        // 通过SurfaceView获得SurfaceHolder
        mHolder = getHolder();
        // 为SurfaceHolder指定回调
        mHolder.addCallback(this);
        mCamera.setDisplayOrientation(90);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // 当Surface被创建之后,开始Camera的预览
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "预览失败");
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Surface发生改变的时候将被调用,第一次显示到界面的时候也会被调用
        if (mHolder.getSurface() == null){
            // 如果Surface为空,不继续操作
            return;
        }

        // 停止Camera的预览
        try {
            mCamera.stopPreview();

        } catch (Exception e){
            Log.d(TAG, "当Surface改变后,停止预览出错");
        }

        // 重新开始预览
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "预览Camera出错");
        }
    }
}
/**
 * Created by Administrator on 2018/1/24.
 * 这个是在预览界面绘制图案部分
 */
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;

public class Draw extends View
{
    private Canvas canvas;//声明画笔
    private Paint paint;//声明画布
    private Paint paint1;
    private Paint paint2;

    private Bitmap bitmap;//声明位图

    public Draw(Context context)
    {
        super(context);
        // TODO 自动生成的构造函数存根
        //创建一个画笔
        paint = new Paint(Paint.DITHER_FLAG);
        paint1 = new Paint(Paint.DITHER_FLAG);
        paint2 = new Paint(Paint.DITHER_FLAG);
        //设置位图的宽高,采用32位ARGB位图模式
        bitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);

        paint.setStyle(Paint.Style.STROKE);//设置非填充
        paint.setStrokeWidth(2);//笔宽5像素
        paint.setColor(Color.RED);//设置为红笔
        paint.setAntiAlias(true);//锯齿不显示
        paint.setDither(true);//设置图像抖动处理
        paint.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式
        paint.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式

        paint1.setStyle(Paint.Style.FILL);//设置非填充
        paint1.setStrokeWidth(33);//笔宽5像素
        paint1.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式
        paint1.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式
        paint1.setColor(Color.BLACK);//设置为黑笔
        paint.setAntiAlias(true);//锯齿不显示
        paint.setDither(true);//设置图像抖动处理

        paint2.setStyle(Paint.Style.FILL);//设置填充
        paint2.setStrokeWidth(12);//笔宽5像素
        paint2.setAntiAlias(true);//锯齿不显示
        paint2.setDither(true);//设置图像抖动处理
        paint2.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式
        paint2.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式
        paint2.setColor(Color.BLACK);//设置为黑笔
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas)
    {
        // TODO 自动生成的方法存根
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap, 0, 0, paint);

        float[] pts = {0,240,260,70};
        canvas.drawLines(pts , paint);   //在画布上画线  1
        float[] pts2 = {695,522,340,1040};
        canvas.drawLines(pts2, paint);   //在画布上画线 2

        Path mPath = new Path();
        mPath.moveTo(260, 70);
        mPath.quadTo(780, 0, 695, 522);
        canvas.drawPath(mPath, paint);    //塞尔塔曲线

        Path path = new Path();      //定义一条路径
        path.moveTo(0,0);      //移动到 坐标(0,0)
        path.lineTo(0,240);
        path.lineTo(270,62);
        path.lineTo(270,0);
        path.lineTo(0,0);
        canvas.drawPath(path, paint2);

        Path path1 = new Path();      //定义一条路径
        path1.moveTo(260,0);    //移动到 坐标(260,0)
        path1.lineTo(720,0);
        path1.lineTo(720,60);
        path1.lineTo(260,60);
        path1.lineTo(260,0);
        canvas.drawPath(path1, paint2);

        Path path2 = new Path();       //定义一条路径
        path2.moveTo(720,60);    //移动到 坐标(720,60)
        path2.lineTo(720,522);
        path2.lineTo(715,522);
        path2.lineTo(715,512);
        path2.lineTo(700,60);
        path2.lineTo(720,60);
        canvas.drawPath(path2, paint2);

        Path path3 = new Path();        //定义一条路径
        path3.moveTo(340,1040);   //移动到 坐标(340,1040)
        path3.lineTo(720,1040);
        path3.lineTo(720,522);
        path3.lineTo(710,512);
        path3.lineTo(340,1040);
        canvas.drawPath(path3, paint2);

        Path path4 = new Path();        //定义一条路径
        path4.moveTo(720,200);   //移动到 坐标(715,512)
        path4.lineTo(500,60);
        path4.lineTo(720,60);
        path4.lineTo(720,200);
        canvas.drawPath(path4, paint2);

        float[] pts3 = {720,108,450,56};
        canvas.drawLines(pts3, paint2);   //在画布上画线 3

        float[] pts4 = {715,230,630,110};
        canvas.drawLines(pts4, paint1);   //在画布上画线 4
        float[] pts5 = {660,130,718,272};
        canvas.drawLines(pts5, paint1);   //在画布上画线 5
        float[] pts6 = {714,522,720,440};
        canvas.drawLines(pts6, paint1);   //在画布上画线 6
    }
}

布局文件 activity_camera.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:text="拍照"
        android:textColor="#6633cc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        />

</LinearLayout>

应用权限:

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

具体的细节就不在说明,可以自己在网上搜一下相关知识,大家使用中有什么问题可以留言哦,如果能解决尽量帮大家解决。

猜你喜欢

转载自blog.csdn.net/xiaoxiaofeng001/article/details/80550454
今日推荐