Android 相机开发 闪光灯,前后摄像头切换,调整缩放比例

来源:互联网 发布:优化 英文 编辑:程序博客网 时间:2024/06/05 18:20
我们在开发的过程中,经常会要使用相机,android自己带有一个源生的app可以用来拍照,但是有时候为了更多的功能,我们需要自定义相机。

考虑点:
1、是否一定要用相机,没有相机的设备就不可以安装你的app了吗?
但是要记得再Manifest文件中声明,google play在没有相机的设备 上会自动过滤掉一定要使用相机的App。
2、你的应用将会怎样使用相机,调用系统已经存在的CameraApp,或者是自己定义一个App?调用系统的相机通过Intent就可以实现
3、图片存储,别的app是否可见?app卸载后是否还要可用?

Manifest文件配置
1、如果是通过intent调用相机,不需要申请权限。,通过添加Feature就可以满足

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

2、自定义相机,则需要申请权限

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

在声明权限之后,google play就会阻止你的app安装在没有相机的设备上。
如果图片需要保存的在SD卡上,需要指明权限

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

使用已经存在的相机APP步奏:
1、构造一个Intent,使用Intent的类型为,MediaStore.ACTION_IMAGE_CAPTURE
调用一个已经存在的相机应用
Intent可以附带一个参数MediaStore.EXTRA_OUTPUT,参数类型为Uri指定一个路径和
文件名保存相片
2、调用startActivityForResult()
3、在activity的onActivityResult()方法中会收到来自Intent的数据

构建一个Intent对象,设置Action,并将保存图片路径传入

Intent cameraIntent = new Intent();            cameraIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);            imageUri = getImageFileUri();            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//指定了存储路径将返回的data将会是null            startActivityForResult(cameraIntent, REQUESt_CODE_CAPTURE_IMAGE);
private Uri getImageFileUri(){        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());        File imageFile = new File(FileUtil.EXAMPLE_PATH + Constant.IMAGE +File.separator + timeStamp + ".jpg");        return Uri.fromFile(imageFile);}

在activity中的onAcivityResult方法中取数据,注意如果指定了保存路径,将不会有返回值,如果没有保存路径,则会返回路径。

@Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if (resultCode == RESULT_OK) {            switch (requestCode) {            case REQUESt_CODE_CAPTURE_IMAGE:                if (null != data)                {                }else                {                }                break;            }        }    }

2、自定义相机

遵循以下步奏:
1、检查是否有相机,访问请求

private boolean isCameraExist(){    return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);}

2、创建一个Activity类继实现SurfaceHolder接口
3、创建一个预览布局
4、创建动作监听,例如一个按钮拍照
5、拍照并保存
6、释放相机

相机功能:
android支持许多相机特点,例如相片格式,闪光灯模式,焦点设置,等等
这些都是通过Camera.Parameters来控制

这些知识点在代码中通过添加注释的方式来讲解。
开发过程中遇到的问题:
1、在onPause中释放相机后,onResume再为相机绑定SurfaceView的时候,会有异常抛出,相机已释放。
解决方案:添加变量hasSurface.在surfaceDestroyed中置为false。
2、闪光灯设置过程中Camera.Parameters.FLASH_MODE_ON无效果,
解决方案:改为Camera.Parameters.FLASH_MODE_TORCH
3、SurfaceHolder.Callback此接口是设置在SurfaceView中的。
4、使用相机前一定要判断是否支持相机,要在Manifest文件中配置,使用前置相机要记得判断是否支持前置相机。
5、人脸识别是在android 4.0之后添加的,并不是所有的android 4.0都支持人脸识别。笔者系统为 android 4.1,并不支持人脸识别。
6、最重要的一点,相机是有限的公共资源,很多app都可以调用,所以一定要release掉!

package com.example.androidtest;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import com.example.constant.Constant;import com.example.util.FileUtil;import android.annotation.SuppressLint;import android.app.Activity;import android.hardware.Camera;import android.hardware.Camera.Face;import android.hardware.Camera.FaceDetectionListener;import android.hardware.Camera.Parameters;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;public class CameraActivity extends Activity implements OnClickListener ,SurfaceHolder.Callback{    private Camera mCamera;    private Parameters mParameters;    private SurfaceView mSurfaceView;    /**     * 相机位置     */    private int cameraPosition = 0;    /**     * 这个参数主要是在程序到后台之后,再切换回来的判断     */    private boolean hasSurface = true;    /**     * 闪光灯是否开启     */    private boolean isLighting = false;    /**     * 是否支持闪光灯     */    private boolean isSupportedLight = false;    /**     * 调整Zoom用的seekbar     */    private SeekBar mSeekBar;    private SurfaceHolder viewHolder;    private int cameraCount,maxZoom;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_camera);        hasSurface = false;        //获取相机个数        cameraCount = Camera.getNumberOfCameras();    }    @Override    protected void onResume() {        super.onResume();        initView();    }    private void initCamera(SurfaceHolder viewHolder)    {        mCamera = getCameraInstance(-1);        mCamera.setFaceDetectionListener(mFaceDetectionListener);//添加人脸识别监听        mParameters = mCamera.getParameters();        maxZoom = mParameters.getMaxZoom();        mSeekBar.setMax(maxZoom*100);        mSeekBar.setProgress((int) (0.5 * maxZoom * 100));        List<String> features = mParameters.getSupportedFlashModes();//判断是否支持闪光灯        if (features.contains(Camera.Parameters.FLASH_MODE_ON)) {            isLighting = false;            isSupportedLight = true;        }        startPreviewOfCamera(viewHolder);        startFaceDectection();    }    private void startPreviewOfCamera(SurfaceHolder viewHolder)    {        try {            mCamera.setPreviewDisplay(viewHolder);            mCamera.setDisplayOrientation(90);//防止预览图片旋转            Parameters mParameters = mCamera.getParameters();            mParameters.setRotation(90);//防止保存的图片旋转            mCamera.setParameters(mParameters);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    /**     * 初始化控件     * @date 2015年4月3日     * @time 下午5:13:35     * @author Tony     */    private void initView()    {        mSurfaceView = (SurfaceView) findViewById(R.id.mSurfaceview);        viewHolder = mSurfaceView.getHolder();        //第一次会再onSurfaceCreated的时候初始化相机,并绑定预览效果        if (hasSurface) {            initCamera(viewHolder);        } else {            viewHolder.addCallback(this);//为viewHolder添加回调            viewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        }        findViewById(R.id.btnOpenSplash).setOnClickListener(this);        findViewById(R.id.btnCaptureCamera).setOnClickListener(this);        findViewById(R.id.btnOpenFront).setOnClickListener(this);        mSeekBar = (SeekBar) findViewById(R.id.mSeekBar);        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {            @Override            public void onStopTrackingTouch(SeekBar seekBar) {            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {            }            @Override            public void onProgressChanged(SeekBar seekBar, int progress,                    boolean fromUser) {                mParameters = mCamera.getParameters();                mParameters.setZoom((int) (progress * 1.0f / (maxZoom * 100) * maxZoom));                mCamera.setParameters(mParameters);            }        });    }    @Override    protected void onPause()     {        super.onPause();        releasedCamera();    }    /**     * 释放相机     * @date 2015年4月3日     * @time 下午5:17:24     * @author Tony     */    private void releasedCamera()    {        if (null != mCamera)         {            mCamera.setPreviewCallback(null) ;            mCamera.stopPreview();            mCamera.release();            mCamera = null;            hasSurface = false;        }    }    @Override    public void onClick(View v) {        switch (v.getId())        {            case R.id.btnOpenSplash:                if (isSupportedLight)                 {                    String flashMode = isLighting ? Camera.Parameters.FLASH_MODE_OFF:Camera.Parameters.FLASH_MODE_TORCH;                    mParameters.setFlashMode(flashMode);                    mCamera.setParameters(mParameters);                    isLighting = !isLighting;                }                break;            case R.id.btnOpenFront:                changeCamera();                break;            case R.id.btnCaptureCamera:                mCamera.takePicture(null, null, mPictureCallback);                break;        }    }    /**     * 拍照时候调用,保存图片     */    private PictureCallback mPictureCallback = new PictureCallback()     {        @Override        public void onPictureTaken(byte[] data, Camera camera)         {            File imageFile = getImageFile();            if (null != imageFile)            {                try                 {                    FileOutputStream fos = new FileOutputStream(imageFile);                    fos.write(data);                    fos.close();                }  catch (IOException e)                 {                    e.printStackTrace();                }            }        }    };    /**     * 获得保存图片的文件     * @return     * @date 2015年4月3日     * @time 下午5:18:03     * @author Tony     */    @SuppressLint("SimpleDateFormat")    private File getImageFile()    {        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "TONY";        File imageFile = new File(FileUtil.EXAMPLE_PATH + Constant.IMAGE +File.separator + timeStamp + ".jpg");        return imageFile;    }    /**     * 获得相机实例     * @param cameraPosition     * @return     * @date 2015年4月3日     * @time 下午5:15:25     * @author Tony     */    public Camera getCameraInstance(int cameraPosition)    {        if (cameraPosition < 0 || cameraPosition > cameraCount) {            cameraPosition = 0;        }        Camera mCamera = null;        try        {            mCamera = Camera.open(cameraPosition);        }        catch (Exception e)        {            //相机别的app在使用,或者是不存在        }        return mCamera;    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        if (!hasSurface) {            hasSurface = true;            if (mCamera == null) {                initCamera(holder);            }            mCamera.startPreview();        }        hasSurface = true;    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width,            int height) {    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        hasSurface = false;    }    private void changeCamera()    {        if (cameraCount <= 1) {            return;        }        mCamera.stopPreview();        mCamera.release();        mCamera = null;        cameraPosition = cameraPosition == 1 ? 0:1;          mCamera = getCameraInstance(cameraPosition);        mCamera.setFaceDetectionListener(mFaceDetectionListener);        startPreviewOfCamera(viewHolder);        mCamera.startPreview();        mCamera.startFaceDetection();    }    private void startFaceDectection()    {        // Try starting Face Detection        Camera.Parameters params = mCamera.getParameters();        // start face detection only *after* preview has started        if (params.getMaxNumDetectedFaces() > 0){            mCamera.startFaceDetection();        }    }    private FaceDetectionListener mFaceDetectionListener = new FaceDetectionListener()    {        @Override        public void onFaceDetection(Face[] faces, Camera camera) {            if (faces.length > 0) {                Log.e("====人脸识别====","" + faces[0].leftEye.x );            }        }    };}

布局文件就不贴了吧。很简单,一个SurfaceView,三个button,还有一个SeekBar

1 0
原创粉丝点击