Une seule intention de laisser l'utilisateur prendre une photo ou de choisir l'image de la galerie dans Android

je développe une application pour Android 2.1 upwards. Je veux permettre à mes utilisateurs de sélectionner une image de profil dans mon application (je n'utilise pas le framework contacts).

La solution idéale serait de tirer une intention qui permet à l'utilisateur de sélectionner une image dans la galerie, mais si une image n'est pas disponible, utilisez l'appareil photo pour prendre une photo (ou vice-versa, c'est à dire permettre à l'utilisateur de prendre une photo, mais si ils savent qu'ils ont déjà une image déjà, laissez les déposer dans la galerie et de choisir ladite image).

Actuellement, je peux faire l'un ou l'autre mais pas les deux.

si je passe directement en mode caméra en utilisant MediaStore.ACTION_IMAGE_CAPTURE il n'y a alors aucune option à laisser tomber dans la galerie.

si je vais directement à la galerie en utilisant L'intention.ACTION_PICK alors je peux choisir une image mais si je clique sur le bouton caméra (dans le coin supérieur droit de la galerie) alors une nouvelle intention de caméra est lancée. Si, toutes les photos prises ne sont pas retournées directement à mon application. (Bien sûr, vous pouvez appuyer sur le bouton arrière pour revenir dans la galerie et sélectionner l'image à partir de là, mais c'est une étape supplémentaire inutile et n'est pas du tout intuitive).

alors y a-t-il un moyen de combiner les deux ou vais-je devoir offrir un menu pour faire l'un ou l'autre de mon application? Semble que ce serait un cas d'utilisation...certes, je suis en manque de quelque chose?

65
demandé sur Damian 2010-04-25 16:07:06

4 réponses

UPDATE : l'autre réponse, en utilisant EXTRA_INITIAL_INTENTS , est meilleure à ce point. Au moment où j'ai écrit ma réponse, EXTRA_INITIAL_INTENTS n'existait pas encore, car il a été ajouté au niveau 5 de L'API.

est-il donc possible de combiner les deux ou vais-je avoir à offrir un menu à faire l'un ou l'autre de l'intérieur de mon application?

Écrire votre propre galerie qui a les caractéristiques que vous désirez.

je pense qu'un menu serait plus simple.

semble comme il serait une utilisation courante cas...certes, je suis en manque de quelque chose?

le développeur à côté de vous pensera que la galerie devrait vous permettre de choisir dans la galerie locale ou bien sautez sur Flickr pour faire une sélection à partir de là. Un autre développeur pense que la caméra ne doit pas seulement permettre de prendre une photo via l'appareil photo, mais à "prendre une photo" via le choix quelque chose de la galerie, inversant les choses de la façon dont vous l'envisagez. Encore un autre développeur pensera que la galerie devrait permettre la cueillette à partir de la galerie locale, ou Flickr, ou la caméra, ou une webcam réseau-attaché. Encore un autre développeur pensera que la galerie est stupide et les utilisateurs devraient simplement choisir des fichiers via un explorateur de fichiers. Et ainsi de suite.

tout cela dans un environnement (téléphones mobiles) où flash pour L'OS est à un prix.

Par conséquent, IMHO, il n'est pas tout à fait choquant que l'équipe centrale Android a choisi de fournir des blocs de construction pour vous d'assembler comme vous le souhaitez, plutôt que d'essayer d'accommoder tous les modèles possibles.

13
répondu CommonsWare 2014-03-25 11:37:12

vous pouvez essayer de faire quelque chose comme ceci:

// ...
// Within your enclosing Class
// ...
private static final int SELECT_PICTURE = 1;

// ... 

Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);

Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

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_PICTURE);

pour savoir comment gérer le résultat de l'activité, référez-vous à cette question


Note: un point critique est la façon de déterminer si la caméra ou la galerie a été utilisée. Cela est montré dans cet exemple de code: https://stackoverflow.com/a/12347567/294884

116
répondu Macarse 2017-05-23 10:31:23

vous pouvez procéder ainsi dans votre activité:

private static final int REQUEST_CODE_PICTURE= 1;

    /**
     * Click on View to change photo. Sets into View of your layout, android:onClick="clickOnPhoto"
     * @param view View
     */
    public void clickOnPhoto(View view) {
        Intent pickIntent = new Intent();
        pickIntent.setType("image/*");
        pickIntent.setAction(Intent.ACTION_GET_CONTENT);
        Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String pickTitle = "Take or select a photo";
        Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { takePhotoIntent });
        startActivityForResult(chooserIntent, REQUEST_CODE_PICTURE);
    }

alors, ajoutez toujours dans votre activité la méthode onActivityResult:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_PICTURE && resultCode == Activity.RESULT_OK) {
            if (data == null) {
                return;
            }
            try {
                InputStream inputStream = getContentResolver().openInputStream(data.getData());
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imgPhoto.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
10
répondu Dario Bruzzese 2015-09-11 09:03:24

ma réponse est presque identique à la solution @Macarse mais j'ajoute également une intention supplémentaire de montrer des applications de Galerie (Ex: Google Photos) et est écrit en Kotlin:

val REQUEST_CODE_GET_IMAGE = 101

private fun addProfileImage() {
    val pickImageFileIntent = Intent()
    pickImageFileIntent.type = "image/*"
    pickImageFileIntent.action = Intent.ACTION_GET_CONTENT

    val pickGalleryImageIntent = Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI)

    val captureCameraImageIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

    val pickTitle = "Capture from camera or Select from gallery the Profile photo"
    val chooserIntent = Intent.createChooser(pickImageFileIntent, pickTitle)
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(captureCameraImageIntent, pickGalleryImageIntent))
    startActivityForResult(chooserIntent, REQUEST_CODE_GET_IMAGE)
}

exemple Bonus:

private var imageTempFile: File? = null
private var imageMimeType: String? = null

private fun extractImage(intent: Intent?) {
    val imageUri = intent?.data
    imageUri?.let {
        Glide.with(this)
                .load(imageUri)
                .into(profileImageCiv)
        imageTempFile = MediaUtils.copyContentFromUriToCacheFile(this, imageUri, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
        imageMimeType = MediaUtils.getMimeType(this, imageUri)
    } ?: run {
        intent?.extras?.get("data")?.let { bitmap ->    // Bitmap was returned as raw bitmap
            Glide.with(this)
                    .load(bitmap)
                    .into(profileImageCiv)
            imageTempFile = MediaUtils.writeBitmapToCacheFile(this, bitmap as Bitmap, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
            imageMimeType = "image/jpeg"    // The bitmap was compressed as JPEG format. The bitmap itself doesn't have any format associated to it
        } ?: run {
            imageTempFile = null
            imageMimeType = null
            Log.e("Intent data is null.")
            Log.d("Error during photo selection")
        }
    }
}
0
répondu vovahost 2018-03-17 12:47:46