Je recherche: Une liste des noms des galeries de photos existantes (j'espère aussi leur vignette du haut) Le contenu de la galerie (je peux ensuite charger les vignettes et leur taille réelle au besoin)
Comment pourrais-je obtenir une liste des "Galeries" (je ne sais pas si c'est le terme approprié dans Android pour les regroupements d'images visibles dans l'application Galerie ...) et leur J'ai besoin d'accéder à la galerie dans sa structure sans utiliser l'affichage de la galerie existante (j'en crée une totalement nouvelle, pas une couche superposée au demandeur de photo, etc.)
Je suppose que MediaStore.Images est là où je dois être, mais je ne vois rien qui me donnera les regroupements ...
Les regroupements sont définis par MediaStore.Images.Media.BUCKET_DISPLAY_NAME
. Voici l'exemple de code pour répertorier les images et enregistrer leur nom de compartiment et date_taken:
// which image properties are we querying
String[] projection = new String[] {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATE_TAKEN
};
// content:// style URI for the "primary" external storage volume
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// Make the query.
Cursor cur = managedQuery(images,
projection, // Which columns to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
null // Ordering
);
Log.i("ListingImages"," query count=" + cur.getCount());
if (cur.moveToFirst()) {
String bucket;
String date;
int bucketColumn = cur.getColumnIndex(
MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int dateColumn = cur.getColumnIndex(
MediaStore.Images.Media.DATE_TAKEN);
do {
// Get the field values
bucket = cur.getString(bucketColumn);
date = cur.getString(dateColumn);
// Do something with the values.
Log.i("ListingImages", " bucket=" + bucket
+ " date_taken=" + date);
} while (cur.moveToNext());
}
/**
* Getting All Images Path
*
* @param activity
* @return ArrayList with images Path
*/
public static ArrayList<String> getAllShownImagesPath(Activity activity) {
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
ArrayList<String> listOfAllImages = new ArrayList<String>();
String absolutePathOfImage = null;
uri = Android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME };
cursor = activity.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
column_index_folder_name = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(absolutePathOfImage);
}
return listOfAllImages;
}
Voici la solution complète en quelques étapes simples:
Les étapes suivantes vous guideront sur la façon de créer un Vector
qui contiendra les albums trouvés sur un appareil donné. Chaque album contiendra une image d'aperçu ainsi qu'un Vector
intérieur qui contiendra toutes les images de l'album.
Créez un objet qui contiendra les images une fois extraites du stockage. Nous allons l'appeler PhoneAlbum
. Voici à quoi cela va ressembler:
public class PhoneAlbum {
private int id;
private String name;
private String coverUri;
private Vector<PhonePhoto> albumPhotos;
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public String getCoverUri() {
return coverUri;
}
public void setCoverUri( String albumCoverUri ) {
this.coverUri = albumCoverUri;
}
public Vector< PhonePhoto > getAlbumPhotos() {
if ( albumPhotos == null ) {
albumPhotos = new Vector<>();
}
return albumPhotos;
}
public void setAlbumPhotos( Vector< PhonePhoto > albumPhotos ) {
this.albumPhotos = albumPhotos;
}
}
Créez un objet qui contiendra les images dans l'album appelé: PhonePhoto
public class PhonePhoto {
private int id;
private String albumName;
private String photoUri;
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getAlbumName() {
return albumName;
}
public void setAlbumName( String name ) {
this.albumName = name;
}
public String getPhotoUri() {
return photoUri;
}
public void setPhotoUri( String photoUri ) {
this.photoUri = photoUri;
}
}
Créez une interface pour gérer les images extraites à la fin. Nous allons l'appeler OnPhoneImagesObtained
. C'est ici:
public interface OnPhoneImagesObtained {
void onComplete( Vector<PhoneAlbum> albums );
void onError();
}
Créez une nouvelle classe: DeviceImageManager
public class DeviceImageManager {
}
Une fois que vous avez créé DeviceImageManager
, ajoutez la méthode suivante:
public static void getPhoneAlbums( Context context , OnPhoneImagesObtained listener ){
// Creating vectors to hold the final albums objects and albums names
Vector< PhoneAlbum > phoneAlbums = new Vector<>();
Vector< String > albumsNames = new Vector<>();
// which image properties are we querying
String[] projection = new String[] {
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID
};
// content: style URI for the "primary" external storage volume
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// Make the query.
Cursor cur = context.getContentResolver().query(images,
projection, // Which columns to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
null // Ordering
);
if ( cur != null && cur.getCount() > 0 ) {
Log.i("DeviceImageManager"," query count=" + cur.getCount());
if (cur.moveToFirst()) {
String bucketName;
String data;
String imageId;
int bucketNameColumn = cur.getColumnIndex(
MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int imageUriColumn = cur.getColumnIndex(
MediaStore.Images.Media.DATA);
int imageIdColumn = cur.getColumnIndex(
MediaStore.Images.Media._ID );
do {
// Get the field values
bucketName = cur.getString( bucketNameColumn );
data = cur.getString( imageUriColumn );
imageId = cur.getString( imageIdColumn );
// Adding a new PhonePhoto object to phonePhotos vector
PhonePhoto phonePhoto = new PhonePhoto();
phonePhoto.setAlbumName( bucketName );
phonePhoto.setPhotoUri( data );
phonePhoto.setId( Integer.valueOf( imageId ) );
if ( albumsNames.contains( bucketName ) ) {
for ( PhoneAlbum album : phoneAlbums ) {
if ( album.getName().equals( bucketName ) ) {
album.getAlbumPhotos().add( phonePhoto );
Log.i( "DeviceImageManager", "A photo was added to album => " + bucketName );
break;
}
}
} else {
PhoneAlbum album = new PhoneAlbum();
Log.i( "DeviceImageManager", "A new album was created => " + bucketName );
album.setId( phonePhoto.getId() );
album.setName( bucketName );
album.setCoverUri( phonePhoto.getPhotoUri() );
album.getAlbumPhotos().add( phonePhoto );
Log.i( "DeviceImageManager", "A photo was added to album => " + bucketName );
phoneAlbums.add( album );
albumsNames.add( bucketName );
}
} while (cur.moveToNext());
}
cur.close();
listener.onComplete( phoneAlbums );
} else {
listener.onError();
}
}
Il ne vous reste plus qu'à rendre les images à l'écran. Dans mon cas, j'aime utiliser Picasso
. Voici comment je le fais:
Picasso.with( getActivity() )
.load( "file:" + mPhoneAlbums.get( i ).getCoverUri() )
.centerCrop()
.fit()
.placeholder( R.drawable.temp_image )
.into( mAlbumPreview );
N'oubliez pas d'ajouter une autorisation de lecture du stockage externe dans votre manifeste:
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE"/>
C'est ça. Tu es prêt! Bonne chance!
Téléchargez le code source d'ici ( Obtenez toutes les images de la galerie dans Android par programme )
activity_main.xml
<RelativeLayout Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#ffffff"
xmlns:Android="http://schemas.Android.com/apk/res/Android">
<GridView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:id="@+id/gv_folder"
Android:numColumns="2"
Android:layout_marginLeft="10dp"
Android:layout_marginRight="10dp"></GridView>
</RelativeLayout>
MainActivity.Java
package galleryimages.galleryimages;
import Android.Manifest;
import Android.content.Intent;
import Android.content.pm.PackageManager;
import Android.database.Cursor;
import Android.net.Uri;
import Android.provider.MediaStore;
import Android.support.v4.app.ActivityCompat;
import Android.support.v4.content.ContextCompat;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.AdapterView;
import Android.widget.GridView;
import Android.widget.Toast;
import Java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
public static ArrayList<Model_images> al_images = new ArrayList<>();
boolean boolean_folder;
Adapter_PhotosFolder obj_adapter;
GridView gv_folder;
private static final int REQUEST_PERMISSIONS = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gv_folder = (GridView)findViewById(R.id.gv_folder);
gv_folder.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getApplicationContext(), PhotosActivity.class);
intent.putExtra("value",i);
startActivity(intent);
}
});
if ((ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) && (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE))) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSIONS);
}
}else {
Log.e("Else","Else");
fn_imagespath();
}
}
public ArrayList<Model_images> fn_imagespath() {
al_images.clear();
int int_position = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
String absolutePathOfImage = null;
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
Log.e("Column", absolutePathOfImage);
Log.e("Folder", cursor.getString(column_index_folder_name));
for (int i = 0; i < al_images.size(); i++) {
if (al_images.get(i).getStr_folder().equals(cursor.getString(column_index_folder_name))) {
boolean_folder = true;
int_position = i;
break;
} else {
boolean_folder = false;
}
}
if (boolean_folder) {
ArrayList<String> al_path = new ArrayList<>();
al_path.addAll(al_images.get(int_position).getAl_imagepath());
al_path.add(absolutePathOfImage);
al_images.get(int_position).setAl_imagepath(al_path);
} else {
ArrayList<String> al_path = new ArrayList<>();
al_path.add(absolutePathOfImage);
Model_images obj_model = new Model_images();
obj_model.setStr_folder(cursor.getString(column_index_folder_name));
obj_model.setAl_imagepath(al_path);
al_images.add(obj_model);
}
}
for (int i = 0; i < al_images.size(); i++) {
Log.e("FOLDER", al_images.get(i).getStr_folder());
for (int j = 0; j < al_images.get(i).getAl_imagepath().size(); j++) {
Log.e("FILE", al_images.get(i).getAl_imagepath().get(j));
}
}
obj_adapter = new Adapter_PhotosFolder(getApplicationContext(),al_images);
gv_folder.setAdapter(obj_adapter);
return al_images;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_PERMISSIONS: {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults.length > 0 && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
fn_imagespath();
} else {
Toast.makeText(MainActivity.this, "The app was not allowed to read or write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
}
}
J'ai trouvé un moyen d'obtenir des albums sans itérer sur chaque photo.
String[] projection = new String[]{
"COUNT(*) as count",
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
"MAX (" + MediaStore.Images.ImageColumns.DATE_TAKEN + ") as max"};
Context context = ServiceProvider.getInstance().getApplicationContext();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
"1) GROUP BY (" + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
null,
"max DESC");
le curseur contiendra autant d'éléments, car il existe un nom de compartiment distinct, et vous pouvez également obtenir le nombre à l'intérieur de chaque position du curseur pour obtenir le nombre d'images à l'intérieur de l'album
ici exemple:
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//gets image path, it will always be a latest image because of sortOrdering by MAX date_taken
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
//gets count via alias ("as count" in projection)
int count = cursor.getInt(cursor.getColumnIndex("count"));
//do you logic here
...
} while (cursor.moveToNext());
}
cursor.close();
}
Quelques explications sur les paramètres de sélection:
contentResolver ajoute des parenthèses lors de la compilation de la requête résultante pour sqlLite, donc si nous faisons une sélection comme
"GROUP BY" + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
il sera compilé comme "WHERE (GROUP BY bucket_display_name)" et provoquera SQLiteException au moment de l'exécution. Sinon, si nous faisons une sélection comme
"1) GROUP BY (" + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
il sera compilé comme "WHERE (1) GROUP BY (bucket_display_name)", ce qui est correct