探しているのは:既存のフォトギャラリー名のリスト(できればトップサムネイルも)ギャラリーのコンテンツ(必要に応じてサムネイルとフルサイズを読み込むことができる)
「ギャラリー」のリストを取得するにはどうすればいいですか(Androidの適切な用語であるかどうかわからない)...)コンテンツ?既存のギャラリーディスプレイを使用せずに、その構造内のギャラリーにアクセスする必要があります(フォトリクエスターへのオーバーレイヤーではなく、まったく新しいギャラリーを作成しています)。
MediaStore.Imagesは私がいる必要がある場所だと思いますが、グループ化を提供するものは表示されません...
グループはMediaStore.Images.Media.BUCKET_DISPLAY_NAME
で定義されます。以下に、画像をリストし、バケット名と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;
}
ここにいくつかの簡単なステップでの完全なソリューションがあります:
次のいくつかの手順では、特定のデバイスで見つかったアルバムを保持するVector
を作成する方法を説明します。すべてのアルバムにはプレビュー画像と、アルバムのすべての画像を保持する内部Vector
が保持されます。
ストレージから抽出された画像を保持するオブジェクトを作成します。 PhoneAlbum
と呼びます。これがどのように見えるかです:
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;
}
}
アルバム内の画像を保持するオブジェクトを作成します: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;
}
}
完了時に抽出された画像を処理するインターフェイスを作成します。 OnPhoneImagesObtained
と呼びます。ここにあります:
public interface OnPhoneImagesObtained {
void onComplete( Vector<PhoneAlbum> albums );
void onError();
}
新しいクラスを作成します:DeviceImageManager
public class DeviceImageManager {
}
DeviceImageManager
を作成したら、次のメソッドを追加します。
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();
}
}
あとは、画像を画面にレンダリングするだけです。私の場合、Picasso
を使用します。ここに私がそれをする方法があります:
Picasso.with( getActivity() )
.load( "file:" + mPhoneAlbums.get( i ).getCoverUri() )
.centerCrop()
.fit()
.placeholder( R.drawable.temp_image )
.into( mAlbumPreview );
マニフェストに外部ストレージを読み取る許可を追加することを忘れないでください:
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE"/>
それでおしまい。準備できた!幸運を!
ここからソースコードをダウンロードします( ギャラリーからすべての画像をAndroidプログラムで取得 )
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();
}
}
}
}
}
}
すべての写真を繰り返し処理せずにアルバムを取得する方法を見つけました。
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");
カーソルには個別のバケット名と同じ数の要素が含まれます。また、カーソル位置ごとにカウントを取得して、アルバム内の画像のカウントを取得できます。
ここに例:
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();
}
選択パラメーターに関する説明:
contentResolverは、sqlLiteの結果クエリをコンパイルするときに括弧を追加します。
「GROUP BY」+ MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
「WHERE(GROUP BY bucket_display_name)」としてコンパイルされ、実行時にSQLiteExceptionが発生します。それ以外の場合、次のように選択すると
"1)GROUP BY(" + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME
「WHERE(1)GROUP BY(bucket_display_name)」としてコンパイルされますが、これは正しいです