jjLin
jjLin

Reputation: 3291

Android How can I call Camera or Gallery Intent Together

If I want to capture image from native camera, I can do:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
        startActivityForResult(intent, IMAGE_CAPTURE);

If I want to get image from gallery, I can do:

Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);

I am wondering how can put the above two together.
That means GET IMAGE FROM GALLERY OR CAPTURE PHOTO Select an action

Is there any example code to do it? Thanks.

Upvotes: 38

Views: 69048

Answers (8)

sanket vetkoli
sanket vetkoli

Reputation: 856

The way of doing this as of 2023 using ActivityResultsContract, you can create your own custom ActivityResultContract something like this

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.MediaStore
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts

class ImageChooserActivityResultContract: ActivityResultContract<Triple<Uri?, PickVisualMediaRequest, String>, Pair<Boolean, Uri?>>() {
override fun createIntent(
    context: Context,
    input: Triple<Uri?, PickVisualMediaRequest, String>
): Intent {
    if (input.first == null) return getImageSelectIntent(input.second)
    val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        .putExtra(MediaStore.EXTRA_OUTPUT, input.first)
    val imageSelectIntent = getImageSelectIntent(input.second)
    val chooserIntent = Intent.createChooser(cameraIntent, input.third)
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(imageSelectIntent))
    return chooserIntent
}

private fun getImageSelectIntent(pickVisualMediaRequest: PickVisualMediaRequest): Intent {
    return if (ActivityResultContracts.PickVisualMedia.isPhotoPickerAvailable()) {
        Intent(MediaStore.ACTION_PICK_IMAGES).apply {
            type = getVisualMimeType(pickVisualMediaRequest.mediaType)
        }
    } else {
        // For older devices running KitKat and higher and devices running Android 12
        // and 13 without the SDK extension that includes the Photo Picker, rely on the
        // ACTION_OPEN_DOCUMENT intent
        Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            type = getVisualMimeType(pickVisualMediaRequest.mediaType)

            if (type == null) {
                // ACTION_OPEN_DOCUMENT requires to set this parameter when launching the
                // intent with multiple mime types
                type = "*/*"
                putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
            }
        }
    }
}

private fun getVisualMimeType(input: ActivityResultContracts.PickVisualMedia.VisualMediaType): String? {
    return when (input) {
        is ActivityResultContracts.PickVisualMedia.ImageOnly -> "image/*"
        is ActivityResultContracts.PickVisualMedia.VideoOnly -> "video/*"
        is ActivityResultContracts.PickVisualMedia.SingleMimeType -> input.mimeType
        is ActivityResultContracts.PickVisualMedia.ImageAndVideo -> null
    }
}

override fun parseResult(resultCode: Int, intent: Intent?): Pair<Boolean, Uri?> {
    val isSuccessful = resultCode == Activity.RESULT_OK
    val uri = intent.takeIf { isSuccessful }?.data
    return Pair(isSuccessful, uri)
    }
}

Next create a ActivityResultLauncher for the same

private val imageChooser =
    registerForActivityResult(ImageChooserActivityResultContract()) { pair ->
        if (pair.first) {
            pair.second?.let { imageUri ->
                //Do image capture part here
                mCameraUri?.let { cameraImageUri ->
                    cameraImageUri.path?.let { path ->
                        val file = File(path)
                        if (file.exists()) file.delete()
                    }
                }
            }
                ?: kotlin.run { mCameraUri?.let { /*Do camera image select here */ } }
        } else {
            //Handle cancel result
        }
    }

Camera permission launcher

private val cameraPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
        if (isGranted) {
            createFileForCameraImageCapture()
            launchImageChooser(mCameraUri)
        } else if (ActivityCompat.shouldShowRequestPermissionRationale(
                this,
                android.Manifest.permission.CAMERA
            )
        ) {
            showPermissionExplainerDialog(getString(R.string.camera_permission_explainer))
        } else {
            launchImageChooser(null)
        }
    }

To launch

private fun createFileForCameraImageCapture() {
    val imageFile: File? = try {
        createImageFile()
    } catch (e: Exception) {
        Log.e(TAG, "createFileForCameraImageCapture: Unalble to create image file", e)
        null
    }

    imageFile?.let {
        mCameraUri =
            FileProvider.getUriForFile(this, BuildConfig.FILE_PROVIDER_AUTHORITY, it)
    } ?: kotlin.run { mCameraUri = null }
}

private fun launchImageChooser(cameraUri: Uri?) {
    imageChooser.launch(
        Triple(
            cameraUri,
            PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly),
            "Image Chooser"
        )
    )
}

Upvotes: 0

Loyea
Loyea

Reputation: 3569

In fact your dialog title is "select an action" means the dialog is a Intent chooser actually. not a user customed dialog. The every single item presents a Intent.

public void click(View view) {
        File file = getExternalFilesDir(Environment.DIRECTORY_DCIM);
        Uri cameraOutputUri = Uri.fromFile(file);
        Intent intent = getPickIntent(cameraOutputUri);
        startActivityForResult(intent, -1);
    }

    private Intent getPickIntent(Uri cameraOutputUri) {
        final List<Intent> intents = new ArrayList<Intent>();

        if (true) {
            intents.add(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI));
        }

        if (true) {
            setCameraIntents(intents, cameraOutputUri);
        }

        if (intents.isEmpty()) return null;
        Intent result = Intent.createChooser(intents.remove(0), null);
        if (!intents.isEmpty()) {
            result.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[] {}));
        }
        return result;


    }

    private void setCameraIntents(List<Intent> cameraIntents, Uri output) {
        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.EXTRA_OUTPUT, output);
            cameraIntents.add(intent);
        }
    }

You may need solve permissions by yourself if run on OS >= 23

Here's my demo:(Appearance differences since OS different)
enter image description here

Upvotes: 2

roepit
roepit

Reputation: 1153

Let's say that you have two intents. One that would open a camera, one that would open a gallery. I will call these cameraIntent and gallerIntent in the example code. You can use intent chooser to combine these two:

Kotlin:

val chooser = Intent.createChooser(galleryIntent, "Some text here")
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(cameraIntent))
startActivityForResult(chooser, requestCode)

Java:

Intent chooser = Intent.createChooser(galleryIntent, "Some text here");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { cameraIntent });
startActivityForResult(chooser, requestCode);

This is, as you asked, how you can put the two together (without having to make your own UI/ dialog).

Upvotes: 36

yukun qian
yukun qian

Reputation: 81

public static Intent getPickImageIntent(Context context) {
    Intent chooserIntent = null;

    List<Intent> intentList = new ArrayList<>();

    Intent pickIntent = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePhotoIntent.putExtra("return-data", true);
    takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(context)));
    intentList = addIntentsToList(context, intentList, pickIntent);
    intentList = addIntentsToList(context, intentList, takePhotoIntent);

    if (intentList.size() > 0) {
        chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1),
                context.getString(R.string.pick_image_intent_text));
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{}));
    }

    return chooserIntent;
}

private static List<Intent> addIntentsToList(Context context, List<Intent> list, Intent intent) {
    List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(intent, 0);
    for (ResolveInfo resolveInfo : resInfo) {
        String packageName = resolveInfo.activityInfo.packageName;
        Intent targetedIntent = new Intent(intent);
        targetedIntent.setPackage(packageName);
        list.add(targetedIntent);
    }
    return list;
}

Upvotes: 0

Rahul Patel
Rahul Patel

Reputation: 3843

If you want to take picture from Camera or Gallery Intent Together, Then check below link. Same question also posted here.

Capturing image from gallery & camera in android

UPDATED CODE:

check below code, In this code not same as you want into listview, but it gives the option in the dialogBox choose image from Gallary OR Camera.

public class UploadImageActivity extends Activity {
ImageView img_logo;
protected static final int CAMERA_REQUEST = 0;
protected static final int GALLERY_PICTURE = 1;
private Intent pictureActionIntent = null;
Bitmap bitmap;

    String selectedImagePath;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main1);

    img_logo= (ImageView) findViewById(R.id.imageView1);
    img_logo.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            startDialog();
        }

    });
}

private void startDialog() {
    AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(
            getActivity());
    myAlertDialog.setTitle("Upload Pictures Option");
    myAlertDialog.setMessage("How do you want to set your picture?");

    myAlertDialog.setPositiveButton("Gallery",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {
                    Intent pictureActionIntent = null;

                    pictureActionIntent = new Intent(
                            Intent.ACTION_PICK,
                            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                     startActivityForResult(
                            pictureActionIntent,
                            GALLERY_PICTURE);

                }
            });

    myAlertDialog.setNegativeButton("Camera",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {

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

                     startActivityForResult(intent,
                            CAMERA_REQUEST);

                }
            });
    myAlertDialog.show();
}

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

    super.onActivityResult(requestCode, resultCode, data);

    bitmap = null;
    selectedImagePath = null;

    if (resultCode == RESULT_OK && requestCode == CAMERA_REQUEST) {

        File f = new File(Environment.getExternalStorageDirectory()
                .toString());
        for (File temp : f.listFiles()) {
            if (temp.getName().equals("temp.jpg")) {
                f = temp;
                break;
            }
        }

        if (!f.exists()) {

            Toast.makeText(getBaseContext(),

            "Error while capturing image", Toast.LENGTH_LONG)

            .show();

            return;

        }

        try {

            bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());

            bitmap = Bitmap.createScaledBitmap(bitmap, 400, 400, true);

            int rotate = 0;
            try {
                ExifInterface exif = new ExifInterface(f.getAbsolutePath());
                int orientation = exif.getAttributeInt(
                        ExifInterface.TAG_ORIENTATION,
                        ExifInterface.ORIENTATION_NORMAL);

                switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotate = 270;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotate = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotate = 90;
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            Matrix matrix = new Matrix();
            matrix.postRotate(rotate);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), matrix, true);



            img_logo.setImageBitmap(bitmap);
            //storeImageTosdCard(bitmap);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    } else if (resultCode == RESULT_OK && requestCode == GALLERY_PICTURE) {
        if (data != null) {

            Uri selectedImage = data.getData();
            String[] filePath = { MediaStore.Images.Media.DATA };
            Cursor c = getContentResolver().query(selectedImage, filePath,
                    null, null, null);
            c.moveToFirst();
            int columnIndex = c.getColumnIndex(filePath[0]);
            selectedImagePath = c.getString(columnIndex);
            c.close();

            if (selectedImagePath != null) {
                txt_image_path.setText(selectedImagePath);
            }

            bitmap = BitmapFactory.decodeFile(selectedImagePath); // load
            // preview image
            bitmap = Bitmap.createScaledBitmap(bitmap, 400, 400, false);



            img_logo.setImageBitmap(bitmap);

        } else {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }

}


}

Also add pemission:

<uses-permission android:name="android.permission.CAMERA" />

 <uses-feature
    android:name="android.hardware.camera.autofocus"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />

store Image to sdcard:

private void storeImageTosdCard(Bitmap processedBitmap) {
    try {
        // TODO Auto-generated method stub

        OutputStream output;
        // Find the SD Card path
        File filepath = Environment.getExternalStorageDirectory();
        // Create a new folder in SD Card
        File dir = new File(filepath.getAbsolutePath() + "/appName/");
        dir.mkdirs();

        String imge_name = "appName" + System.currentTimeMillis()
                + ".jpg";
        // Create a name for the saved image
        File file = new File(dir, imge_name);
        if (file.exists()) {
            file.delete();
            file.createNewFile();
        } else {
            file.createNewFile();

        }

        try {

            output = new FileOutputStream(file);

            // Compress into png format image from 0% - 100%
            processedBitmap
                    .compress(Bitmap.CompressFormat.PNG, 100, output);
            output.flush();
            output.close();

            int file_size = Integer
                    .parseInt(String.valueOf(file.length() / 1024));
            System.out.println("size ===>>> " + file_size);
            System.out.println("file.length() ===>>> " + file.length());

            selectedImagePath = file.getAbsolutePath();



        }

        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Upvotes: 51

Felix
Felix

Reputation: 2703

If you want to show all the apps installed in the phone that can deal with photos such as Camera, Gallery, Dropbox, etc.

You can do something like:

1.- Ask for all the intents available:

    Intent camIntent = new Intent("android.media.action.IMAGE_CAPTURE");
    Intent gallIntent=new Intent(Intent.ACTION_GET_CONTENT);
    gallIntent.setType("image/*"); 

    // look for available intents
    List<ResolveInfo> info=new ArrayList<ResolveInfo>();
    List<Intent> yourIntentsList = new ArrayList<Intent>();
    PackageManager packageManager = context.getPackageManager();
    List<ResolveInfo> listCam = packageManager.queryIntentActivities(camIntent, 0);
    for (ResolveInfo res : listCam) {
        final Intent finalIntent = new Intent(camIntent);
        finalIntent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        yourIntentsList.add(finalIntent);
        info.add(res);
    }
    List<ResolveInfo> listGall = packageManager.queryIntentActivities(gallIntent, 0);
    for (ResolveInfo res : listGall) {
        final Intent finalIntent = new Intent(gallIntent);
        finalIntent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        yourIntentsList.add(finalIntent);
        info.add(res);
    }

2.- Show a custom dialog with the list of items:

    AlertDialog.Builder dialog = new AlertDialog.Builder(context);
    dialog.setTitle(context.getResources().getString(R.string.select_an_action));
    dialog.setAdapter(buildAdapter(context, activitiesInfo),
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    Intent intent = intents.get(id);
                    context.startActivityForResult(intent,1);
                }
            });

    dialog.setNeutralButton(context.getResources().getString(R.string.cancel),
            new android.content.DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    dialog.show();

This is a full example: https://gist.github.com/felixgborrego/7943560

Upvotes: 14

Leon Yuu
Leon Yuu

Reputation: 11

I think I encountered your case before. An idea is that we will create a one item list alert dialog with selectable item, and each item will do a unique function defined by your own intention. If you want an icon for each element in items list, it should take a bit more work to do. Hope it will helpful.

    String title = "Open Photo";
    CharSequence[] itemlist ={"Take a Photo",
                  "Pick from Gallery",
                  "Open from File"};

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setIcon(R.drawable.icon_app);
    builder.setTitle(title);
    builder.setItems(itemlist, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            switch (which) {
            case 0:// Take Photo
                // Do Take Photo task here
                break;
            case 1:// Choose Existing Photo
                // Do Pick Photo task here
                break;
            case 2:// Choose Existing File
                // Do Pick file here
                break;
            default:
                break;
            }
        }
    });
    AlertDialog alert = builder.create();
    alert.setCancelable(true);
    alert.show();

Upvotes: 1

0gravity
0gravity

Reputation: 2762

Create a button in your XML layout and the add the attribute android:onClick="takeAPicture" then in your main activity create a method with the same name from the onClick attribute.

public void takeAPicture(View view){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
        startActivityForResult(intent, IMAGE_CAPTURE);
}

And just do another method for when you want to get the image from the gallery:

public void getImageFromGallery(View view) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
} 

Upvotes: 0

Related Questions