2

I'm using the below class to take a picture in Android, and I want to take the picture using front camera. I have added the required permissions to the manifest file:

public class CameraController extends AsyncTask{

    final Context context;

    private boolean hasCamera;

    private Camera camera;
    private int cameraId;

    public CameraController(Context c){
        context = c.getApplicationContext();

        if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            cameraId = getFrontCameraId();

            if(cameraId != -1){
                hasCamera = true;
            }else{
                hasCamera = false;
            }
        }else{
            hasCamera = false;
        }
    }


    public void getCameraInstance(){
        camera = null;

        if(hasCamera){
            try{
                camera = Camera.open(cameraId);
                prepareCamera();
            }
            catch(Exception e){
                hasCamera = false;
            }
        }
    }

    public void takePicture(){
        if(hasCamera){
            camera.takePicture(null,null,mPicture);
        }
    }

    public void releaseCamera(){
        if(camera != null){
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }

    private int getFrontCameraId(){
        int camId = -1;
        int numberOfCameras = Camera.getNumberOfCameras();
        CameraInfo ci = new CameraInfo();

        for(int i = 0;i < numberOfCameras;i++){
            Camera.getCameraInfo(i,ci);
            if(ci.facing == CameraInfo.CAMERA_FACING_FRONT){
                camId = i;
            }
        }

        return camId;
    }

    private void prepareCamera(){
        SurfaceView view = new SurfaceView(context);

        try{
            camera.setPreviewDisplay(view.getHolder());
        }catch(IOException e){
            throw new RuntimeException(e);
        }

        camera.startPreview();

        Camera.Parameters params = camera.getParameters();
        params.setJpegQuality(100);

        camera.setParameters(params);
    }

    private Camera.PictureCallback mPicture = new Camera.PictureCallback(){
        @Override
        public void onPictureTaken(byte[] data, Camera camera){
            File pictureFile = getOutputMediaFile();

            if(pictureFile == null){
                Log.d("TEST", "Error creating media file, check storage permissions");
                return;
            }

            try{
                Log.d("TEST","File created");
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            }catch(FileNotFoundException e){
                Log.d("TEST","File not found: "+e.getMessage());
            } catch (IOException e){
                Log.d("TEST","Error accessing file: "+e.getMessage());
            }
        }
    };

    private File getOutputMediaFile(){

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp");

        if(!mediaStorageDir.exists()){
            if(!mediaStorageDir.mkdirs()){
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

        File mediaFile;
        mediaFile = new File(mediaStorageDir.getPath()+File.separator+"IMG_"+timeStamp+".jpg");

        return mediaFile;
    }

    @Override
    protected Object doInBackground(Object[] params) {
        try{

            takePicture();
            return "1";
        }catch(Exception e){
            return "-1";
        }
    }
    @Override
    protected void onPostExecute(Object o) {
        super.onPostExecute(o);
        releaseCamera();

    }
}

and call it in my mainActivity same this:

   public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        context = this;
        CameraController cc = new CameraController(context);
        cc.getCameraInstance();
        cc.execute();
}

The above code is not working and is not taking any picture. I did debug the code and noticed that the onPictureTaken not called.

itoctopus
  • 4,133
  • 4
  • 32
  • 44
  • Maybe this will help you http://stackoverflow.com/questions/6200369/picturecallback-onpicturetaken-never-called – mariuss Oct 27 '15 at 11:50
  • On the face of it, you call `camera.takePicture()` too early. The constraint is that you are allowed to do so only after the preview actually starts (this means that for some devices, we must wait for up to 300ms after we call to `startPreview()`). – Alex Cohn Oct 27 '15 at 14:47

1 Answers1

0

try this code: this is the mainactivity

public class AndroidCameraExample extends Activity implements SensorEventListener,FaceDetectionListener{
    private Camera mCamera;
    private CameraPreview mPreview;
    private PictureCallback mPicture;
    private Button capture, switchCamera;
    private Context myContext;
    private LinearLayout cameraPreview;
    private boolean cameraFront = false,hasaccel,changed=false;
    SensorManager sm;
    List<Sensor> s;
    Sensor sensor;
    String photopath;
    int ax=100,ay;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        WindowManager.LayoutParams layout = getWindow().getAttributes();
        layout.screenBrightness = 1F;
        getWindow().setAttributes(layout);
        myContext = this;
        initialize();
        hasaccel = checkaccelerometer();

    }

    private int findFrontFacingCamera() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                cameraId = i;
                cameraFront = true;
                break;
            }
        }
        return cameraId;
    }

    private int findBackFacingCamera() {
        int cameraId = -1;
        //Search for the back facing camera
        //get the number of cameras
        int numberOfCameras = Camera.getNumberOfCameras();
        //for every camera check
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                cameraId = i;
                cameraFront = false;
                break;
            }
        }
        return cameraId;
    }

    public void onResume() {
        super.onResume();
        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
            toast.show();
            finish();
        }
        if (mCamera == null) {
            //if the front facing camera does not exist
            if (findFrontFacingCamera() < 0) {
                Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
                switchCamera.setVisibility(View.GONE);
            }       
            int cameraId = findFrontFacingCamera();
            //Mayur
            mCamera = Camera.open((cameraId));

        //  mCamera.setFaceDetectionListener(this);
        //  mCamera.startFaceDetection();
            setCameraDisplayOrientation(this, cameraId, mCamera);
            mPicture = getPictureCallback();
            mPreview.refreshCamera(mCamera);
        }
    }

    public void initialize() {
        cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
        mPreview = new CameraPreview(myContext, mCamera);
        cameraPreview.addView(mPreview);

        capture = (Button) findViewById(R.id.button_capture);
        capture.setOnClickListener(captrureListener);

        switchCamera = (Button) findViewById(R.id.button_ChangeCamera);
        switchCamera.setOnClickListener(switchCameraListener);
    }

    OnClickListener switchCameraListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            //get the number of cameras
            int camerasNumber = Camera.getNumberOfCameras();
            if (camerasNumber > 1) {
                //release the old camera instance
                //switch camera, from the front and the back and vice versa

                releaseCamera();
                chooseCamera();
            } else {
                Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
                toast.show();
            }
        }
    };

    public void chooseCamera() {
        //if the camera preview is the front
        if (cameraFront) {
            int cameraId = findBackFacingCamera();
            if (cameraId >= 0) {
                //open the backFacingCamera
                //set a picture callback
                //refresh the preview

                mCamera = Camera.open(cameraId);                
                mPicture = getPictureCallback();            
                mPreview.refreshCamera(mCamera);
            }
        } else {
            int cameraId = findFrontFacingCamera();
            if (cameraId >= 0) {
                //open the backFacingCamera
                //set a picture callback
                //refresh the preview

                mCamera = Camera.open(cameraId);
                mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        //when on Pause, release camera in order to be used from other applications
        releaseCamera();
    }

    private boolean hasCamera(Context context) {
        //check if the device has camera
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            return true;
        } else {
            return false;
        }
    }

    private PictureCallback getPictureCallback() {
        PictureCallback picture = new PictureCallback() {

            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                //make a new picture file
                File pictureFile = getOutputMediaFile();
                // Location of stored image
                Log.d("Mayur", "Picture: "+pictureFile);
                Log.d("Mayur","Data: "+data);
                if (pictureFile == null) {
                    return;
                }
                try {
                    //check orientation and rotate if necessary

                    //write the file
                    while(!changed)
                    {
                    Log.d("Parth", "X: "+ax);
                    }
                    int rotate=-90;
                /*  if((ax<=5 && ax>=-1) && (ay>=6 && ay<=9))
                    {
                        rotate=-90;
                    }
                    else if((ax<=9 && ax>=6) && (ay>=-1 && ay<=5))
                    {
                        rotate=-90;
                    }
                    else if((ax<=-6 && ax>=-9) && (ay>=-1 && ay<=5))
                    {
                        rotate = -180;
                    }
                    else if((ax<=5 && ax>=-1) && (ay>=-9 && ay<=-6))
                    {
                        rotate = 90;
                    }
                    */
                    Log.d("Parth", "X: "+ax+" Y:"+ay);
                    Matrix matrix = new Matrix();
                    if(android.os.Build.VERSION.SDK_INT>13 )
                    {
                        float[] mirrorY = { -1, 0, 0, 0, 1, 0, 0, 0, 1};
                        Matrix matrixMirrorY = new Matrix();
                        matrixMirrorY.setValues(mirrorY);

                        matrix.postConcat(matrixMirrorY);

                        matrix.preRotate(rotate);

                    }

                    Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                    int i = ExifInterface.ORIENTATION_FLIP_HORIZONTAL;
                    bmp = Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true);
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    bmp.compress(Bitmap.CompressFormat.JPEG, 85, fos);
                    photopath = pictureFile.getAbsolutePath();
                    fos.flush();
                    fos.close();
                    bmp.recycle();
                    //Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
                    //toast.show();
                    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(pictureFile)));
                    Intent intent = new Intent(myContext, LayoutTest1Activity.class);
                    intent.putExtra("path", photopath);
                    startActivity(intent);
                    finish();

                } catch (FileNotFoundException e) {
                } catch (IOException e) {
                }

                //refresh camera to continue preview
                mPreview.refreshCamera(mCamera);
            }
        };
        return picture;
    }

    protected void checkorientation() {
        // TODO Auto-generated method stub
        sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sm.registerListener(this, sensor,SensorManager.SENSOR_DELAY_FASTEST);

    }

    OnClickListener captrureListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            //Mayur
            checkorientation();
            Camera.Parameters params=mCamera.getParameters();
            List<Size> sizes =params.getSupportedPictureSizes();
            Size mSize=null;
            int temp=0;
//          for(Size size:sizes)
//          {
//              mSize=size;
//              Log.d("Mayur", "H: "+mSize.height+" W: "+mSize.width);
//          }

            mSize=sizes.get(0); //taking largest resolution

            Log.d("Mayur", "Loaded with  H: "+mSize.height+"W: "+mSize.width);
            params.setPictureSize(mSize.width, mSize.height);
            mCamera.setParameters(params);

            //
            mCamera.takePicture(null, null, mPicture);

        }


    };
    private boolean checkaccelerometer() {
        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        s = new ArrayList<Sensor>();
        s = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if(s.size()>0)
        {
            Toast.makeText(myContext, "has accelerometer", Toast.LENGTH_SHORT).show();
            return true;
        }
        return false;
        // TODO Auto-generated method stub
    }
    //make picture and save to a folder
    private static File getOutputMediaFile() {
        //make a new file directory inside the "sdcard" folder
        File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Creaa");
        mediaStorageDir.mkdirs();
        //if this "Creaa Camera folder does not exist
        if (!mediaStorageDir.exists()) {
            //if you cannot make this folder return
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }

        //take the current timeStamp
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        //and make a media file:
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + "mypic_" + timeStamp + ".jpg");
        return mediaFile;
    }

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        ax = (int) event.values[0];
        ay  = (int) event.values[1];
        sm.unregisterListener(this);
        Toast.makeText(myContext, "X : "+ax+" Y: "+ay, Toast.LENGTH_SHORT).show();
        changed=true;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    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;
         }
         Log.d("Parth", "Result : "+result);
         camera.setDisplayOrientation(result);
     }

    @Override
    public void onFaceDetection(Face[] faces, Camera camera) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "facedeteted", Toast.LENGTH_SHORT).show();
        if(faces.length>0)
        Log.d("Parth", "mouth:"+faces[0].mouth.x+"\nrect :"+faces[0].rect.bottom);
    }


}

and the 2nd class:this is for camera preview as you need surfaceview for front camera unlikle back camera which we start from intent.

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

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        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) {
        try {
            // create the surface and start camera preview
            if (mCamera == null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException e) {
            Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void refreshCamera(Camera camera) {
        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
        setCamera(camera);
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

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

    public void setCamera(Camera camera) {
        //method to set a camera instance
        mCamera = camera;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // mCamera.release();

    }
}

this code is used fro directly starting the front camera. use both the classes above

Parth Anjaria
  • 3,961
  • 3
  • 30
  • 62