Get list of photo galleries on Android
I'm looking for: A list of the existing photo gallery names (hopefully their top thumbnail as wel开发者_如何学Cl) The contents of the gallery (I can then load thumbnails and full size as needed)
How would I go about getting a list of the "Galleries" (don't know if that's the proper term in android for the groupings of images visible in the Gallery app...) and their contents? I need access to the gallery in it's structure without using the existing gallery display (I'm creating a totally new one, not an over layer to the photo requestor etc.)
I assume MediaStore.Images is where I need to be but I don't see anything that will give me the groupings...
Groupings are defined by MediaStore.Images.Media.BUCKET_DISPLAY_NAME
. Here is the sample code to list the images and log their bucket name and 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;
}
Here is the full solution in few simple steps:
The next few steps will guid you how to create a Vector
that will hold the albums found on a given device. Every Album will hold a preview image as well an inner Vector
that will hold all the images of the Album.
Create an object that will hold the images once extracted from storage. We are going to call it
PhoneAlbum
. This is how it's going to look: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; } }
Create an object that will hold the images within the album called:
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; } }
Create an interface to handle the extracted images upon completion. We are going to call it
OnPhoneImagesObtained
. Here it is:public interface OnPhoneImagesObtained { void onComplete( Vector<PhoneAlbum> albums ); void onError(); }
Create a new class:
DeviceImageManager
public class DeviceImageManager { }
Once you created
DeviceImageManager
, add the following method: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(); } }
Now all you have left is to render the images to screen. In my case I like to use
Picasso
. Here is how I do it:Picasso.with( getActivity() ) .load( "file:" + mPhoneAlbums.get( i ).getCoverUri() ) .centerCrop() .fit() .placeholder( R.drawable.temp_image ) .into( mAlbumPreview );
Don't forget to add a permission to read external storage in your manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
That's it. You are good to go! Good luck!
I've found a way to get albums without iterating over every 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");
cursor will contain as much elements, as distinct bucket name exists, and also you can get count inside every cursor position to get count of images inside album
here example:
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();
}
Some explanation about selection param:
contentResolver adds parentheses when compiling resulting query for sqlLite, so if we make selection like
"GROUP BY " + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
it will be compiled as "WHERE (GROUP BY bucket_display_name)" and will cause SQLiteException at runtime. Otherwise if we make selection like
"1) GROUP BY (" + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
it will be compiled as "WHERE (1) GROUP BY (bucket_display_name)", which is correct
Download the source code from here (Get all images from gallery in android programmatically)
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();
}
}
}
}
}
}
精彩评论