Camera does not open on HTC devices

1k Views Asked by At

I have built a Camera based on the code example presented here and have enhanced it with the Camera.java and ShutterButton.java from AOSP GingerBread,the code I took away was mostly for the autofocus and for the ShutterButton.The Camera has been tested on Samsung Galaxy Nexus and the Samsung Galaxy S4 and the LG Optimus Phone running 4.0.x and it works.However,upon testing at appthwack.com the results are here.This was my Camera.open code which was not working:

    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     

The above code is called in the Activity's onResume which means that the Camera object is only in use when the screen is visible to the user,I release the Camera in onPause() like this:

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

I have changed the code for opening the camera to:

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

This did not work either,I have also tried adding the following code to the CameraPreview class that has:

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

This did not work either.Also,for anyone asking me about permissions,I have declared all the requisite permissions as:

  <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"
    />

It would be a little difficult to get started working on a brand new Camera,I would like to(if possible) keep the existing structure of the Camera intact,so could you please help me sort this issue out.The entire logcat file is available along with the test results posted above.

EDIT:

Using the global SurfaceHolder Object instead of the holder on holder provider by surfaceCreated solves the issue on HTC Desire HD but not on HTC One S.It throws the error here:

 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)

This is preceeded by:

 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

I guess it means that the Camera is busy,that is it is being used elsewhere,is it due to a previous crash on the device,would it rectify itself if I put the camera closing code in surfaceDestroyed,doing that seems extremely dangerous,I added this code to my surfaceDestroyed:

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

The Camera is now blank and does not show a preview at all,it gets stuck at setting the Preview Size.There must be some thing I am not doing that can solve this error.

2

There are 2 best solutions below

2
On

This is example how to get camera:

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

And also check the permissions in manifest

   <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" />
4
On

I don't know what is the exact issue , but you are writing your code on surfaceCreated but i have some other technique.

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

You can call above two function wherever you want to use , to show & Preview of camera on surface.

Next thing implements SurfaceHolder.Callback

That will @Override three method for surface few like

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.