Android 自定义相机开发(支持前置,后置摄像头,可以自动聚焦,保存和显示图片)

实现功能:
自定义相机开发:支持前置,后置摄像头切换,可以自动聚焦,保存图片和显示图片

实现代码:
一,布局activity_camera.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.camerademo.view.CameraPreview
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/focusView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

    <Button
        android:id="@+id/btn_take_picture"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="15dp"
        android:background="@drawable/btn_camera_default" />

    <Button
        android:id="@+id/btn_swich_camera"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:layout_marginRight="15dp"
        android:background="@drawable/ic_switch_camera" />

</RelativeLayout>

三,CameraPreview.java

package com.example.camerademo.view;

import java.io.IOException;


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 *@Description: 
 * @author zhuzhifeng
 * @date 2016年3月18日 上午9:20:41
 */

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView 
        implements SurfaceHolder.Callback {
	/** LOG标识 */
	// private static final String TAG = "CameraPreview";

	/** 分辨率 */
	public static final int WIDTH = 1024;
	public static final int HEIGHT = 768;

	/** 监听接口 */
	private OnCameraStatusListener listener;

	private SurfaceHolder holder;
	private Camera camera;
	private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头



	// 创建一个PictureCallback对象,并实现其中的onPictureTaken方法
	private PictureCallback pictureCallback = new PictureCallback() {

		// 该方法用于处理拍摄后的照片数据
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {

			// 停止照片拍摄
			camera.stopPreview();
			camera = null;

			// 调用结束事件
			if (null != listener) {
				listener.onCameraStopped(data);
			}
		}
	};
	private PictureCallback rawCallback = new PictureCallback() {
		public void onPictureTaken(byte[] _data, Camera _camera) {
			/* 要处理raw data?写?否 */
		}
	};
	/*为了实现拍照的快门声音及拍照保存照片需要下面三个回调变量*/
	ShutterCallback myShutterCallback = new ShutterCallback() 
	//快门按下的回调,在这里我们可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。
	{

		public void onShutter() {
			// TODO Auto-generated method stub


		}
	};
	/*public AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
		
		@Override
		public void onAutoFocus(boolean success, Camera camera) {
			System.out.println("----> onAutoFocus");			
		}
	};*/
	// Preview类的构造方法
	public CameraPreview(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 获得SurfaceHolder对象
		holder = getHolder();
		// 指定用于捕捉拍照事件的SurfaceHolder.Callback对象
		// 只要是实现SurfaceHolder.Callback接口的对象都行
		holder.addCallback(this);
		// 设置SurfaceHolder对象的类型
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		
		

	}

	// 在surface创建时激发
	public void surfaceCreated(SurfaceHolder holder) {
		// Log.e(TAG, "==surfaceCreated==");

		
		try {
			
			initCamera();


			if (null != listener) {
				listener.onTouchFocus(camera);
			}
		} catch (IOException e) {
			e.printStackTrace();
			// 释放手机摄像头
			camera.release();
			camera = null;
		}
	}

	// 在surface销毁时激发
	public void surfaceDestroyed(SurfaceHolder holder) {
		// Log.e(TAG, "==surfaceDestroyed==");
		if (camera != null) {
			camera.setPreviewCallback(null); /*在启动PreviewCallback时这个必须在前不然退出出错。 
			           这里实际上注释掉也没关系*/  

			camera.stopPreview();
			// 释放手机摄像头
			camera.release();
		}
	}

	// 在surface的大小发生改变时激发
	public void surfaceChanged(final SurfaceHolder holder, int format, int w, int h) {

      
	}

	/**
	 * @throws IOException 
	 * 
	 */


	protected void initCamera() throws IOException {
	    // 获得Camera对象
		camera = Camera.open();
		// 设置用于显示拍照摄像的SurfaceHolder对象
					camera.setPreviewDisplay(holder);
		// 获取照相机参数
		Camera.Parameters parameters = camera.getParameters();
		// 设置照片格式
		parameters.setPictureFormat(PixelFormat.JPEG);

		//parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);//加上闪光灯模式会报错
		// 1连续对焦
		parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);

		// 设置预浏尺寸
		parameters.setPreviewSize(WIDTH, HEIGHT);
		// 设置照片分辨率
		parameters.setPictureSize(WIDTH, HEIGHT);
//
//		//设置大小和方向等参数
//		parameters.setPictureSize(1280, 960);
//		parameters.setPreviewSize(960, 720);
		// 设置照相机参数
		camera.setParameters(parameters);
		// 开始拍照
		camera.startPreview();
		camera.cancelAutoFocus();// 一定要加上这句,才可以连续聚集

		
	}

	// 停止拍照,并将拍摄的照片传入PictureCallback接口的onPictureTaken方法
	public void takePicture(boolean isAutoFocus) {
		// Log.e(TAG, "==takePicture==");
		if (camera != null) {
			if (true == isAutoFocus) {
				// 自动对焦
				camera.autoFocus(new AutoFocusCallback() {
					@Override
					public void onAutoFocus(boolean success, Camera camera) {
						if (null != listener) {
							listener.onAutoFocus(success);
				
						}
						// 自动对焦成功后才拍摄
						if (success) {
							camera.takePicture(myShutterCallback, rawCallback, pictureCallback);
						}
					}
				});
			} else {
				camera.takePicture(myShutterCallback, rawCallback, pictureCallback);
			}
		}
	}

	// 设置监听事件
	public void setOnCameraStatusListener(OnCameraStatusListener listener) {
		this.listener = listener;
	}

	/**
	 * 相机拍照监听接口
	 */
	public interface OnCameraStatusListener {

		// 相机拍照结束事件
		void onCameraStopped(byte[] data);

		// 拍摄时自动对焦事件
		void onAutoFocus(boolean success);

		// 触摸屏幕对焦事件
		void onTouchFocus(Camera mCamera);
	}
	/**
	 * 选择前置还是后置摄像头
	 */


	@SuppressLint("NewApi")
	public void switchCamera() {
        //切换前后摄像头
        int cameraCount = 0;
        CameraInfo cameraInfo = new CameraInfo();
        cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数

        for(int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
            if(cameraPosition == 1) {
                //现在是后置,变更为前置
                if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置  
                    camera.stopPreview();//停掉原来摄像头的预览
                    camera.release();//释放资源
                    camera = null;//取消原来摄像头
                    camera = Camera.open(i);//打开当前选中的摄像头
                    try {
                        camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    camera.startPreview();//开始预览
                    cameraPosition = 0;
                    break;
                }
            } else {
                //现在是前置, 变更为后置
                if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置  
                    camera.stopPreview();//停掉原来摄像头的预览
                    camera.release();//释放资源
                    camera = null;//取消原来摄像头
                    camera = Camera.open(i);//打开当前选中的摄像头
                    try {
                        camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    camera.startPreview();//开始预览
                    cameraPosition = 1;
                    break;
                }
            }

        }
	}
	
//	/**
//	 * 打开默认摄像头
//	 */
//	public void openCamera() {
//		int cameraId = CameraHelper.getFutureCameraId(mActivity);
//		openCamera(cameraId);
//	}

}

四,CameraActivity.java

package com.example.camerademo;

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

import com.example.camerademo.view.CameraPreview;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

/**
 *@Description: 
 * @author zhuzhifeng
 * @date 2016年3月18日 上午9:34:25
 */
public class CameraActivity extends Activity 
        implements CameraPreview.OnCameraStatusListener,OnClickListener {

	public static final Uri IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
	public static final String PATH = Environment.getExternalStorageDirectory().toString() + "/AndroidMedia/";

	private CameraPreview mCameraPreview;
	private ImageView focusView;
	private boolean isTaking = false; // 拍照中
	private boolean isAutoFocus;// 是否自动对焦
	private Button mBtnTakePicture;
	private Camera camera;
    private AutoFocusCallback autofocuscallback = new AutoFocusCallback() {
		
		@Override
		public void onAutoFocus(boolean success, Camera camera) {
			// TODO Auto-generated method stub
		System.out.println("----->> onAutoFocus ");
		}
	};
	private Button mSwitchCamera;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 设置横屏
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		// 设置全屏
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		// 照相预览界面
		setContentView(R.layout.activity_camera);
		// 照相预览界面
		mCameraPreview = (CameraPreview) findViewById(R.id.preview);
		mBtnTakePicture = (Button)findViewById(R.id.btn_take_picture);
		mSwitchCamera = (Button)findViewById(R.id.btn_swich_camera);
		mSwitchCamera.setOnClickListener(this);
		
		mCameraPreview.setOnCameraStatusListener(this);
		mCameraPreview.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN && !isTaking) {
                    if(camera != null){
                    	camera.autoFocus(autofocuscallback);
                    	System.out.println("----> onTouch");
                    }
				
				}
				return false;
				
			}
		});
	
	
		
		mBtnTakePicture.setOnClickListener(this);
		// 焦点图片
		focusView = (ImageView) findViewById(R.id.focusView);
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		isAutoFocus = prefs.getBoolean("preferences_autoFocus", false);
	}

	/**
	 * 触屏事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN && !isTaking) {
//			isTaking = true;
//			mCameraPreview.takePicture(isAutoFocus);
		}
		return super.onTouchEvent(event);
	}
	
	/**
	 * 存储图像并将信息添加入媒体数据库
	 */
	private Uri insertImage(ContentResolver cr, String name, long dateTaken, String directory, String filename,
			Bitmap source, byte[] jpegData) {

		OutputStream outputStream = null;
		String filePath = directory + filename;
		try {
			File dir = new File(directory);
			if (!dir.exists()) {
				dir.mkdirs();
			}
			File file = new File(directory, filename);
			if (file.createNewFile()) {
				outputStream = new FileOutputStream(file);
				if (source != null) {
					source.compress(CompressFormat.JPEG, 75, outputStream);
				} else {
					outputStream.write(jpegData);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (Throwable t) {
				}
			}
		}
		ContentValues values = new ContentValues(7);
		values.put(MediaStore.Images.Media.TITLE, name);
		values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
		values.put(MediaStore.Images.Media.DATE_TAKEN, dateTaken);
		values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
		values.put(MediaStore.Images.Media.DATA, filePath);
		return cr.insert(IMAGE_URI, values);
	}

	/**
	 * 相机拍照结束事件
	 */
	@Override
	public void onCameraStopped(byte[] data) {
		Log.e("onCameraStopped", "==onCameraStopped==");
		
		// 创建图像
		Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
		// 系统时间
		long dateTaken = System.currentTimeMillis();
		// 图像名称
		String filename = DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString() + ".jpg";
		// 存储图像(PATH目录)
		Uri uri = insertImage(getContentResolver(), filename, dateTaken, PATH, filename, bitmap, data);
		// 返回结果
		Intent intent = getIntent();
		intent.putExtra("uriStr", uri.toString());
		intent.putExtra("dateTaken", dateTaken);
		// intent.putExtra("filePath", PATH + filename);
		// intent.putExtra("orientation", orientation);  // 拍摄方向
		setResult(20, intent);

		finish();
	}

	/**
	 * 拍摄时自动对焦事件
	 */
	@Override
	public void onAutoFocus(boolean success) {
		// 改变对焦状态图像
		if (success) {
			focusView.setImageResource(R.drawable.right);
		} else {
			focusView.setImageResource(R.drawable.wrong);
			Toast.makeText(this, "焦距不准,请重拍!", Toast.LENGTH_SHORT).show();
			isTaking = false;
		}
	}

	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_take_picture:
			isTaking = true;
			mCameraPreview.takePicture(isAutoFocus);
			break;
		case R.id.btn_swich_camera:
			mCameraPreview.switchCamera();
			break;
		default:
			break;
		}
		
	}

	/* 
	 * 触摸屏幕对焦事件
	 */
	@Override
	public void onTouchFocus(Camera mCamera){
		camera = mCamera;
		
	}


}

五,MainActivity.java

package com.example.camerademo;



import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity {

	private final int REQUEST_CAPTURE_PIC = 100;//拍照请求标识
	private ImageView iv_show;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		iv_show = (ImageView)findViewById(R.id.iv_show);
		
		startCapture();
		
	}
	
	/**
	 * 
	 */
	private void startCapture() {
		// TODO Auto-generated method stub
		Intent intent = new Intent(this, CameraActivity.class);
		startActivityForResult(intent, REQUEST_CAPTURE_PIC);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(requestCode == REQUEST_CAPTURE_PIC){//拍照回来的
			
			if(data != null){
				
			
			Bundle bundle = data.getExtras();
			
			// 获得照片uri
			Uri uri = Uri.parse(bundle.getString("uriStr"));
		
			// 获得拍照时间
			long dateTaken = bundle.getLong("dateTaken");
			try {
				// 从媒体数据库获取该照片
				Bitmap cameraBitmap = MediaStore.Images.Media.getBitmap(
						getContentResolver(), uri);
				previewBitmap(cameraBitmap); // 预览图像
				
			
				// 从媒体数据库删除该照片(按拍照时间)
				getContentResolver().delete(
						CameraActivity.IMAGE_URI,
						MediaStore.Images.Media.DATE_TAKEN + "="
								+ String.valueOf(dateTaken), null);
			
			} catch (Exception e) {
				e.printStackTrace();
			}
			}else{
				
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	/**
	 * @param cameraBitmap
	 */
	private void previewBitmap(Bitmap cameraBitmap) {
		// TODO Auto-generated method stub
		iv_show.setImageBitmap(cameraBitmap);
	}
	
	public void BtnTakePicture(View v){
		startCapture();
	}

}

六:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.camerademo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

几点需要注意:

1)如果项目运行出错,也许是屏幕适配的问题
我这里用的是小米平板,如果你想用手机,需要修改在CameraPreview中的代码,修改如下:

		// 设置预浏尺寸
//		parameters.setPreviewSize(WIDTH, HEIGHT);
//		// 设置照片分辨率
//		parameters.setPictureSize(WIDTH, HEIGHT);
//
		//设置大小和方向等参数
		parameters.setPictureSize(1280, 960);
		parameters.setPreviewSize(960, 720);

2)自动聚焦关键代码:

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);

CameraPreview.java中,如果你去掉了上面这句代码,就不能自动聚焦,只能手动点击屏幕,聚集了


源码下载地址:

http://download.csdn.net/detail/shakdy/9476207






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值