在Android中,例如图库和音乐播放器,它们能够扫描我们的系统,获取到本地的相片跟音乐,这一点是如何做到的呢?
当我们往手机上放图片或者音乐的时候,会在手机内存中某个位置上的某个database中存放图片或者音乐的信息,而我们的应用程序是能够通过ContentResolver去读取到这些数据的。
下面可以先看一下database在哪,如下:
然后在data/data/下面呢,有很多provider提供的数据库,而我们的音乐或者图片就是在一个叫做Media的库下:
external是智能手机中内置的SD卡,而internal则是机身的内存。
这两个database里面的结构是一样的,我们把external给拉到本地电脑上,如下红色框框显示的,左边就是从手机SD卡拉到电脑,右边是从电脑推到手机SD卡上。
接下来可以利用SQLiteSpy之类的工具打开我们的数据库,可以看到Images 和 Audio 相关的表和视图:
比如图片,我们可以查看images这张表,其结构如下:
音乐,可以查看audio的视图,如下:
既然知道了这些表的数据结构,那么如何在我们的应用程序中去获取到这些数据呢?答案,当然就是利用ContentResolver了。
具体看代码,下面我写的一个MusicLoader,是为了获取本地音乐,其中利用了一些过滤条件,只拿出我想要的音乐。
- package com.example.nature;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Parcel;
- import android.os.Parcelable;
- import android.provider.MediaStore.Audio.Media;
- import android.util.Log;
- public class MusicLoader {
- private static final String TAG = "com.example.nature.MusicLoader";
- private static List<MusicInfo> musicList = new ArrayList<MusicInfo>();
- private static MusicLoader musicLoader;
- private static ContentResolver contentResolver;
- //Uri,指向external的database
- private Uri contentUri = Media.EXTERNAL_CONTENT_URI;
- //projection:选择的列; where:过滤条件; sortOrder:排序。
- private String[] projection = {
- Media._ID,
- Media.DISPLAY_NAME,
- Media.DATA,
- Media.ALBUM,
- Media.ARTIST,
- Media.DURATION,
- Media.SIZE
- };
- private String where = "mime_type in (\'audio/mpeg\',\'audio/x-ms-wma\') and bucket_display_name <> \'audio\' and is_music > 0 " ;
- private String sortOrder = Media.DATA;
- public static MusicLoader instance(ContentResolver pContentResolver){
- if(musicLoader == null){
- contentResolver = pContentResolver;
- musicLoader = new MusicLoader();
- }
- return musicLoader;
- }
- private MusicLoader(){ //利用ContentResolver的query函数来查询数据,然后将得到的结果放到MusicInfo对象中,最后放到数组中
- Cursor cursor = contentResolver.query(contentUri, projection, where, null, sortOrder);
- if(cursor == null){
- Log.v(TAG,"Line(37 ) Music Loader cursor == null.");
- }else if(!cursor.moveToFirst()){
- Log.v(TAG,"Line(39 ) Music Loader cursor.moveToFirst() returns false.");
- }else{
- int displayNameCol = cursor.getColumnIndex(Media.DISPLAY_NAME);
- int albumCol = cursor.getColumnIndex(Media.ALBUM);
- int idCol = cursor.getColumnIndex(Media._ID);
- int durationCol = cursor.getColumnIndex(Media.DURATION);
- int sizeCol = cursor.getColumnIndex(Media.SIZE);
- int artistCol = cursor.getColumnIndex(Media.ARTIST);
- int urlCol = cursor.getColumnIndex(Media.DATA);
- do{
- String title = cursor.getString(displayNameCol);
- String album = cursor.getString(albumCol);
- long id = cursor.getLong(idCol);
- int duration = cursor.getInt(durationCol);
- long size = cursor.getLong(sizeCol);
- String artist = cursor.getString(artistCol);
- String url = cursor.getString(urlCol);
- MusicInfo musicInfo = new MusicInfo(id, title);
- musicInfo.setAlbum(album);
- musicInfo.setDuration(duration);
- musicInfo.setSize(size);
- musicInfo.setArtist(artist);
- musicInfo.setUrl(url);
- musicList.add(musicInfo);
- }while(cursor.moveToNext());
- }
- }
- public List<MusicInfo> getMusicList(){
- return musicList;
- }
- public Uri getMusicUriById(long id){
- Uri uri = ContentUris.withAppendedId(contentUri, id);
- return uri;
- }
- //下面是自定义的一个MusicInfo子类,实现了Parcelable,为的是可以将整个MusicInfo的ArrayList在Activity和Service中传送,=_=!!,但其实不用
- static class MusicInfo implements Parcelable{
- private long id;
- private String title;
- private String album;
- private int duration;
- private long size;
- private String artist;
- private String url;
- public MusicInfo(){
- }
- public MusicInfo(long pId, String pTitle){
- id = pId;
- title = pTitle;
- }
- public String getArtist() {
- return artist;
- }
- public void setArtist(String artist) {
- this.artist = artist;
- }
- public long getSize() {
- return size;
- }
- public void setSize(long size) {
- this.size = size;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getAlbum() {
- return album;
- }
- public void setAlbum(String album) {
- this.album = album;
- }
- public int getDuration() {
- return duration;
- }
- public void setDuration(int duration) {
- this.duration = duration;
- }
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeString(title);
- dest.writeString(album);
- dest.writeString(artist);
- dest.writeString(url);
- dest.writeInt(duration);
- dest.writeLong(size);
- }
- public static final Parcelable.Creator<MusicInfo>
- CREATOR = new Creator<MusicLoader.MusicInfo>() {
- @Override
- public MusicInfo[] newArray(int size) {
- return new MusicInfo[size];
- }
- @Override
- public MusicInfo createFromParcel(Parcel source) {
- MusicInfo musicInfo = new MusicInfo();
- musicInfo.setId(source.readLong());
- musicInfo.setTitle(source.readString());
- musicInfo.setAlbum(source.readString());
- musicInfo.setArtist(source.readString());
- musicInfo.setUrl(source.readString());
- musicInfo.setDuration(source.readInt());
- musicInfo.setSize(source.readLong());
- return musicInfo;
- }
- };
- }
- }
- package com.example.nature;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Parcel;
- import android.os.Parcelable;
- import android.provider.MediaStore.Audio.Media;
- import android.util.Log;
- public class MusicLoader {
- private static final String TAG = "com.example.nature.MusicLoader";
- private static List<MusicInfo> musicList = new ArrayList<MusicInfo>();
- private static MusicLoader musicLoader;
- private static ContentResolver contentResolver;
- //Uri,指向external的database
- private Uri contentUri = Media.EXTERNAL_CONTENT_URI;
- //projection:选择的列; where:过滤条件; sortOrder:排序。
- private String[] projection = {
- Media._ID,
- Media.DISPLAY_NAME,
- Media.DATA,
- Media.ALBUM,
- Media.ARTIST,
- Media.DURATION,
- Media.SIZE
- };
- private String where = "mime_type in (\'audio/mpeg\',\'audio/x-ms-wma\') and bucket_display_name <> \'audio\' and is_music > 0 " ;
- private String sortOrder = Media.DATA;
- public static MusicLoader instance(ContentResolver pContentResolver){
- if(musicLoader == null){
- contentResolver = pContentResolver;
- musicLoader = new MusicLoader();
- }
- return musicLoader;
- }
- private MusicLoader(){ //利用ContentResolver的query函数来查询数据,然后将得到的结果放到MusicInfo对象中,最后放到数组中
- Cursor cursor = contentResolver.query(contentUri, projection, where, null, sortOrder);
- if(cursor == null){
- Log.v(TAG,"Line(37 ) Music Loader cursor == null.");
- }else if(!cursor.moveToFirst()){
- Log.v(TAG,"Line(39 ) Music Loader cursor.moveToFirst() returns false.");
- }else{
- int displayNameCol = cursor.getColumnIndex(Media.DISPLAY_NAME);
- int albumCol = cursor.getColumnIndex(Media.ALBUM);
- int idCol = cursor.getColumnIndex(Media._ID);
- int durationCol = cursor.getColumnIndex(Media.DURATION);
- int sizeCol = cursor.getColumnIndex(Media.SIZE);
- int artistCol = cursor.getColumnIndex(Media.ARTIST);
- int urlCol = cursor.getColumnIndex(Media.DATA);
- do{
- String title = cursor.getString(displayNameCol);
- String album = cursor.getString(albumCol);
- long id = cursor.getLong(idCol);
- int duration = cursor.getInt(durationCol);
- long size = cursor.getLong(sizeCol);
- String artist = cursor.getString(artistCol);
- String url = cursor.getString(urlCol);
- MusicInfo musicInfo = new MusicInfo(id, title);
- musicInfo.setAlbum(album);
- musicInfo.setDuration(duration);
- musicInfo.setSize(size);
- musicInfo.setArtist(artist);
- musicInfo.setUrl(url);
- musicList.add(musicInfo);
- }while(cursor.moveToNext());
- }
- }
- public List<MusicInfo> getMusicList(){
- return musicList;
- }
- public Uri getMusicUriById(long id){
- Uri uri = ContentUris.withAppendedId(contentUri, id);
- return uri;
- }
- //下面是自定义的一个MusicInfo子类,实现了Parcelable,为的是可以将整个MusicInfo的ArrayList在Activity和Service中传送,=_=!!,但其实不用
- static class MusicInfo implements Parcelable{
- private long id;
- private String title;
- private String album;
- private int duration;
- private long size;
- private String artist;
- private String url;
- public MusicInfo(){
- }
- public MusicInfo(long pId, String pTitle){
- id = pId;
- title = pTitle;
- }
- public String getArtist() {
- return artist;
- }
- public void setArtist(String artist) {
- this.artist = artist;
- }
- public long getSize() {
- return size;
- }
- public void setSize(long size) {
- this.size = size;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getAlbum() {
- return album;
- }
- public void setAlbum(String album) {
- this.album = album;
- }
- public int getDuration() {
- return duration;
- }
- public void setDuration(int duration) {
- this.duration = duration;
- }
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeString(title);
- dest.writeString(album);
- dest.writeString(artist);
- dest.writeString(url);
- dest.writeInt(duration);
- dest.writeLong(size);
- }
- public static final Parcelable.Creator<MusicInfo>
- CREATOR = new Creator<MusicLoader.MusicInfo>() {
- @Override
- public MusicInfo[] newArray(int size) {
- return new MusicInfo[size];
- }
- @Override
- public MusicInfo createFromParcel(Parcel source) {
- MusicInfo musicInfo = new MusicInfo();
- musicInfo.setId(source.readLong());
- musicInfo.setTitle(source.readString());
- musicInfo.setAlbum(source.readString());
- musicInfo.setArtist(source.readString());
- musicInfo.setUrl(source.readString());
- musicInfo.setDuration(source.readInt());
- musicInfo.setSize(source.readLong());
- return musicInfo;
- }
- };
- }
- }
package com.example.nature; import java.util.ArrayList; import java.util.List; import android.content.ContentResolver; import android.content.ContentUris; import android.database.Cursor; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.provider.MediaStore.Audio.Media; import android.util.Log; public class MusicLoader { private static final String TAG = "com.example.nature.MusicLoader"; private static List<MusicInfo> musicList = new ArrayList<MusicInfo>(); private static MusicLoader musicLoader; private static ContentResolver contentResolver; //Uri,指向external的database private Uri contentUri = Media.EXTERNAL_CONTENT_URI; //projection:选择的列; where:过滤条件; sortOrder:排序。 private String[] projection = { Media._ID, Media.DISPLAY_NAME, Media.DATA, Media.ALBUM, Media.ARTIST, Media.DURATION, Media.SIZE }; private String where = "mime_type in (\'audio/mpeg\',\'audio/x-ms-wma\') and bucket_display_name <> \'audio\' and is_music > 0 " ; private String sortOrder = Media.DATA; public static MusicLoader instance(ContentResolver pContentResolver){ if(musicLoader == null){ contentResolver = pContentResolver; musicLoader = new MusicLoader(); } return musicLoader; } private MusicLoader(){ //利用ContentResolver的query函数来查询数据,然后将得到的结果放到MusicInfo对象中,最后放到数组中 Cursor cursor = contentResolver.query(contentUri, projection, where, null, sortOrder); if(cursor == null){ Log.v(TAG,"Line(37 ) Music Loader cursor == null."); }else if(!cursor.moveToFirst()){ Log.v(TAG,"Line(39 ) Music Loader cursor.moveToFirst() returns false."); }else{ int displayNameCol = cursor.getColumnIndex(Media.DISPLAY_NAME); int albumCol = cursor.getColumnIndex(Media.ALBUM); int idCol = cursor.getColumnIndex(Media._ID); int durationCol = cursor.getColumnIndex(Media.DURATION); int sizeCol = cursor.getColumnIndex(Media.SIZE); int artistCol = cursor.getColumnIndex(Media.ARTIST); int urlCol = cursor.getColumnIndex(Media.DATA); do{ String title = cursor.getString(displayNameCol); String album = cursor.getString(albumCol); long id = cursor.getLong(idCol); int duration = cursor.getInt(durationCol); long size = cursor.getLong(sizeCol); String artist = cursor.getString(artistCol); String url = cursor.getString(urlCol); MusicInfo musicInfo = new MusicInfo(id, title); musicInfo.setAlbum(album); musicInfo.setDuration(duration); musicInfo.setSize(size); musicInfo.setArtist(artist); musicInfo.setUrl(url); musicList.add(musicInfo); }while(cursor.moveToNext()); } } public List<MusicInfo> getMusicList(){ return musicList; } public Uri getMusicUriById(long id){ Uri uri = ContentUris.withAppendedId(contentUri, id); return uri; } //下面是自定义的一个MusicInfo子类,实现了Parcelable,为的是可以将整个MusicInfo的ArrayList在Activity和Service中传送,=_=!!,但其实不用 static class MusicInfo implements Parcelable{ private long id; private String title; private String album; private int duration; private long size; private String artist; private String url; public MusicInfo(){ } public MusicInfo(long pId, String pTitle){ id = pId; title = pTitle; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAlbum() { return album; } public void setAlbum(String album) { this.album = album; } public int getDuration() { return duration; } public void setDuration(int duration) { this.duration = duration; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); dest.writeString(title); dest.writeString(album); dest.writeString(artist); dest.writeString(url); dest.writeInt(duration); dest.writeLong(size); } public static final Parcelable.Creator<MusicInfo> CREATOR = new Creator<MusicLoader.MusicInfo>() { @Override public MusicInfo[] newArray(int size) { return new MusicInfo[size]; } @Override public MusicInfo createFromParcel(Parcel source) { MusicInfo musicInfo = new MusicInfo(); musicInfo.setId(source.readLong()); musicInfo.setTitle(source.readString()); musicInfo.setAlbum(source.readString()); musicInfo.setArtist(source.readString()); musicInfo.setUrl(source.readString()); musicInfo.setDuration(source.readInt()); musicInfo.setSize(source.readLong()); return musicInfo; } }; } }
最后,我们就可以在我们的手机上看到我们音乐了,不过数据库中有些是乱码的,我还不知道怎么解决。。。
图片的获取也是相类似的,放上代码,具体的自行琢磨:
- package com.example.hmgallery;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentResolver;
- import android.database.Cursor;
- import android.provider.MediaStore.Images.Media;
- import android.provider.MediaStore.Images.Thumbnails;
- import android.util.SparseArray;
- public class Images{
- public static final String IMAGE_PATH = "IMAGE_PATH";
- public static final String IMAGE_ID = "IMAGE_ID";
- public static final String IMAGE_POSITION = "IMAGE_POSITION";
- public static final String IMAGE_COUNTS = "IMAGE_COUNTS";
- private static List<ImageItem> imageItems = new ArrayList<ImageItem>();
- private static SparseArray<ImageItem> tempArray;
- public static void loadImages(ContentResolver contentResolver){
- tempArray = new SparseArray<ImageItem>();
- String[] projection = {Media._ID,Media.DATA,Media.ORIENTATION};
- String where = Media.BUCKET_DISPLAY_NAME + " = \'Camera\'";
- String sortOrder = Media._ID + " desc";
- StringBuilder inImageIds = new StringBuilder(Thumbnails.IMAGE_ID);
- inImageIds.append(" in ( ");
- Cursor cursor = contentResolver.query(Media.EXTERNAL_CONTENT_URI, projection, where, null, sortOrder);
- if(cursor.moveToFirst()){
- do {
- int imageId = cursor.getInt(cursor.getColumnIndex(Media._ID));
- String imagePath = cursor.getString(cursor.getColumnIndex(Media.DATA));
- int orientation = cursor.getInt(cursor.getColumnIndex(Media.ORIENTATION));
- ImageItem imageItem = new ImageItem(imageId,imagePath,orientation);
- imageItems.add(imageItem);
- tempArray.put(imageId, imageItem);
- inImageIds.append(imageId).append(",");
- }while(cursor.moveToNext());
- }
- inImageIds.deleteCharAt(inImageIds.length() - 1);
- inImageIds.append(" ) ");
- String[] thumbnailProjection = {Thumbnails.DATA,Thumbnails.IMAGE_ID};
- cursor = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, thumbnailProjection, inImageIds.toString(), null, null);
- if(cursor.moveToFirst()){
- do {
- int imageId = cursor.getInt(cursor.getColumnIndex(Thumbnails.IMAGE_ID));
- String thumnbailPath = cursor.getString(cursor.getColumnIndex(Media.DATA));
- ImageItem imageItem = tempArray.get(imageId);
- if(imageItem != null){
- imageItem.setThumbnailPath(thumnbailPath);
- }
- }while(cursor.moveToNext());
- }
- tempArray = null;
- }
- public static ImageItem[] getImageItems(){
- return imageItems.toArray(new ImageItem[]{});
- }
- }
- package com.example.hmgallery;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentResolver;
- import android.database.Cursor;
- import android.provider.MediaStore.Images.Media;
- import android.provider.MediaStore.Images.Thumbnails;
- import android.util.SparseArray;
- public class Images{
- public static final String IMAGE_PATH = "IMAGE_PATH";
- public static final String IMAGE_ID = "IMAGE_ID";
- public static final String IMAGE_POSITION = "IMAGE_POSITION";
- public static final String IMAGE_COUNTS = "IMAGE_COUNTS";
- private static List<ImageItem> imageItems = new ArrayList<ImageItem>();
- private static SparseArray<ImageItem> tempArray;
- public static void loadImages(ContentResolver contentResolver){
- tempArray = new SparseArray<ImageItem>();
- String[] projection = {Media._ID,Media.DATA,Media.ORIENTATION};
- String where = Media.BUCKET_DISPLAY_NAME + " = \'Camera\'";
- String sortOrder = Media._ID + " desc";
- StringBuilder inImageIds = new StringBuilder(Thumbnails.IMAGE_ID);
- inImageIds.append(" in ( ");
- Cursor cursor = contentResolver.query(Media.EXTERNAL_CONTENT_URI, projection, where, null, sortOrder);
- if(cursor.moveToFirst()){
- do {
- int imageId = cursor.getInt(cursor.getColumnIndex(Media._ID));
- String imagePath = cursor.getString(cursor.getColumnIndex(Media.DATA));
- int orientation = cursor.getInt(cursor.getColumnIndex(Media.ORIENTATION));
- ImageItem imageItem = new ImageItem(imageId,imagePath,orientation);
- imageItems.add(imageItem);
- tempArray.put(imageId, imageItem);
- inImageIds.append(imageId).append(",");
- }while(cursor.moveToNext());
- }
- inImageIds.deleteCharAt(inImageIds.length() - 1);
- inImageIds.append(" ) ");
- String[] thumbnailProjection = {Thumbnails.DATA,Thumbnails.IMAGE_ID};
- cursor = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, thumbnailProjection, inImageIds.toString(), null, null);
- if(cursor.moveToFirst()){
- do {
- int imageId = cursor.getInt(cursor.getColumnIndex(Thumbnails.IMAGE_ID));
- String thumnbailPath = cursor.getString(cursor.getColumnIndex(Media.DATA));
- ImageItem imageItem = tempArray.get(imageId);
- if(imageItem != null){
- imageItem.setThumbnailPath(thumnbailPath);
- }
- }while(cursor.moveToNext());
- }
- tempArray = null;
- }
- public static ImageItem[] getImageItems(){
- return imageItems.toArray(new ImageItem[]{});
- }
- }
package com.example.hmgallery; import java.util.ArrayList; import java.util.List; import android.content.ContentResolver; import android.database.Cursor; import android.provider.MediaStore.Images.Media; import android.provider.MediaStore.Images.Thumbnails; import android.util.SparseArray; public class Images{ public static final String IMAGE_PATH = "IMAGE_PATH"; public static final String IMAGE_ID = "IMAGE_ID"; public static final String IMAGE_POSITION = "IMAGE_POSITION"; public static final String IMAGE_COUNTS = "IMAGE_COUNTS"; private static List<ImageItem> imageItems = new ArrayList<ImageItem>(); private static SparseArray<ImageItem> tempArray; public static void loadImages(ContentResolver contentResolver){ tempArray = new SparseArray<ImageItem>(); String[] projection = {Media._ID,Media.DATA,Media.ORIENTATION}; String where = Media.BUCKET_DISPLAY_NAME + " = \'Camera\'"; String sortOrder = Media._ID + " desc"; StringBuilder inImageIds = new StringBuilder(Thumbnails.IMAGE_ID); inImageIds.append(" in ( "); Cursor cursor = contentResolver.query(Media.EXTERNAL_CONTENT_URI, projection, where, null, sortOrder); if(cursor.moveToFirst()){ do { int imageId = cursor.getInt(cursor.getColumnIndex(Media._ID)); String imagePath = cursor.getString(cursor.getColumnIndex(Media.DATA)); int orientation = cursor.getInt(cursor.getColumnIndex(Media.ORIENTATION)); ImageItem imageItem = new ImageItem(imageId,imagePath,orientation); imageItems.add(imageItem); tempArray.put(imageId, imageItem); inImageIds.append(imageId).append(","); }while(cursor.moveToNext()); } inImageIds.deleteCharAt(inImageIds.length() - 1); inImageIds.append(" ) "); String[] thumbnailProjection = {Thumbnails.DATA,Thumbnails.IMAGE_ID}; cursor = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, thumbnailProjection, inImageIds.toString(), null, null); if(cursor.moveToFirst()){ do { int imageId = cursor.getInt(cursor.getColumnIndex(Thumbnails.IMAGE_ID)); String thumnbailPath = cursor.getString(cursor.getColumnIndex(Media.DATA)); ImageItem imageItem = tempArray.get(imageId); if(imageItem != null){ imageItem.setThumbnailPath(thumnbailPath); } }while(cursor.moveToNext()); } tempArray = null; } public static ImageItem[] getImageItems(){ return imageItems.toArray(new ImageItem[]{}); } }