相机无法在HTC设备上打开

时间:2013-12-25 09:32:36

标签: android nullpointerexception android-camera surfaceview surfaceholder

我根据提供的here代码示例构建了一个Camera,并使用来自AOSP GingerBread的Camera.java和ShutterButton.java对其进行了增强,我带走的代码主要用于自动对焦和ShutterButton 。相机已经在Samsung Galaxy Nexus以及运行4.0.x的Samsung Galaxy S4LG Optimus手机上进行了测试。但是,在appthwack.com上进行测试时结果为{{3}这是我的Camera.open代码无效:

    try{   
         Camera.open();
       }
       catch(Exception ex)
       {
          Log.e(TAG,"Could not open camera",ex);//running on HTC prints could not open camera
       }
   mPreview=new CameraPreview(this,mCamera);//this is which the NullPointerException is thrown     

上面的代码在Activity的onResume中调用,这意味着只有当用户看到屏幕时才使用Camera对象,我会在onPause()中释放Camera,如下所示:

    sensorManager.unregisterListener(this);
    isPreviewShowing=false;
    if(mCamera!=null)
    killCamera();
    container.removeAllViews();

     private void killCamera()
{
    if(mCamera!=null)
    {
        mCamera.cancelAutoFocus();
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
        mCamera=null;
    }
}

我已将打开相机的代码更改为:

 Camera.CameraInfo info=new Camera.CameraInfo();
    int cameraCount=mCamera.getNumberOfCameras();
    int cameraIndex=0;
    for(cameraIndex=0;cameraIndex<cameraCount;cameraIndex++)
    {
        Camera.getCameraInfo(cameraIndex, info);
        if(info.facing==CameraInfo.CAMERA_FACING_BACK)
        {
            try
            {
                mCamera=Camera.open(cameraIndex);
            }
            catch(Exception ex)
            {
                Log.e(TAG, "Could not open camera",ex);
            }
        }
    }

这也不起作用,我还尝试将以下代码添加到CameraPreview类中:

 @SuppressWarnings("deprecation")
public CameraPreview(Context context,Camera camera) {
    super(context);
    this.ctx=context;
    mCamera=camera;
    mHolder=this.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

    @Override
public void surfaceCreated(SurfaceHolder holder) {
    if(mCamera==null)
    {
        mCamera=null;
        Camera.CameraInfo info=new Camera.CameraInfo();
        int cameraCount=mCamera.getNumberOfCameras();
        int cameraIndex=0;
        for(cameraIndex=0;cameraIndex<cameraCount;cameraIndex++)
        {
            Camera.getCameraInfo(cameraIndex, info);
            if(info.facing==CameraInfo.CAMERA_FACING_BACK)
            {
                try
                {
                    mCamera=Camera.open(cameraIndex);
                }
                catch(Exception ex)
                {
                    Log.e(TAG, "Could not open camera",ex);
                }
            }
        }

    }
    try
    {
        if(mCamera==null)
        {
            Log.d(TAG,"Camera is null here but why???");
        }
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    }
    catch(IOException e)
    {
        Log.e("CameraPreview","Error getting camera preview",e);
    }
}

这也不起作用。另外,对于任何问我权限的人,我已将所有必需的权限声明为:

  <uses-permission android:name="android.permission.CAMERA" />


<uses-feature android:name="android.hardware.camera"
    android:required="true"
     />
<uses-feature android:name="android.hardware.camera.autofocus"
              android:required="true"
     />
<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true"
    />

开始使用全新的相机会有点困难,我想(如果可能的话)保持相机的现有结构完好无损,那么请你帮我解决这个问题。整个logcat文件随上面公布的测试结果一起提供。

编辑:

通过surfaceCreated使用全局SurfaceHolder对象而不是持有者提供者上的持有者解决了HTC Desire HD上的问题,而不是HTC One S.It会在此处引发错误:

 java.lang.NullPointerException at 
 com.blutechnologies.scancard.CameraPreview.surfaceCreated(CameraPreview.java:95) at   
 android.view.SurfaceView.updateWindow(SurfaceView.java:543) at 
 android.view.SurfaceView.access$000(SurfaceView.java:81) at 
 android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169) at 
 android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590) at 
 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1793) at 
 android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2700) at 
 android.os.Handler.dispatchMessage(Handler.java:99) at 
 android.os.Looper.loop(Looper.java:156) at 
 android.app.ActivityThread.main(ActivityThread.java:5045) at 
 java.lang.reflect.Method.invokeNative(Native Method) at 
 java.lang.reflect.Method.invoke(Method.java:511) at 
 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at 
 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at 
 dalvik.system.NativeStart.main(Native Method)

这之前是:

 I  ActivityManager START {cmp=com.blutechnologies.scancard/.CameraActivity} from pid 21085
 I  QualcommCamera  Qint android::get_camera_info(int, camera_info*): E
 V  QCameraHAL  void android::HAL_getCameraInfo(int, android::CameraInfo*): E
 V  QCameraHAL  void android::HAL_getCameraInfo(int, android::CameraInfo*): X

我想这意味着相机正在忙碌,即它正在其他地方使用,是因为之前设备发生了崩溃,如果我将相机关闭代码放在surfaceDestroyed中,它是否会自行纠正,这样做似乎非常危险,我将此代码添加到我的surfaceDestroyed:

  private void killCamera()
{
    if(mCamera!=null)
    {
        mCamera.cancelAutoFocus();
        mCamera.release();
        mCamera=null;
    }
}

相机现在是空白的,根本没有显示预览,它在设置预览尺寸时卡住了。必须有一些我没做的事情可以解决这个错误。

2 个答案:

答案 0 :(得分:2)

这是如何获取相机的示例:

 private Camera getCameraInstance() {
        int cameraCount = 0;
        Camera cam = null;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();
        for ( int camIdx = 0; camIdx < cameraCount; camIdx++ ) {
            Camera.getCameraInfo( camIdx, cameraInfo );
            if ( cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK  ) {
                try {
                    cam = Camera.open( camIdx );
                } catch (RuntimeException e) {
                    Log.e("Camera", "Camera failed to open: " + e.getLocalizedMessage());
                }
            }
        }

        return cam;
    }

并检查清单中的权限

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

答案 1 :(得分:0)

我不知道究竟是什么问题,但是您在surfaceCreated上编写代码,但我还有其他一些技巧。

Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;

**OnCreate** 
...
...

getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

<强> OnPreviewStart()

OnPreviewStart() {
    if (!previewing) {
        camera = Camera.open();
        if (camera != null) {
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

<强> onPreviewStop()

onPreviewStop() {
               if (camera != null && previewing) {
                   camera.stopPreview();
                   camera.release();
                   camera = null;

                   previewing = false;
               }
       }

您可以在任何您想要使用的地方调用以上两个功能,以显示&amp;表面上的相机预览。

下一件事implements SurfaceHolder.Callback

那将@Override三种方法表面很少像

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}
public void surfaceCreated(SurfaceHolder holder){}
public void surfaceDestroyed(SurfaceHolder holder){}

Check for more detail.