Android 2.2 SDK - 针对Nexus One上的Camera API的setParameters失败

时间:2010-12-29 21:02:23

标签: android mobile android-emulator android-2.2-froyo

我正在使用稍微修改过的Camera API Demo版本,它可以在模拟器中使用。我正在使用我在其中一个邮件组中找到的反射类,但在我的Nexus One(Android 2.2.1)上测试时仍然出现此错误:

12-29 13:22:04.027: ERROR/QualcommCameraHardware(2145): Invalid preview size requested: 320x402
12-29 13:22:04.037: DEBUG/AndroidRuntime(16514): Shutting down VM
12-29 13:22:04.037: WARN/dalvikvm(16514): threadid=1: thread exiting with uncaught exception (group=0x4001d7f0)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514): FATAL EXCEPTION: main
12-29 13:22:04.047: ERROR/AndroidRuntime(16514): java.lang.RuntimeException: setParameters failed
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.hardware.Camera.native_setParameters(Native Method)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.hardware.Camera.setParameters(Camera.java:647)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at com.android.iwasthere.Preview.surfaceChanged(Preview.java:78)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.SurfaceView.updateWindow(SurfaceView.java:538)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.SurfaceView.dispatchDraw(SurfaceView.java:339)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.View.draw(View.java:6743)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.View.draw(View.java:6743)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewRoot.draw(ViewRoot.java:1407)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.os.Looper.loop(Looper.java:123)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at android.app.ActivityThread.main(ActivityThread.java:4627)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at java.lang.reflect.Method.invokeNative(Native Method)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at java.lang.reflect.Method.invoke(Method.java:521)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-29 13:22:04.047: ERROR/AndroidRuntime(16514):     at dalvik.system.NativeStart.main(Native Method)

CameraPreview.java

package xxx;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

public class CameraPreview extends Activity {

    private Preview mPreview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        mPreview = new Preview(this);
        setContentView(mPreview);

    }

}

Preview.java

package xxx;
import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class Preview extends SurfaceView implements SurfaceHolder.Callback {

    SurfaceHolder mHolder;
    Camera mCamera;

    Preview(Context context) {
        super(context);

        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    public void surfaceCreated(SurfaceHolder holder) {

        mCamera = Camera.open();
        try {

           mCamera.setPreviewDisplay(holder);

        } catch (IOException exception) {

            mCamera.release();
            mCamera = null;

        }

    }

    public void surfaceDestroyed(SurfaceHolder holder) {

        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;

    }


    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {

        final double ASPECT_TOLERANCE = 0.05;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

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

        int targetHeight = h;

        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);
            }
        }

        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;

    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

        Camera.Parameters parameters = mCamera.getParameters();

        //MODIFIED HERE
        List<Size> sizes = Reflect.getSupportedPictureSizes(parameters);
        //List<Size> sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, w, h);
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);

        mCamera.setParameters(parameters);
        mCamera.startPreview();

    }

}

Reflect.java

package xxx;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import android.hardware.Camera;
import android.hardware.Camera.Size;

public class Reflect {

    private static Method Parameters_getSupportedPictureSizes;
    private static Method Parameters_getSupportedPreviewSizes;

    static {
        initCompatibility();
    };

    private static void initCompatibility() {
        try {
            Parameters_getSupportedPictureSizes = Camera.Parameters.class
                    .getMethod("getSupportedPictureSizes", new Class[] {});
            /* success, this is a newer device */
        } catch (NoSuchMethodException nsme) {
            /* failure, must be older device */
        }
        try {
            Parameters_getSupportedPreviewSizes = Camera.Parameters.class
                    .getMethod("getSupportedPreviewSizes", new Class[] {});
            /* success, this is a newer device */
        } catch (NoSuchMethodException nsme) {
            /* failure, must be older device */
        }
    }

    @SuppressWarnings("unchecked")
    public static List<Size> getSupportedPictureSizes(Camera.Parameters p) {
        try {
            if (Parameters_getSupportedPictureSizes != null) {
                return (List<Size>) Parameters_getSupportedPictureSizes
                        .invoke(p);
            } else {
                return null;
            }
        } catch (InvocationTargetException ite) {
            /* unpack original exception when possible */
            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) {
            System.err.println("unexpected " + ie);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public static List<Size> getSupportedPreviewSizes(Camera.Parameters p) {
        try {
            if (Parameters_getSupportedPreviewSizes != null) {
                return (List<Size>) Parameters_getSupportedPreviewSizes
                        .invoke(p);
            } else {
                return null;
            }
        } catch (InvocationTargetException ite) {
            /* unpack original exception when possible */
            Throwable cause = ite.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            } else {
                /*
                 * unexpected checked exception; wrap and re-throw
                 */
                throw new RuntimeException(ite);
            }
        } catch (IllegalAccessException ie) {
            return null;
        }
    }
}

1 个答案:

答案 0 :(得分:2)

  

请求的预览尺寸无效:   320x402

您无法使用任意预览尺寸。您需要使用Camera.Parameters.getSupportedPreviewSizes()和Camera.Parameters.getSupportedPictureSizes()来查找最接近您所需尺寸的预览和图片大小。