279 votes

Obtenir/choisir une image à partir de l'application Galerie intégrée d'Android de manière programmatique

J'essaie d'ouvrir une image/photo dans l'application intégrée Gallery à partir de mon application.

J'ai une URI de l'image (l'image est située sur la carte SD).

Avez-vous des suggestions ?

0 votes

J'ai mis à jour ma réponse pour fournir plus de code de test afin de m'assurer que vous récupérez les résultats correctement.

0 votes

regardez ma réponse, c'est une mise à jour du code de hcpl et cela fonctionne pour le gestionnaire de fichiers astro et le gestionnaire de fichiers oi aussi.

15 votes

Quelqu'un devrait mettre à jour la question "Obtenir/choisir une image à partir de l'Android...". La question actuelle interprète que j'ai une image et que je veux la montrer via l'application galerie par défaut.

356voto

hcpl Points 5759

C'est une solution complète. Je viens de mettre à jour cet exemple de code avec les informations fournies dans la réponse ci-dessous par @mad. Consultez également la solution ci-dessous de @Khobaib expliquant comment traiter les images picasa.

Mise à jour

Je viens de revoir ma réponse originale et j'ai créé un projet Android Studio simple que vous pouvez récupérer sur github et importer directement sur votre système.

https://github.com/hanscappelle/SO-2169649

(notez que la sélection de fichiers multiples nécessite encore du travail)

Sélection d'une seule image

Avec la prise en charge des images des explorateurs de fichiers grâce à l'utilisateur fou.

public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.Button01)
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                String path = cursor.getString(column_index);
                cursor.close();
                return path;
            }
            // this is our fallback here
            return uri.getPath();
    }

}

Sélection de plusieurs images

Puisque quelqu'un a demandé cette information dans un commentaire et qu'il est préférable d'avoir des informations rassemblées.

Définir un paramètre supplémentaire EXTRA_ALLOW_MULTIPLE sur l'intention :

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Et dans le traitement des résultats, vérifiez ce paramètre :

if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    if( list != null ) {
       for (Parcelable parcel : list) {
         Uri uri = (Uri) parcel;
         // TODO handle the images one by one here
       }
   }
} 

Notez que cette fonction n'est prise en charge que par le niveau 18+ de l'API.

0 votes

Cela ne fonctionne pas lorsque j'utilise le gestionnaire de fichiers Astro. Vous savez pourquoi ?

0 votes

@hcpl Merci pour la réponse. Pouvez-vous me dire comment obtenir plusieurs images... ?

0 votes

petit ajout pour la compatibilité des appareils : intent.setType("image/*") ; if (Android.os.Build.MODEL.startsWith("HTC")) intent.putExtra("folderType", "com.htc.HTCAlbum.ALL_PHOTOS") ;

134voto

mad Points 2492

Voici une mise à jour de l'excellent code que hcpl a posté. mais cela fonctionne avec le gestionnaire de fichiers OI, le gestionnaire de fichiers astro ET la galerie de médias aussi (testé). donc je suppose que cela fonctionnera avec tous les gestionnaires de fichiers (y en a-t-il beaucoup d'autres que ceux mentionnés ?). j'ai fait quelques corrections au code qu'il a écrit.

public class BrowsePicture extends Activity {

    //YOU CAN EDIT THIS TO WHATEVER YOU WANT
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;
    //ADDED
    private String filemanagerstring;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
        .setOnClickListener(new OnClickListener() {

            public void onClick(View arg0) {

                // in onCreate or any event where your want the user to
                // select a file
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);
            }
        });
    }

    //UPDATED
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();

                //OI FILE Manager
                filemanagerstring = selectedImageUri.getPath();

                //MEDIA GALLERY
                selectedImagePath = getPath(selectedImageUri);

                //DEBUG PURPOSE - you can delete this if you want
                if(selectedImagePath!=null)
                    System.out.println(selectedImagePath);
                else System.out.println("selectedImagePath is null");
                if(filemanagerstring!=null)
                    System.out.println(filemanagerstring);
                else System.out.println("filemanagerstring is null");

                //NOW WE HAVE OUR WANTED STRING
                if(selectedImagePath!=null)
                    System.out.println("selectedImagePath is the right one for you!");
                else
                    System.out.println("filemanagerstring is the right one for you!");
            }
        }
    }

    //UPDATED!
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }

1 votes

Comment récupérer une image bitmap à partir d'un chemin OI ?

2 votes

regardez le code. aux lignes avec le commentaire //Maintenant nous avons la chaîne désirée... c'est tout ce dont vous avez besoin. ensuite utilisez la classe BitmapFactory pour récupérer un bitmap à partir d'un chemin d'accès

0 votes

Merci. Vous avez un bon point, je n'ai jamais essayé d'autres gestionnaires de fichiers :).

26voto

abbath Points 537

Les méthodes de hcpl fonctionnent parfaitement avant KitKat, mais ne fonctionnent pas avec l'API DocumentsProvider. Pour cela, il suffit de suivre le tutoriel officiel Android pour les documentsproviders : https://developer.Android.com/guide/topics/providers/document-provider.html -> ouvrir un document, section Bitmap.

J'ai simplement utilisé le code de hcpl et l'ai étendu : si le fichier avec le chemin récupéré de l'image lève une exception, j'appelle cette fonction :

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
             getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
}

Testé sur Nexus 5.

0 votes

Réponse très utile, à utiliser pour sélectionner des images dans l'application "Photos".

0 votes

J'ai essayé cela sur les fichiers locaux et ceux du serveur, cela a fonctionné pour les deux.

11voto

szhln Points 101

Sur la base du code ci-dessus, j'ai réfléchi au code suivant, qui est peut-être plus approprié :

public String getPath(Uri uri) {
    String selectedImagePath;
    //1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor != null){
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        selectedImagePath = cursor.getString(column_index);
    }else{
        selectedImagePath = null;
    }

    if(selectedImagePath == null){
        //2:OI FILE Manager --- call method: uri.getPath()
        selectedImagePath = uri.getPath();
    }
    return selectedImagePath;
}

10voto

Anthony Forloney Points 30083

En supposant que vous ayez un image dans le répertoire de votre carte SD pour les images uniquement.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*"); 
startActivityForResult(intent, 1);

Ensuite, vous pouvez décider de ce que vous souhaitez faire avec le contenu de retour dans votre activité.

Il s'agit d'un exemple de récupération du nom du chemin d'accès à l'image. Testez-le avec votre code pour vous assurer que vous pouvez gérer les résultats obtenus. Vous pouvez modifier le code si nécessaire pour mieux répondre à vos besoins.

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

  // this matches the request code in the above call
  if (requestCode == 1) {
      Uri _uri = i.getData();

    // this will be null if no image was selected...
    if (_uri != null) {
      // now we get the path to the image file
     cursor = getContentResolver().query(_uri, null,
                                      null, null, null);
     cursor.moveToFirst();
     String imageFilePath = cursor.getString(0);
     cursor.close();
     }
   }

Mon conseil est d'essayer de faire fonctionner correctement la récupération des images, je pense que le problème est le contenu de l'accès aux images sur la carte SD. Jetez un coup d'oeil à Affichage des images sur la carte SD .

Si vous parvenez à le faire fonctionner, probablement en fournissant un fournisseur correct dans l'exemple, vous devriez être en mesure de trouver une solution de contournement pour votre code.

Tenez-moi au courant en mettant à jour cette question avec vos progrès. Bonne chance

0 votes

@Anthony, merci pour votre réponse. Malheureusement, elle ne fonctionne pas pour moi. J'obtiens l'erreur suivante : android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }

0 votes

Vous devez appeler startActivityforResult et fournir une activité. C'est à ça que je faisais allusion quand je parlais de décider de ce qu'il fallait faire ensuite, c'est ma faute.

0 votes

Cela ne fonctionne toujours pas... Je vérifie que le dossier existe et qu'il y a un fichier image dans le dossier. J'appelle startActivityForResult(intent, 1); et j'obtiens toujours cette erreur... Ce code est situé en dehors de l'activité, mais j'ai une référence à l'activité et j'appelle la fonction startActivityForResult sur cette référence - peut-être est-ce la raison ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X