Boîte de dialogue pour choisir une image de la galerie ou de la caméra

122

Existe-t-il un moyen standard d'appeler la boîte de dialogue avec le choix de choisir une image de la caméra ou d'obtenir de la galerie (comme dans l'annuaire intégré ou Skype)?

J'ai jeté un coup d'œil à cela, mais le code ouvre la galerie sans suggérer de le choisir depuis la caméra.

Appareil: Samsung Galaxy Tab
Android: 2.3.3

Sergey Metlov
la source
Jetez un œil à cette réponse avec une intention qui fusionne les deux demandes (Caméra et Galerie) dans une intention unique: stackoverflow.com/a/32475805/2232889
Mario Velasco

Réponses:

192

Le code ci-dessous peut être utilisé pour prendre une photo et pour choisir une photo. Affichez simplement une boîte de dialogue avec deux options et, lors de la sélection, utilisez le code approprié.

Pour prendre une photo depuis l'appareil photo:

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);//zero can be replaced with any action code (called requestCode)

Pour choisir une photo dans la galerie:

Intent pickPhoto = new Intent(Intent.ACTION_PICK,
           android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);//one can be replaced with any action code

onActivityResult code:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 
    switch(requestCode) {
    case 0:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }

    break; 
    case 1:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }
    break;
    }
}

Enfin, ajoutez cette autorisation dans le fichier manifeste:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Shankar Agarwal
la source
20
Les autorisations de l'appareil photo ne sont pas nécessaires car elles ouvrent l'application par défaut.
tasomaniac
2
@Jeremy Non, c'est faux. Si vous n'en avez pas du tout l'autorisation, vous pouvez simplement l'utiliser. Parce que ce n'est pas votre application qui ouvre la caméra. La nuance est que si vous avez l'autorisation et si l'utilisateur a rejeté l'autorisation, son utilisation Intentcomme solution de secours lève SecurityException. Plus d'informations: plus.google.com/+AndroidDevelopers/posts/e9kyM7VXajz
tasomaniac
2
L'autorisation de la caméra est maintenant nécessaire pour ouvrir l'intention de la caméra @tasomaniac
Saad Bilal
27
avec ACTION_IMAGE_CAPTURE je reçois imageReturnedIntent.getData () == null pourquoi?
Xan
3
Selon la documentation officielle developer.android.com/training/camera/photobasics, la prise de photo ne sauvegarde pas l'image dans Uri retournée par intents getData (). Vous ne pouvez obtenir une vignette qu'à partir de l'intention de résultat (intent.getBundle (). Get ("data)). L'image en taille réelle peut être écrite dans un fichier préparé à cet effet avant l'appel de startActivityForResult.
marioc64
56

J'ai fusionné certaines solutions pour créer un utilitaire complet pour choisir une image dans la galerie ou l'appareil photo. Voici les fonctionnalités de ImagePicker util gist (également dans une librairie Github ):

  • Intentions fusionnées pour les requêtes Galerie et Appareil photo.
  • Redimensionner les grandes images sélectionnées (par exemple: 2500 x 1600)
  • Faire pivoter l'image si nécessaire

Capture d'écran:

Intention de démarrage ImagePicker

Modifier : voici un fragment de code pour obtenir une intention fusionnée pour les applications Galerie et Appareil photo. Vous pouvez voir le code complet sur ImagePicker util gist (également dans une bibliothèque Github ):

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;
}
Mario Velasco
la source
4
Cela fonctionne parfaitement, Mario. Merci beaucoup! Je l'ai testé dans un Samsung GT-I9100, un LG L7, mais cela échoue lorsque nous essayons de mettre l'image de la caméra dans un Nexus 6 avec Android 6. La solution serait d'ajouter ceci à votre ligne 58 dans ImagePicker.java:boolean isCamera = (imageReturnedIntent == null || imageReturnedIntent.getData() == null);
Gabi Moreno
1
Merci @GabrielMorenoIbarra. Vous l'avez corrigé, maintenant c'est dans mon code aussi.
Mario Velasco du
qu'est-ce que getTempFileet comment utiliser cette fonction? s'il vous plaît mettre à jour la réponse
Basheer AL-MOMANI
1
C'est une fonction pour obtenir un fichier temporel. Jetez un œil au lien et vous trouverez un script plus détaillé
Mario Velasco
1
@Brainware, oui, cela dépend de la version d'Android. Pensez à utiliser FileProviderpour API> = 23 et Urimoins cher.
CoolMind
19

Cette bibliothèque simplifie les choses.

Il suffit d'appeler:

PickImageDialog.on(MainActivity.this, new PickSetup(BuildConfig.APPLICATION_ID));

Ensuite, faites en sorte que votre activité implémente IPickResult et remplacez cette méthode ci-dessous.

@Override
public void onPickResult(PickResult r) {
    if (r.getError() == null) {
        imageView.setImageBitmap(r.getBitmap());

        //or

        imageView.setImageURI(r.getUri());
    } else {
        //Handle possible errors
        //TODO: do what you have to do with r.getError();
    }
}
Vansuita Jr.
la source
J'ai des photos d'Amazon dans mon bord de téléphone s7 chaque fois que je sélectionne l'option de galerie, il redirige vers la page de connexion amazon et dans d'autres téléphones, c'est bien .. mais je teste dans le bord
s7
C'est une approche très désordonnée, peut affecter tout le code. Je ne sais pas pourquoi le gars a créé un repo mvn séparé.
Joy
Cela permet-il des images à sélection multiple ou à capture multiple?
Adnan
12

Vous pouvez implémenter ce code pour sélectionner l'image de la galerie ou de la caméra: -

private ImageView imageview;
private Button btnSelectImage;
private Bitmap bitmap;
private File destination = null;
private InputStream inputStreamImg;
private String imgPath = null;
private final int PICK_IMAGE_CAMERA = 1, PICK_IMAGE_GALLERY = 2;

Maintenant, sur l'événement de clic de bouton, vous pouvez appeler votre méthode de sélection d'image. C'est à l'intérieur de l'activité onCreate.

imageview = (ImageView) findViewById(R.id.imageview);
btnSelectImage = (Button) findViewById(R.id.btnSelectImage);

//OnbtnSelectImage click event...
btnSelectImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            selectImage();
        }
    });

En dehors de la création de votre activité.

// Select image from camera and gallery
private void selectImage() {
    try {
        PackageManager pm = getPackageManager();
        int hasPerm = pm.checkPermission(Manifest.permission.CAMERA, getPackageName());
        if (hasPerm == PackageManager.PERMISSION_GRANTED) {
            final CharSequence[] options = {"Take Photo", "Choose From Gallery","Cancel"};
            android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(activity);
            builder.setTitle("Select Option");
            builder.setItems(options, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int item) {
                    if (options[item].equals("Take Photo")) {
                        dialog.dismiss();
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        startActivityForResult(intent, PICK_IMAGE_CAMERA);
                    } else if (options[item].equals("Choose From Gallery")) {
                        dialog.dismiss();
                        Intent pickPhoto = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(pickPhoto, PICK_IMAGE_GALLERY);
                    } else if (options[item].equals("Cancel")) {
                        dialog.dismiss();
                    }
                }
            });
            builder.show();
        } else
            Toast.makeText(this, "Camera Permission error", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        Toast.makeText(this, "Camera Permission error", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    inputStreamImg = null;
    if (requestCode == PICK_IMAGE_CAMERA) {
        try {
            Uri selectedImage = data.getData();
            bitmap = (Bitmap) data.getExtras().get("data");
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bytes);

            Log.e("Activity", "Pick from Camera::>>> ");

            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
            destination = new File(Environment.getExternalStorageDirectory() + "/" +
                    getString(R.string.app_name), "IMG_" + timeStamp + ".jpg");
            FileOutputStream fo;
            try {
                destination.createNewFile();
                fo = new FileOutputStream(destination);
                fo.write(bytes.toByteArray());
                fo.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            imgPath = destination.getAbsolutePath();
            imageview.setImageBitmap(bitmap);

        } catch (Exception e) {
            e.printStackTrace();
        }
    } else if (requestCode == PICK_IMAGE_GALLERY) {
        Uri selectedImage = data.getData();
        try {
            bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bytes);
            Log.e("Activity", "Pick from Gallery::>>> ");

            imgPath = getRealPathFromURI(selectedImage);
            destination = new File(imgPath.toString());
            imageview.setImageBitmap(bitmap);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public String getRealPathFromURI(Uri contentUri) {
    String[] proj = {MediaStore.Audio.Media.DATA};
    Cursor cursor = managedQuery(contentUri, proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

Enfin, ajoutez enfin la caméra et écrivez l'autorisation de stockage externe sur AndroidManifest.xml

Cela fonctionne grandement pour moi, j'espère que cela fonctionnera également pour vous.

Nikhil
la source
1
J'ajoute l'autorisation de la caméra mais une erreur précise et j'affiche "erreur d'autorisation de la caméra"
roghayeh hosseini
7

Je pense que c'est à vous de montrer ce dialogue pour choisir. Pour la galerie, vous utiliserez ce code, et pour l'appareil photo, essayez ceci .

Igor Filippov
la source
1
Mais l'image se met à l'envers dans cet échantillon
Ensoleillé
3

Si vous souhaitez obtenir l'image de la galerie ou capturer l'image et la définir sur la vue image en mode portrait, le code suivant vous aidera.

Dans onCreate ()

imageViewRound.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            selectImage();
        }
    });




    private void selectImage() {
    Constants.iscamera = true;
    final CharSequence[] items = { "Take Photo", "Choose from Library",
            "Cancel" };

     TextView title = new TextView(context);
     title.setText("Add Photo!");
        title.setBackgroundColor(Color.BLACK);
        title.setPadding(10, 15, 15, 10);
        title.setGravity(Gravity.CENTER);
        title.setTextColor(Color.WHITE);
        title.setTextSize(22);


    AlertDialog.Builder builder = new AlertDialog.Builder(
            AddContactActivity.this);



    builder.setCustomTitle(title);

    // builder.setTitle("Add Photo!");
    builder.setItems(items, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals("Take Photo")) {
                // Intent intent = new
                // Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                Intent intent = new Intent(
                        android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                /*
                 * File photo = new
                 * File(Environment.getExternalStorageDirectory(),
                 * "Pic.jpg"); intent.putExtra(MediaStore.EXTRA_OUTPUT,
                 * Uri.fromFile(photo)); imageUri = Uri.fromFile(photo);
                 */
                // startActivityForResult(intent,TAKE_PICTURE);

                Intent intents = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);

                intents.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

                // start the image capture Intent
                startActivityForResult(intents, TAKE_PICTURE);

            } else if (items[item].equals("Choose from Library")) {
                Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(
                        Intent.createChooser(intent, "Select Picture"),
                        SELECT_PICTURE);
            } else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}




    @SuppressLint("NewApi")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
    case SELECT_PICTURE:
        Bitmap bitmap = null;
        if (resultCode == RESULT_OK) {
            if (data != null) {


                try {
                    Uri selectedImage = data.getData();
                    String[] filePath = { MediaStore.Images.Media.DATA };
                    Cursor c = context.getContentResolver().query(
                            selectedImage, filePath, null, null, null);
                    c.moveToFirst();
                    int columnIndex = c.getColumnIndex(filePath[0]);
                    String picturePath = c.getString(columnIndex);
                    c.close();
                    imageViewRound.setVisibility(View.VISIBLE);
                    // Bitmap thumbnail =
                    // (BitmapFactory.decodeFile(picturePath));
                    Bitmap thumbnail = decodeSampledBitmapFromResource(
                            picturePath, 500, 500);

                    // rotated
                    Bitmap thumbnail_r = imageOreintationValidator(
                            thumbnail, picturePath);
                    imageViewRound.setBackground(null);
                    imageViewRound.setImageBitmap(thumbnail_r);
                    IsImageSet = true;
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        break;
    case TAKE_PICTURE:
        if (resultCode == RESULT_OK) {

            previewCapturedImage();

        }

        break;
    }

}



 @SuppressLint("NewApi")
private void previewCapturedImage() {
    try {
        // hide video preview

        imageViewRound.setVisibility(View.VISIBLE);

        // bimatp factory
        BitmapFactory.Options options = new BitmapFactory.Options();

        // downsizing image as it throws OutOfMemory Exception for larger
        // images
        options.inSampleSize = 8;

        final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
                options);

        Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 500, 500,
                false);

        // rotated
        Bitmap thumbnail_r = imageOreintationValidator(resizedBitmap,
                fileUri.getPath());

        imageViewRound.setBackground(null);
        imageViewRound.setImageBitmap(thumbnail_r);
        IsImageSet = true;
        Toast.makeText(getApplicationContext(), "done", Toast.LENGTH_LONG)
                .show();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
}






    // for roted image......
private Bitmap imageOreintationValidator(Bitmap bitmap, String path) {

    ExifInterface ei;
    try {
        ei = new ExifInterface(path);
        int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);
        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            bitmap = rotateImage(bitmap, 90);
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            bitmap = rotateImage(bitmap, 180);
            break;
        case ExifInterface.ORIENTATION_ROTATE_270:
            bitmap = rotateImage(bitmap, 270);
            break;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return bitmap;
}



private Bitmap rotateImage(Bitmap source, float angle) {

    Bitmap bitmap = null;
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    try {
        bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                source.getHeight(), matrix, true);
    } catch (OutOfMemoryError err) {
        source.recycle();
        Date d = new Date();
        CharSequence s = DateFormat
                .format("MM-dd-yy-hh-mm-ss", d.getTime());
        String fullPath = Environment.getExternalStorageDirectory()
                + "/RYB_pic/" + s.toString() + ".jpg";
        if ((fullPath != null) && (new File(fullPath).exists())) {
            new File(fullPath).delete();
        }
        bitmap = null;
        err.printStackTrace();
    }
    return bitmap;
}




public static Bitmap decodeSampledBitmapFromResource(String pathToFile,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathToFile, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
            reqHeight);

    Log.e("inSampleSize", "inSampleSize______________in storage"
            + options.inSampleSize);
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(pathToFile, options);
}




public static int calculateInSampleSize(BitmapFactory.Options options,
        int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

    }

    return inSampleSize;
}




public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}






private static File getOutputMediaFile(int type) {

    // External sdcard location
    File mediaStorageDir = new File(
            Environment
                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            IMAGE_DIRECTORY_NAME);

    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
                    + IMAGE_DIRECTORY_NAME + " directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
            Locale.getDefault()).format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");
    } else {
        return null;
    }

    return mediaFile;
}






public Uri getOutputMediaFileUri(int type) {
    return Uri.fromFile(getOutputMediaFile(type));
}

J'espère que ceci vous aidera....!!!

Si targetSdkVersion est supérieur à 24, FileProvider est utilisé pour accorder l'accès.

Créez un fichier xml (chemin: res \ xml) chemin_fournisseurs.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Ajouter un fournisseur dans AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

et remplacer

return Uri.fromFile(getOutputMediaFile(type));

À

               return FileProvider.getUriForFile(this,  BuildConfig.APPLICATION_ID + ".provider", getOutputMediaFile(type));
Pratibha Sarode
la source