5

I would like to ask the user to take a picture, either from camera or from the existing pictures in the device (gallery or whatever). How can I do that?

I have implemented the solution below, which seems to work fine, but the documentation is quite confusing so I would like to know if there are better solutions.

Also, check out this related post. There you will see how to get the image path or Bitmap: Get/pick an image from Android's built-in Gallery app programmatically

So, in my solution you would create a TakePictureHelper object and do the following.

Let's say you display a dialog where the user can choose "camera" or "other". When the user chooses an option you would call either takeFromCamera() or takeFromOther(). When the picture is taken (or not) the onActivityResult() method will be called. There you would call retrievePicture, which will return the Uri of the picture or null if no picture was taken.

Please let me know what you think, share ideas or ask me anything if I wasn't clear.

Thank you very much!

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TakePictureHelper {

    public final static int REQUEST_CAMERA = 1;
    public final static int REQUEST_OTHER = 2;

    private Uri cameraImageUri;

    /**
     * Request picture from camera using the given title
     */
    public void takeFromCamera(Activity activity, String title)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File cameraImageOutputFile = new File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                createCameraImageFileName());
        cameraImageUri = Uri.fromFile(cameraImageOutputFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri);
        activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_CAMERA);
    }

    /**
     * Request picture from any app (gallery or whatever) using the given title
     */
    public void takeFromOther(Activity activity, String title)
    {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_OTHER);
    }

    /**
     * Retrieve the picture, taken from camera or gallery.
     *
     * @return the picture Uri, or null if no picture was taken.
     */
    public Uri retrievePicture(Activity activity, int requestCode, int resultCode, Intent data)
    {
        Uri result = null;

        if (resultCode == Activity.RESULT_OK) {

            if (requestCode == REQUEST_OTHER) {
                result = data.getData();
            } else if (requestCode == REQUEST_CAMERA) {
                result = cameraImageUri;
            }
        }

        return result;
    }

    private String createCameraImageFileName() {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        return timeStamp + ".jpg";
    }
}
Community
  • 1
  • 1
Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100

4 Answers4

5

based on @yurezcv's answer, here's what I came up with (Most importantly how to retrieve image in onActivityResult):

private List<File> cameraImageFiles;

private void popImageChooser(){
    // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);

    cameraImageFiles = new ArrayList<File>();

    int i=0;
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia");

        File cameraImageOutputFile = new File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                createCameraImageFileName());
        cameraImageFiles.add(cameraImageOutputFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraImageFiles.get(i)));
        i++;

        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.attach_images_title));

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
    startActivityForResult(chooserIntent, ACTIVITY_REQUEST_CODE_IMAGE);
}


protected void onActivityResult(int requestCode, int resultCode, 
           Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case ACTIVITY_REQUEST_CODE_IMAGE:
        if(resultCode == RESULT_OK){

            Uri uri = null;
            if(imageReturnedIntent == null){   //since we used EXTRA_OUTPUT for camera, so it will be null

                for(int i=0;i<cameraImageFiles.size();i++){
                    if(cameraImageFiles.get(i).exists()){
                        uri = Uri.fromFile(cameraImageFiles.get(i));
                        break;
                    }
                }
                Log.d("attachimage", "from camera: "+uri);
            }
            else {  // from gallery
                uri = imageReturnedIntent.getData();
                Log.d("attachimage", "from gallery: "+uri.toString());
            }

            if(uri != null){
                attachImage(uri);
            }
        }
    }
}
OatsMantou
  • 193
  • 3
  • 7
3

This solution works for me:

private void addPhoto() {   
       // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);     
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia");

        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.add_new));

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
    startActivityForResult(chooserIntent, YOUR_REQUEST_CODE);
}

It creates one intent dialog with all possible variants for select image from camera, filesystem, etc.

yurezcv
  • 1,033
  • 12
  • 19
1
  1. Create in your layout a button (by clicking on this button will open a dialog where you can choose whether to choose the camera or galleria).

  2. Now initializes the button in its class:

    - Before onCreate:

    Button btu;

    - Inside onCreate:

    btu = (Button) findViewById(R.id.BtUp);

  3. Methods call camera and gallery

- Before onCreate boot

int CAMERA_REQUEST = 1;

- Method Call camera

public void callCamera() {
    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.putExtra("crop", "true");
    cameraIntent.putExtra("aspectX", 0);
    cameraIntent.putExtra("aspectY", 0);
    cameraIntent.putExtra("outputX", 200);
    cameraIntent.putExtra("outputY", 150);
    startActivityForResult(cameraIntent, CAMERA_REQUEST);
}

- Method Call gallery

public void callGallery() {
    Intent intent = new Intent(Intent.ACTION_PICK,
                               MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent,0);
}
  1. Create a method to show the AlertDialog, which appear to choose:

    public void showAlertDialog(Context context) {
    this.context = context;
    final String items[] = {getString(R.string.TextTakeCam), getString(R.string.TextTakeGal)};
    
    AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this);
    ab.setTitle(getString(R.string.TextTitleDia));
    AlertDialog.Builder builder = ab.setItems(items, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface d, int choice) {
            if (choice == 0) {
                callCamera();
            } else if (choice == 1) {
                image.setVisibility(View.INVISIBLE);
                callGallery();
            }
        }});
    ab.show();
    

    }

  2. Call AlertDialog in button

    btu.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String title = getString(R.string.TextUp);
        String msg = getString(R.string.TextUp2);
        showAlertDialog2(MainActivity.this,title,msg,true);
        //maneger.UpdateC(edname.getText().toString(),edfoto.getText().toString(),ednum. getText().toString());
        }
    });
    

Inside AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Sergei Bubenshchikov
  • 5,275
  • 3
  • 33
  • 60
1

I found a better and easy way to take picture from camera or gallery i.e. using this library https://android-arsenal.com/details/1/3623

You can follow the link above or follow these steps:

Steps to use this library in your project are:

  1. Add dependency to Gradle:

    compile 'com.frosquivel:magicalcamera:4.4'

  2. Implementation Code:

    PermissionGranted permissionGranted = new PermissionGranted(this); MagicalCamera magicalCamera = new MagicalCamera(this, permissionGranted); //The parameter this, is the current activity //permission for take photo, it is false if the user check deny permissionGranted.checkCameraPermission(); //for search and write photoss in device internal memory //normal or SD memory permissionGranted.checkReadExternalPermission(); permissionGranted.checkWriteExternalPermission();

  3. Call to Take Photo From Camera:

    magicalCamera.takePhoto();

  4. Call to Select Photo From Gallery:

    magicalCamera.selectedPicture("my_header_name");

  5. Override OnActivityResult(); method to get Bitmap and Path:

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    magicalCamera.resultPhoto(requestCode, resultCode, data);//with this form you obtain the bitmap
    Bitmap bitmap = magicalCamera.getPhoto();
    imageView.setImageBitmap(bitmap);
    //if you need path of bitmap use this code
    String path = magicalCamera.savePhotoInMemoryDevice(magicalCamera.getPhoto(),"myPhotoName","myDirectoryName", MagicalCamera.JPEG, true);
    

    if(path != null){ Toast.makeText(MainActivity.this, "The photo is save in device, please check this path: " + path, Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(MainActivity.this, "Sorry your photo dont write in devide, please contact with fabian7593@gmail and say this error", Toast.LENGTH_SHORT).show(); } }

For more details refer to the link above

Rahul Sharma
  • 5,949
  • 5
  • 36
  • 46