Android用摄像头的那点破事

摄像头不是所有随便的(w, h)都能够认识的,所以呢,我们有了下面这样的增强版:

List<Size> mSupportedPreviewSizes;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

后来的Sample里有了这段代码,看起来强大了不少。然而非常不幸的,首先getSupportedPreviewSizes()这个函数在2.1之后才有,我一开始是打算用1.6开发的……好吧我改,这个先不说,自己的手机已经刷到2.1了,这个函数的返回值居然是null?!如果确实想老版本上也用的话,怎么办??

有鉴于有软件可以达成,所以肯定是有方法的!得这么写:

public class SupportedSizesReflect {
	private static Method Parameters_getSupportedPreviewSizes = null;
	private static Method Parameters_getSupportedPictureSizes = null;

	static {
		initCompatibility();
	};

	private static void initCompatibility() {
		try {
			Parameters_getSupportedPreviewSizes = Camera.Parameters.class.getMethod(
					"getSupportedPreviewSizes", new Class[] {});

			Parameters_getSupportedPictureSizes = Camera.Parameters.class.getMethod(
					"getSupportedPictureSizes", new Class[] {});

		} catch (NoSuchMethodException nsme) {
			nsme.printStackTrace();
			Parameters_getSupportedPreviewSizes = Parameters_getSupportedPictureSizes = null;
		}
	}

	/**
	 * Android 2.1之后有效
	 * @param p
	 * @return Android1.x返回null
	 */
	public static List<Size> getSupportedPreviewSizes(Camera.Parameters p) {
		return getSupportedSizes(p, Parameters_getSupportedPreviewSizes);
	}

	public static List<Size> getSupportedPictureSizes(Camera.Parameters p){
		return getSupportedSizes(p, Parameters_getSupportedPictureSizes);
	}	

	@SuppressWarnings("unchecked")
	private static List<Size> getSupportedSizes(Camera.Parameters p, Method method){
		try {
			if (method != null) {
				return (List<Size>) method.invoke(p);
			} else {
				return null;
			}
		} catch (InvocationTargetException ite) {
			Throwable cause = ite.getCause();
			if (cause instanceof RuntimeException) {
				throw (RuntimeException) cause;
			} else if (cause instanceof Error) {
				throw (Error) cause;
			} else {
				throw new RuntimeException(ite);
			}
		} catch (IllegalAccessException ie) {
			return null;
		}
	}
}

啊啊~,リフレクションなんか、大嫌い……然后还要用类似这样的方法调用~

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {

	Camera.Parameters params = camera.getParameters();

	List<Size> supportedPictureSizes
				= SupportedSizesReflect.getSupportedPictureSizes(params);
	List<Size> supportedPreviewSizes
				= SupportedSizesReflect.getSupportedPreviewSizes(params);

	if ( supportedPictureSizes != null &&
		supportedPreviewSizes != null &&
		supportedPictureSizes.size() > 0 &&
		supportedPreviewSizes.size() > 0) {

		//2.x
		pictureSize = supportedPictureSizes.get(0);

		int maxSize = 1280;
		if(maxSize > 0){
			for(Size size : supportedPictureSizes){
				if(maxSize >= Math.max(size.width,size.height)){
					pictureSize = size;
					break;
				}
			}
		}

		WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		DisplayMetrics displayMetrics = new DisplayMetrics();
		display.getMetrics(displayMetrics);

		previewSize = getOptimalPreviewSize(
							supportedPreviewSizes,
							display.getWidth(),
							display.getHeight()); 

		params.setPictureSize(pictureSize.width, pictureSize.height);
		params.setPreviewSize(previewSize.width, previewSize.height);								

	}
	this.camera.setParameters(params);
	try {
		this.camera.setPreviewDisplay(holder);
	} catch (IOException e) {
		e.printStackTrace();
	}
	this.camera.startPreview();
}


预览画面90°的,2.X后可以用parameters.set(“rotation”, “90″),之前的话得写成parameters.set(“orientation”, “portrait”)。但是据说不是所有的机器都可以的……

你可能感兴趣的:(Android用摄像头的那点破事)