自定义相机(一)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > 自定义相机(一)

自定义相机(一)

 2015/4/23 17:21:45  rw_rongwei  程序员俱乐部  我要评论(0)
  • 摘要:在5.0之前的版本中自定义相机是按如下步骤:一,做一个自定义相机的步骤1.找到并获取相机的权限检测相机的存在,并获取权限检测是否有相机设备代码if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){//有相机设备returntrue;}else{//没有相机设备returnfalse;}检测相机是否可用代码Camerac=null;try{c=Camera.open()
  • 标签:自定义

在5.0之前的版本自定义相机是按如下步骤:

一,做一个自定义相机的步骤

1.找到并获取相机的权限

检测相机的存在,并获取权限

检测是否有相机设备代码

if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // 有相机设备
        return true;
    } else {
        // 没有相机设备
        return false;
    }

检测相机是否可用代码

Camera c = null;
    try {
        c = Camera.open(); // 得到一个相机的实例
    }
    catch (Exception e){
        // 相机不存在或正在被使用
    }

2.建一个预览视图类

该类应为SurfaceView的子类

      作为一个自定义的视图类

        其主要业务是在在不同的事件内,通过传入的Camera实例控制预览视图(Preview)

        具体API的演示代码如下:

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // 如果你的视图可以改变或旋转,需关注这个事件
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

3.建一个预览布局

布局相对比较简单,之后显示相机预览图的SurfaceView将通过代码加在FrameLayout中

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

  <Button
    android:id="@+id/button_capture"
    android:text="Capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    />
</LinearLayout>

在与之对应的Activity中主要代码如下:

public class CameraActivity extends Activity {

    private Camera mCamera;
    private CameraPreview mPreview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // 创建Camera的实例
        mCamera = Camera.open();

        //为Activity添加Preview视图SurfaceView
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }
}

 

4.监听拍照动作

按钮监听动作,然后就开始聚焦

具体代码实现就是和普通监听一样,聚焦则可以使用camera.autoFocus(autoFocusCallBack);

autoFocusCallBack是AutoFocusCallback的实例,主要用来回调对焦完成后的操作。

    比如通过Camera.takePicture(shutter,PictureCallback,PictureCallback)捕获图片

5.捕获图片并保存

通过Camera.takePicture(shutter,PictureCallback,PictureCallback)捕获图片后,需要对图片进行保存

private PictureCallback mPicture = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions: " +
                e.getMessage());
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};
以上是官方API中的Demo,通过onPictureTaken方法获取捕获到的图片数据,可供参考

6.释放相机资源

在之前的surfaceDestroyed中可以通过camera.release释放相机资源以免影响其他应用的使用

以下是自己写的demo,图简单,省了很多,结构也很乱,不过基本的照相功能已实现

package com.rw.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;


public class CameraDemo extends Activity {
    private SurfaceView cameraSurface;
    private SurfaceHolder myHolder;
    private boolean isPreview=false;
    Camera camera;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        setContentView(R.layout.camera_layout);
        
        getView();
        
        //添加回调函数
        myHolder=cameraSurface.getHolder();
        myHolder.addCallback(new Callback() {
            
            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                
            }
            
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    CameraDemo.this.initCamera(holder);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width,
                    int height) {
                
            }
        });
    }

    /**
     * 初始化相机
     * @param holder
     * @throws IOException 
     */
    @SuppressWarnings("deprecation")
    protected void initCamera(SurfaceHolder holder) throws IOException {
        
            if(!isPreview)
                camera=Camera.open(1);
            camera.setDisplayOrientation(90);
        if(camera!=null && !isPreview){
            
            camera.setPreviewDisplay(holder);
            
            camera.startPreview();

            isPreview=true;
        }
    }

    /**
     * 获取视图控件
     */
    private void getView() {
        cameraSurface=(SurfaceView) findViewById(R.id.camera_surface_id);
    }
    /**
     * 捕获图片
     * @param v
     */
    public void takePhoto(View v){
        if(camera!=null){
            Log.i("CameraDemo","开始照相了!");
            camera.autoFocus(autoFocusCallBack);
        }
    }
    //完成自动聚焦后的回调方法
    AutoFocusCallback autoFocusCallBack =new AutoFocusCallback() {
        
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            if(success){
                camera.takePicture(new ShutterCallback() {
                    
                    @Override
                    public void onShutter() {
                        
                    }
                }, new PictureCallback(){

                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        
                    }
                    
                }, jpeg);
            }
        }
    };
    //捕获到图片后的回调方法
    PictureCallback jpeg=new PictureCallback() {
        
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            //根据拍照的数据创建位图
            final Bitmap bm=BitmapFactory.decodeByteArray(data,0, data.length);
            
            File file=new File(Environment.getExternalStorageDirectory(),"testPicture.jpg");
            
            FileOutputStream outStream =null;
            
            try {
                outStream=new FileOutputStream(file);
                bm.compress(CompressFormat.JPEG, 100, outStream);
                outStream.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            camera.stopPreview();
            camera.startPreview();
            isPreview=true;
            
        }
    };
    //释放将相机资源
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(camera!=null){
            camera.release();
        }
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
    }
    
    
    
}
发表评论
用户名: 匿名