1

我正在使用表面视图向用户显示相机预览。这是我的启动方法:

private void pickCam(){
    if (Camera.getNumberOfCameras() < 1)
        return;

    if (Camera.getNumberOfCameras() == 1)
    {
        CameraInfo cInfo=new CameraInfo();
                Camera.getCameraInfo(0, cInfo);
    camera = Camera.open(0);

    }
    else
        camera = Camera.open(currentCamera);


    Camera.Parameters parameters = camera.getParameters();
    parameters = camera.getParameters();
    parameters.setRotation(90);
    try {

        Camera.Size mCameraSize = null;

        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {


            if (size.width <= surfaceWidth && size.height <= surfaceHeight) {

                if (mCameraSize == null)
                    mCameraSize = size;
                else {

                    int currentArea = mCameraSize.width
                            * mCameraSize.height;
                    int newArea = size.width * size.height;

                    if (newArea > currentArea) {

                        mCameraSize = size;
                    }
                }
            }

        }
        parameters.setPreviewSize(mCameraSize.width, mCameraSize.height);

        camera.setParameters(parameters);

        camera.setDisplayOrientation(90);

        camera.setPreviewDisplay(surfaceHolder);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    camera.startPreview();
}

当用户单击按钮时:

if (camera != null)
camera.takePicture(null, null,this);

此代码在 Sony Xperia(2 个摄像头)上运行良好,但在 HTC Wildfire 和三星 Galaxy S+(均为 1 个摄像头)上预览失败。没有异常被抛出,它什么也不显示。我可以在所有这些设备上拍照。

对于两个设备,pickCamMethod 的 LogCat 输出都是空的:

04-23 14:25:22.987: I/System.out(5871): PickCamBegin 
04-23 14:25:23.428: I/System.out(5871): PickCamEnd 

我怎样才能让它在所有情况下都能正常工作?

4

2 回答 2

2

在清单文件中添加权限

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

develoepr 站点有关于该主题的优秀文档。

http://developer.android.com/guide/topics/media/camera.html

我使用了开发者网站上的代码并制作了一个示例。根据您的需要修改以下内容。

在你的活动中

public class MainActivity extends Activity {

private static final int REQUEST_CODE = 1; 
ImageView imageView;
Button b;
private Camera mCamera;
private CameraPreview mPreview;
private Bitmap bitmap;
private PictureCallback mPicture;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    boolean check =checkCameraHardware(MainActivity.this);
    if(check)
    {
         mCamera = getCameraInstance();

        // mCamera.setDisplayOrientation(90);
         setCameraDisplayOrientation(this,
                 1,  mCamera);//requires min sdk 9
    }
    // Create an instance of Camera
    mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
            if(!imagesFolder.exists())
            imagesFolder.mkdirs();   
            File pictureFile = new File(imagesFolder, "image.jpg");

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);

                System.out.println("hello");
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d("No File", "File not found: " + e.getMessage());
            } catch (IOException e) {
                //Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };

    // Create our Preview view and set it as the content of our activity.
    mPreview = new CameraPreview(this, mCamera);
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    preview.addView(mPreview);
     b = (Button) findViewById(R.id.button_capture);
     b.setOnClickListener(new OnClickListener()
      {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
                 mCamera.takePicture(null, null, mPicture);
                 Toast.makeText(MainActivity.this, "Called",1000).show();

        }

      });
  }
 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
         Toast.makeText(this, "Phone has camera", Toast.LENGTH_LONG).show();
        return true;
    } else {
        // no camera on this device
         Toast.makeText(this, "Phone has no camera", Toast.LENGTH_LONG).show();
        return false;
    }
}
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}


@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    mCamera.release();
}
 }

用于预览的 CameraPreview 类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;

public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    mHolder.addCallback(this);
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, now tell the camera where to draw the preview.
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

    if (mHolder.getSurface() == null){
      // preview surface does not exist
      return;
    }

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e){
      // ignore: tried to stop a non-existent preview
    }

    // set preview size and make any resize, rotate or
    // reformatting changes here

    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e){
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>

<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
于 2013-04-23T11:41:20.600 回答
1

您提到的那些设备 HTC Wildfire 和三星 Galaxy S+ 可能在不支持的较低版本的 Android 上运行Camera.getNumberOfCameras()

HTC Wildfire于 2010 年发布,最高支持 Android 2.2 (API Lv.8)

三星 Galaxy S+ , 最高支持 Android 2.3 (API Lv.9/Lv.10)

API 级别指南可在此处找到:Android 开发人员:什么是 API 级别?

因此,您使用的方法Camera.getNumberOfCameras()已添加到 API 9 中(请参阅文档

您可能需要使用Build.VERSION单独处理它们,所以您可以尝试pickCam()像这样更改您的第一行:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
// Means the device is using API Lv.9+
// Use the method that can work for Lv.9+
    if (Camera.getNumberOfCameras() < 1)
        return;

    if (Camera.getNumberOfCameras() == 1)
    {
        CameraInfo cInfo=new CameraInfo();
        Camera.getCameraInfo(0, cInfo);
        camera = Camera.open(0);

    }
    else
        camera = Camera.open(currentCamera);
} else {
// Use alternative method that support lower API levels
    camera = Camera.open();
}

Camera.open()是适用于 2.2 的方法,适用于Camera.open(int)2.3+(请参阅文档

请让我知道这是否适合您。

于 2013-04-23T12:34:17.787 回答