android前后摄像头切换demo,startview后的页面上有切换、拍照两个按钮,拍照后照片未保存,需要保存的请看下方注释,实现了拍照、聚焦功能,以下是CameraPreview.java源码:
package com.myselftest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import android.widget.RelativeLayout;
import android.view.MotionEvent;
import android.app.Activity;
import android.view.View.OnClickListener;
import android.hardware.Camera.CameraInfo;
import android.os.SystemProperties;
import android.view.View.OnTouchListener;
import android.graphics.Rect;
import android.hardware.Camera.PictureCallback;
public class CameraPreview extends Activity implements OnClickListener, SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private Camera mCamera;
private Camera.Parameters mCameraParam;
private int mPrvW = 800;
private int mPrvH = 600;
private final AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
private long mFocusCallbackTime;
private FocusIndicatorView mFocusIndicatorView;
private static final int WIDTH_DP = 80;
private static final int HEIGTH_DP = 80;
private boolean focusing = false;
private boolean state;
private TextView btn_position = null;
private TextView btn_capture = null;
private SurfaceHolder holder = null;
private VideoPreview mVideoPreview;
private int cameraPosition = 1; //1,camera_back 0,camera_front
private int cameraId;
private RelativeLayout mRelativeLayout;
CameraInfo ci = null;
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_preview);
Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
btn_position = (TextView) findViewById(R.id.btn_position);
btn_capture = (TextView) findViewById(R.id.btn_capture);
mPrvW = this.getWindow().getWindowManager().getDefaultDisplay().getWidth();
mPrvH = mPrvW*4/3;
mFocusIndicatorView = new FocusIndicatorView(this);
int width_px = dip2px(this, WIDTH_DP);
int heigth_px = dip2px(this, HEIGTH_DP);
RelativeLayout.LayoutParams mLayoutParams = new RelativeLayout.LayoutParams(width_px, heigth_px);
int[] rules = mLayoutParams.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = 1;
mRelativeLayout = (RelativeLayout) findViewById(R.id.main_layout);
mRelativeLayout.addView(mFocusIndicatorView, mLayoutParams);
mRelativeLayout.setOnTouchListener(onTouchListener);
mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
btn_position.setOnClickListener(this);
btn_capture.setOnClickListener(this);
}
@Override
public void onClick(View v){
if(v.equals(btn_position)){
camera_position();
}else if(v.equals(btn_capture)){
rawCapture();
}
}
@Override
protected void onResume() {
super.onResume();
mVideoPreview.setAspectRatio(mPrvW, mPrvH);
holder = mVideoPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public boolean onTouchEvent(MotionEvent event) {
if(focusing == false) {
focusing = true;
mFocusIndicatorView.showStart();
mCamera.autoFocus(mAutoFocusCallback);
}
return true;
}
public class FocusIndicatorView extends View {
public FocusIndicatorView(Context context) {
super(context);
}
private void setDrawable(int resid) {
setBackgroundDrawable(getResources().getDrawable(resid));
}
public void showStart() {
setDrawable(R.drawable.ic_focus_focusing);
}
public void showSuccess() {
setDrawable(R.drawable.ic_focus_focused);
}
public void showFail() {
setDrawable(R.drawable.ic_focus_failed);
}
public void clear() {
setBackgroundDrawable(null);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i(TAG, "surfaceChanged width is : " + width+" height is"+height+" ci.orientation="+ci.orientation);
startPreview(ci.orientation);
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
ci = new CameraInfo();
Camera.getCameraInfo(0, ci);
openCamera(0);
cameraId = 0;
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
closeCamera();
Log.i(TAG, "surfaceCreated closeCamera ");
}
}
private void openCamera(int cmaId) {
if (mCamera == null) {
mCamera = Camera.open(cmaId);
cameraId = cmaId;
Log.i(TAG, "Enter openCamera to init the mCamera.");
if (null == mCamera) {
Log.i(TAG, "init the mCamera is null.");
}
}
}
private void closeCamera() {
if (null != mCamera) {
mCamera.release();
mCamera = null;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
stopPreview();
closeCamera();
Log.i(TAG, "surfaceDestroyed closeCamera ");
}
private void stopPreview() {
if (null != mCamera) {
mCamera.stopPreview();
}
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
if (0 == msg.what) {
mFocusIndicatorView.clear();
}
}
};
private void startPreview(int orientation) {//orientation:当前所选摄像头的偏转角度
if (null != mCamera) {
mCameraParam = mCamera.getParameters();
}else{
return;
}
Size size = mCameraParam.getPictureSize();
List<Size> sizes = mCameraParam.getSupportedPreviewSizes();
Size optimalSize = null;
if (size != null && size.height != 0) {
optimalSize = getOptimalPreviewSize(sizes, (double) mPrvH / mPrvW);
}
if (optimalSize != null) {
mCameraParam.setPreviewSize(optimalSize.width, optimalSize.height);
} else {
mCameraParam.setPreviewSize(mPrvW, mPrvH);
}
mCameraParam.set("fps-mode", 0); // Frame rate is normal
mCameraParam.set("cam-mode", 0); // Cam mode is preview
if (cameraPosition == 1) {
mCameraParam.setFocusMode(mCameraParam.FOCUS_MODE_CONTINUOUS_PICTURE);
mCameraParam.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
}
mCamera.setDisplayOrientation(orientation);
mCamera.setParameters(mCameraParam);
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
}
private Size getOptimalPreviewSize(List<Size> sizes, double targetRatio) {
final double ASPECT_TOLERANCE = 0.05;
if (sizes == null) {
return null;
}
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
Display display = getWindowManager().getDefaultDisplay();
int targetHeight = Math.min(display.getHeight(), display.getWidth());
if (targetHeight <= 0) {
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
targetHeight = windowManager.getDefaultDisplay().getHeight();
}
Log.d(TAG, "getOptimalPreviewSize() sizes.size = " + sizes.size());
int i = 1;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
i++;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
Log.d(TAG, "No preview size match the aspect ratio");
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
} else {
Log.d(TAG, String.format("Optimal preview size is %sx%s", optimalSize.width, optimalSize.height));
}
return optimalSize;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
return true;
case KeyEvent.KEYCODE_SEARCH:
return true;
case KeyEvent.KEYCODE_FOCUS:
return true;
case KeyEvent.KEYCODE_BACK:
break;
}
return super.onKeyDown(keyCode, event);
}
private void camera_position(){
CameraInfo cameraInfo = new CameraInfo();
int cameraCount = Camera.getNumberOfCameras();
for(int i = 0; i <cameraCount; i++){
Camera.getCameraInfo(i, cameraInfo);
Log.d(TAG, "cameraOrientation-"+i+":"+cameraInfo.orientation);
if(cameraPosition == 0){
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK){
stopPreview();
closeCamera();
openCamera(i);
cameraPosition = 1;
if (null != mCamera) {
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException ex) {
closeCamera();
Log.i(TAG, "camera_position closeCamera "+i);
ex.printStackTrace();
}
startPreview(cameraInfo.orientation);
}
break;
}
}else{
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
stopPreview();
closeCamera();
openCamera(i);
cameraPosition = 0;
if (null != mCamera) {
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException ex) {
closeCamera();
Log.i(TAG, "camera_position closeCamera "+i);
ex.printStackTrace();
}
startPreview(90);
}
break;
}
}
}
}
private void rawCapture() {
if(mCamera != null){
try {
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
mCamera.takePicture(null, null, new JpegPictureCallback());
Toast.makeText(this, getString(R.string.cma_capture_success), Toast.LENGTH_LONG).show();
mCamera.stopPreview();
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}catch(Exception ex){
closeCamera();
ex.printStackTrace();
}
Log.i(TAG, "rawCapture function end");
}
}
private final class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback {
public void onAutoFocus(boolean focused, android.hardware.Camera camera) {
mFocusCallbackTime = System.currentTimeMillis();
Log.i(TAG, "mFocusCallbackTime is " + mFocusCallbackTime);
if(focused && !state) {
mFocusIndicatorView.showSuccess();
mHandler.sendEmptyMessageDelayed(0, 1500);
} else if(!focused){
mHandler.removeMessages(0);
mFocusIndicatorView.showFail();
}
focusing = false;
state = focused;
}
}
private final class JpegPictureCallback implements PictureCallback {
public void onPictureTaken(byte[] jpegData, android.hardware.Camera camera) {
Log.d(TAG, "mJpegPictureCallbackTime = " + System.currentTimeMillis());
if (jpegData != null) {
storeImage(jpegData);
}
}
}
private void storeImage(byte[] jpegData) {//本例未保存所拍照片,如需要保存,请取消下方的注释
String name = "factorymode_test.jpg";
// File fHandle = new File(name);
// try {
// OutputStream bos = new FileOutputStream(fHandle);
// bos.write(jpegData);
// bos.close();
// long storeImageTime = System.currentTimeMillis();
// Log.d(TAG, "storeImageTime = " + storeImageTime);
// } catch (Exception ex) {
// fHandle.delete();
// }
}
OnTouchListener onTouchListener = new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event){
mFocusIndicatorView.setX(event.getX());
mFocusIndicatorView.setY(event.getY());
if(event.getAction() == MotionEvent.ACTION_DOWN){
mFocusIndicatorView.showSuccess();
}else if(event.getAction() == MotionEvent.ACTION_UP){
mFocusIndicatorView.showFail();
if(cameraPosition == 1){
focusOnTouch(event);
}
}
return true;
}
};
private void focusOnTouch(MotionEvent event){
int [] location = new int[2];
mRelativeLayout.getLocationOnScreen(location);
Rect focusRect = calculateTapArea(mVideoPreview.getWidth(), mVideoPreview.getHeight(), 1f, event.getRawX(),
event.getRawY(), location[0], location[0] + mRelativeLayout.getWidth(), location[1], location[1] + mRelativeLayout.getHeight());
Rect meteringRect = calculateTapArea(mVideoPreview.getWidth(), mVideoPreview.getHeight(), 1.5f, event.getRawX(),
event.getRawY(), location[0], location[0] + mRelativeLayout.getWidth(), location[1], location[1] + mRelativeLayout.getHeight());
mCameraParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if(mCameraParam.getMaxNumFocusAreas() > 0){
List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
focusAreas.add(new Camera.Area(focusRect, 1000));
mCameraParam.setFocusAreas(focusAreas);
}
if(mCameraParam.getMaxNumMeteringAreas() > 0){
List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
meteringAreas.add(new Camera.Area(meteringRect, 1000));
mCameraParam.setMeteringAreas(meteringAreas);
}
if(mCamera != null){
mCamera.setParameters(mCameraParam);
}
mCamera.autoFocus(mAutoFocusCallback);
}
private Rect calculateTapArea(int focusWidth, int focusHeight, float areaMultiple, float x, float y, int previewLeft, int previewRight, int preViewTop, int preViewBottom){
int areaWidth = (int)(focusWidth * areaMultiple);
int areaHeight = (int)(focusHeight * areaMultiple);
int centerX = (previewLeft + previewRight) / 2;
int centerY = (preViewTop + preViewBottom) / 2;
double unitx = (((double)previewRight - (double)previewLeft)) /2000;
double unity = (((double)preViewBottom - (double)preViewTop)) /2000;
int left = clamp((int)(((x - areaWidth / 2) - centerX) / unitx), -1000, 1000);
int top = clamp((int)(((y - areaHeight / 2) - centerY) / unity), -1000, 1000);
int right = clamp((int)(left + areaWidth / unitx), -1000, 1000);
int bottom = clamp((int)(top + areaHeight / unity), -1000, 1000);
return new Rect(left, top, right, bottom);
}
private int clamp(int x, int min, int max){
if(x > max){
return max;
}
if(x < min){
return min;
}
return x;
}
}
camera_preview.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/main_layout"
android:orientation="vertical">
<com.myselftest.VideoPreview
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"/>
<Button
android:id="@+id/btn_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="33dp"
android:gravity="center"
android:text="@string/cma_capture" />
<Button
android:id="@+id/btn_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="48dp"
android:gravity="center"
android:text="@string/cma_position" />
</RelativeLayout>
以上代码在android6.0上测试通过。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。