16

我的要求既不是显示相机预览,也不是使用相机意图进行图像捕捉。

在那里,我找到了一种适用于我的第一个测试设备(Galaxy tab 7")的方法。

我的CaptureImage功能如下

private void CaptureImage() {
        int FrontCameraFound = getCameraID();
        if (FrontCameraFound != -1) {
            mCamera = Camera.open(FrontCameraFound);

            parameters = mCamera.getParameters();

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

            Camera.PictureCallback mCall = new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {

                    bmp = BitmapFactory.decodeByteArray(data, 0, data.length);

                    // set bitmap tp image view just to check 
                    // if image capture proper, testing purpose
                    iv_image.setImageBitmap(bmp);

                    mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null;
                }
            };
            mCamera.takePicture(null, null, mCall);
        }
    }

getCameraID功能如下

private int getCameraID() {
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();

    for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        // for capture image from back camera
        // If want to capture from front 
        // then change it to CAMERA_FACING_FRONT
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            try {
                return camIdx;
            } catch (RuntimeException e) {

            }
        }
    }
    return -1;
}

现在我面临在不同设备上成功运行以上代码的困难。

  • 三星 Galaxy S+ (2.3.6):前置摄像头总是返回绿色图像,但后置摄像头的编码工作正常。
  • 三星 Galaxy Nexus (4.1):编码不起作用 无论是前置摄像头还是后置摄像头,“takePicture”都失败。
  • LG Optimus Net (2.3.4):只有后置摄像头并且工作正常。
  • 三星 Galaxy Tab 7" (2.3.3):两个摄像头都工作正常。
  • 摩托罗拉 Xoom (3.1):两台相机工作正常。

三星 Galaxy Nexus 的 Logcat:

09-21 09:37:42.125: E/AndroidRuntime(4647): Caused by: java.lang.RuntimeException: takePicture failed
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.native_takePicture(Native Method)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.takePicture(Camera.java:1061)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.takePicture(Camera.java:1006)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at fortyonepost.com.pwop.TakePictureDemoActivity.CaptureImage(TakePictureDemoActivity.java:63)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at fortyonepost.com.pwop.TakePictureDemoActivity.onCreate(TakePictureDemoActivity.java:36)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.Activity.performCreate(Activity.java:5008)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)

不可能检查每个设备的代码,我只是在 5 个设备上测试我的代码,并且 2 个设备导致问题,所以有没有任何标准方法可以在没有意图和预览的情况下从相机获取图像。

请注意,我在清单中包含并将最低 sdk 版本设置为 9

更新:takePicture Failed在Camera.java 类中第 1061 行的 4.1 Nexus Galaxy中,这是类链接,它为我提供了native_takePicture(msgType); function in Camera.java确实抛出的信息

4

3 回答 3

3

android 设备中的相机处理是主要的 PITA - 不同的设备(甚至同一设备上的 android 版本)可以而且肯定会有不同的行为。基本上,您正在与设备上的一些恶魔进程交谈,它们彼此不同。

我没有解决所有问题的方法,但这是我迄今为止的发现

  • 并非所有分辨率都能正常工作,即使它们在相机参数中进行了宣传。您必须在设置相机时对其进行测试,以防出现问题
  • 预览数据通过映射的内存区域提供给您
  • NV21 格式始终提供并且应为默认格式,但我会查询相机设置。当您打开相机时,它可以从之前使用相机的其他应用程序中进行一些设置。(据说打开时相机会重置为默认值)

我已经开发了一些为 JavaOCR 项目开发的相机管理工具,它适用于大多数设备。随意以此为灵感:

http://sourceforge.net/p/javaocr/code/240/tree/trunk/demos/camera-utils/src/main/java/net/sf/javaocr/demos/android/utils/camera/CameraManager.java

于 2012-09-26T08:39:49.533 回答
3

经过几次搜索,我发现相机的预览是必要的,我想知道我的代码如何在某些设备上运行良好,即使它是错误的。

任何方式的解决方案是,

我们需要在表面视图上保持相机预览,我们可以将该表面视图隐藏在任何其他视图后面,我在 framelayout 中获取表面视图(我知道它已被弃用),在它上面我获取图像视图,对于表面视图我只取 80*80 dp 表面视图,因为像 30*30 dp 这样的小表面视图不起作用,并且再次出现错误。

于 2012-10-03T10:44:21.783 回答
1

您需要使用 Camera.setOneShotPreviewCallback 方法,然后处理图像

尝试使用 YuvImage 并在将其传递给 bitmapfactory 之前对其进行压缩,如下所示:

YuvImage yuvimage = new YuvImage(byteArr, ImageFormat.NV21, width, height, null);
    Rect rect = new Rect(0, 0, width, height);
    ByteArrayOutputStream outstr = new ByteArrayOutputStream();
    yuvimage.compressToJpeg(rect, 100, outstr);
    Bitmap bm = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());

编辑:

您必须使用表面视图,但表面视图可以隐藏在另一个视图下方,因此它在屏幕上不可见,但仍然存在并处于活动状态。

于 2012-10-01T20:38:31.530 回答