65
votes

I am building an application where I want to capture an image by the default camera activity and return back to my activity and load that image in a ImageView. The problem is camera activity always returning null. In my onActivityResult(int requestCode, int resultCode, Intent data) method I am getting data as null. Here is my code:

public class CameraCapture extends Activity {

    protected boolean _taken = true;
    File sdImageMainDirectory;
    Uri outputFileUri;

    protected static final String PHOTO_TAKEN = "photo_taken";
    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        try {

            super.onCreate(savedInstanceState);   
            setContentView(R.layout.cameracapturedimage);
                    File root = new File(Environment
                            .getExternalStorageDirectory()
                            + File.separator + "myDir" + File.separator);
                    root.mkdirs();
                    sdImageMainDirectory = new File(root, "myPicName");



                startCameraActivity();

        } catch (Exception e) {
            finish();
            Toast.makeText(this, "Error occured. Please try again later.",
                    Toast.LENGTH_SHORT).show();
        }

    }

    protected void startCameraActivity() {

        outputFileUri = Uri.fromFile(sdImageMainDirectory);

        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        switch (requestCode) {
        case CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE:
        {
            if(resultCode==Activity.RESULT_OK)
            {
                try{
                ImageView imageView=(ImageView)findViewById(R.id.cameraImage);
                imageView.setImageBitmap((Bitmap) data.getExtras().get("data"));
                }
                catch (Exception e) {
                    // TODO: handle exception
                }
            }

            break;
        }

        default:
            break;
        }
    }

     @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState.getBoolean(CameraCapture.PHOTO_TAKEN)) {
            _taken = true;
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBoolean(CameraCapture.PHOTO_TAKEN, _taken);
    }
}

Am I doing anything wrong?

11
is the sdcard mounted? where u able to see the image 'myPicName'? and do u have the permissions in the manifest? <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />Jana
I can see the file in the ddms while usb debugging. And i also have given the permission. If i use outputFileUri instead of data when loading the image in the imageview it works. That means camera is capturing the image but why i am getting null in the data parameter of onactivityresult() methodrawcoder064
Pay attention if you have allowed the permission to access your Storage.yalematta

11 Answers

114
votes

You are getting wrong because you are doing it wrong way.

If you pass the extra parameter MediaStore.EXTRA_OUTPUT with the camera intent then camera activity will write the captured image to that path and it will not return the bitmap in the onActivityResult method.

If you will check the path which you are passing then you will know that actually camera had write the captured file in that path.

For further information you can follow this, this and this

18
votes

I am doing it another way. The data.getData() field is not guaranteed to return a Uri, so I am checking if it's null or not, if it is then the image is in extras. So the code would be -

if(data.getData()==null){
    bitmap = (Bitmap)data.getExtras().get("data");
}else{
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
}

I am using this code in the production application, and it's working.

5
votes

I had a similar problem. I had commented out some lines in my manifest file which caused the thumbnail data to be returned as null.

You require the following to get this to work:

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

I hope this resolves your issue

If you phone is a Samsung, it could be related to this http://kevinpotgieter.wordpress.com/2011/03/30/null-intent-passed-back-on-samsung-galaxy-tab/

There is another open question which may give additional information

4
votes

If you are using an ImageView to display the Bitmap returned by Camera Intent you need to save the imageview reference inside onSaveInstanceState and also restore it later on inside onRestoreInstanceState. Check out the code for onSaveInstanceState and onRestoreInstanceState below.

public class MainActivity extends Activity {

    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1;
    String mCurrentPhotoPath;
    ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageView = (ImageView) findViewById(R.id.imageView1);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void startCamera(View v) throws IOException {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File photoFile = null;

        photoFile = createImageFile();
        //intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photoFile));
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
        }

    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE
                && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap imageBitmap = (Bitmap) extras.get("data");
            System.out.println(imageBitmap);
            imageView.setImageBitmap(imageBitmap);
        }
    }

    private File createImageFile() throws IOException {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = Environment
                .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(imageFileName, /* prefix */
                ".jpg", /* suffix */
                storageDir /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        System.out.println(mCurrentPhotoPath);
        return image;
    }

    private void setPic() {
        // Get the dimensions of the View
        int targetW = imageView.getWidth();
        int targetH = imageView.getHeight();

        // Get the dimensions of the bitmap
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        // Determine how much to scale down the image
        int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

        // Decode the image file into a Bitmap sized to fill the View
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        imageView.setImageBitmap(bitmap);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);
        System.out.println(mCurrentPhotoPath);
        imageView = (ImageView) findViewById(R.id.imageView1);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onRestoreInstanceState(savedInstanceState);
        System.out.println(mCurrentPhotoPath);
        imageView = (ImageView) findViewById(R.id.imageView1);
    }
}
2
votes

after many search :

private static final int TAKE_PHOTO_REQUEST = 1;
private ImageView mImageView;
String mCurrentPhotoPath;
private File photoFile;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_saisir_frais);
    mImageView = (ImageView) findViewById(R.id.imageViewPhoto);
    dispatchTakePictureIntent();
}





@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == TAKE_PHOTO_REQUEST && resultCode == RESULT_OK) {

            // set the dimensions of the image
            int targetW =100;
            int targetH = 100;

            // Get the dimensions of the bitmap
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions);
            int photoW = bmOptions.outWidth;
            int photoH = bmOptions.outHeight;

            // Determine how much to scale down the image
            int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

            // Decode the image file into a Bitmap sized to fill the View
            bmOptions.inJustDecodeBounds = false;
            bmOptions.inSampleSize = scaleFactor;
            bmOptions.inPurgeable = true;

           // stream = getContentResolver().openInputStream(data.getData());
            Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath(),bmOptions);
            mImageView.setImageBitmap(bitmap);
    }

}


private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;
}


private void dispatchTakePictureIntent() {

    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        photoFile = createImageFile();
        takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
1
votes

Try following code

            {
                final String[] imageColumns = { MediaStore.Images.Media._ID,MediaStore.Images.Media.DATA };

                final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
                Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
                imageCursor.moveToFirst();
                do {
                    String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
                    if (fullPath.contains("DCIM")) {

                        //get bitmap from fullpath here.
                        return;
                    }
                }
                while (imageCursor.moveToNext());
0
votes

You can generate bitmap from the file that you send to camera intent. Please use this code...

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data){
    switch (requestCode) {

    case CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE:
     {
        if(resultCode==Activity.RESULT_OK)
           {

                int orientation = getOrientationFromExif(sdImageMainDirectory);// get orientation that image taken

                BitmapFactory.Options options = new BitmapFactory.Options();

                InputStream is = null;
                Matrix m = new Matrix();
                m.postRotate(orientation);//rotate image

                is = new FileInputStream(sdImageMainDirectory);

                options.inSampleSize = 4 //(original_image_size/4);
                Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                        bitmap.getHeight(), m, true);

                 // set bitmap to image view    

                 //bitmap.recycle();    
           }

        break;
    }

    default:
        break;
    }

}

private int getOrientationFromExif(String imagePath) {
        int orientation = -1;
        try {
            ExifInterface exif = new ExifInterface(imagePath);
            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 
                    ExifInterface.ORIENTATION_NORMAL);

            switch (exifOrientation) {
                case ExifInterface.ORIENTATION_ROTATE_270:
                    orientation = 270;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    orientation = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    orientation = 90;
                    break;
                case ExifInterface.ORIENTATION_NORMAL:
                    orientation = 0;
                    break;
                default:
                    break;
            }
        } catch (IOException e) {
            //Log.e(LOG_TAG, "Unable to get image exif orientation", e);
        }
        return orientation;
    }
0
votes
File cameraFile = null;

public void openChooser() {
    Intent pickIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    cameraFile = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
    takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));

    String pickTitle = "Select or take a new Picture"; // Or get from strings.xml
    Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,new Intent[]{takePhotoIntent});
    startActivityForResult(chooserIntent, SELECT_PHOTO);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case SELECT_PHOTO:
            if (resultCode == Activity.RESULT_OK) {
                Uri selectedImage = data.getData();
                if (selectedImage != null) {
                    //from gallery 
                } else if (cameraFile != null) {
                    //from camera
                    Uri cameraPictureUri = Uri.fromFile(cameraFile);
                }
            }
            break;
    }
}
0
votes

Try this tutorial. It works for me and use permission as usual in manifesto & also check permission

https://androidkennel.org/android-camera-access-tutorial/

0
votes

After a lot of vigorous research I finally reached to a conclusion. For doing this, you should save the image captured to the external storage. And then,retrieve while uploading. This way the image res doesnt degrade and you dont get NullPointerException too! I have used timestamp to name the file so we get a unique filename everytime.

 private void fileChooser2() {
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
    Intent intent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    String pictureName=getPictureName();
    fi=pictureName;
    File imageFile=new File(pictureDirectory,pictureName);
    Uri pictureUri = Uri.fromFile(imageFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT,pictureUri);
    startActivityForResult(intent,PICK_IMAGE_REQUEST2);
}

Function to create a file name :

private String getPictureName() {
    SimpleDateFormat adf=new SimpleDateFormat("yyyyMMdd_HHmmss");
    String timestamp = adf.format(new Date());
    return "The New image"+timestamp+".jpg";//give a unique string so that the imagename cant be overlapped with other apps'image formats
}

and the onActivityResult:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
         
        if(requestCode==PICK_IMAGE_REQUEST2 && resultCode==RESULT_OK )//&& data!=null && data.getData()!=null)
        {
            final ProgressDialog progressDialog = new ProgressDialog(this);
            progressDialog.setTitle("Uploading");
            progressDialog.show();
            Toast.makeText(getApplicationContext(),"2",Toast.LENGTH_SHORT).show();
                File picDir=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File imageFile=new File(picDir.getAbsoluteFile(),fi);
            filePath=Uri.fromFile(imageFile);
            try {
            }catch (Exception e)
            {
                e.printStackTrace();
            }



            StorageReference riversRef = storageReference.child(mAuth.getCurrentUser().getUid()+"/2");
            riversRef.putFile(filePath)
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            progressDialog.dismiss();
                            Toast.makeText(getApplicationContext(), "File Uploaded ", Toast.LENGTH_LONG).show();
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception exception) {
                            progressDialog.dismiss();
                            Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    })
                    .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                            double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                            progressDialog.setMessage("Uploaded " + ((int) progress) + "%...");
                        }
                    });

Edit: give permissions for camera and to write and read from storage in your manifest.

0
votes

While taking from camera few mobiles would return null. The below workaround will solve. Make sure to check data is null:

          private int  CAMERA_NEW = 2;
          private String imgPath;

          private void takePhotoFromCamera() {
               Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
               intent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri());
               startActivityForResult(intent, CAMERA_NEW);
          }

         // to get the file path 
         private  Uri setImageUri() {
           // Store image in dcim
              File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/", "image" + new Date().getTime() + ".png");
              Uri imgUri = Uri.fromFile(file);
              this.imgPath = file.getAbsolutePath();
              return imgUri;
           }
          
          @Override
          public void onActivityResult(int requestCode, int resultCode, Intent data) 
          {
                 super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == CAMERA_NEW) {

              try {
                 Log.i("Crash","CAMERA_NEW");
                 if(data!=null &&(Bitmap) data.getExtras().get("data")!=null){
                     bitmap = (Bitmap) data.getExtras().get("data");
                     personImage.setImageBitmap(bitmap);
                     Utils.saveImage(bitmap, getActivity());
                               
                 }else{
                       File f= new File(imgPath);
                       BitmapFactory.Options options = new BitmapFactory.Options();
                       options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                       options.inSampleSize= 4;
                       bitmap = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
                       personImage.setImageBitmap(bitmap);
                              
                    }
                } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(getActivity(), "Failed!", Toast.LENGTH_SHORT).show();
             }
      }