Search code examples
androidcamerapreview

Android camera can't preview, can take photo


I'm displaying a camera preview to an user using surface view. Here's my method for starting it:

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

When user clicks a buton:

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

This code works well on Sony Xperia(2 cameras), but preview fails on HTC Wildfire and Samsung Galaxy S+(both 1 cam). No exception beeing throw, it just displays nothing. I am able to take pictures on all of those devices.

LogCat output for pickCamMethod is empty for both devices:

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

How can i make it work in all cases?


Solution

  • Add permission's in the manifest file

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

    The develoepr site has excellent documentation on the topic.

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

    I used the code on the developer site and made a sample. Modify the below according to your needs.

    In your activity

    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 class for preview

    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>