Reputation: 4816
I've created an app that allows the user to create a photo album(Folder) on External Storage. Now I am trying to retrieve the images from said directory and display them inside a GridView. I'm using an AsyncTask to iterate through the directory of files using listFiles() and then creating a bitmap once I grab each image, recycle it, and then use it again. My problem is that nothing is showing up in my GridView. I've set up a few Log breaks and LogCat shows me that the iteration does happen and the images are retrieved. This leads me to think that I made a mistake somewhere in my Adapter class that binds the bitmaps to the Grid, possibly in getView? Or maybe I'm wrong. Any help on what I'm doing wrong? I tried to comment the code as much as possible and I've left out the unecessary pieces. Thanks
public class AlbumGridView extends Activity implements OnItemClickListener {
private GridView sdcardImages;
private ImageAdapter imageAdapter;
private Display display;
private Bitmap bitmap;
private Bitmap b;
File[] imageList;
private static final String TAG = "AlbumGridView";
String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.album_view);
//display =
//((Object) getSystemService(Context.WINDOW_SERVICE))).getDefaultDisplay();
path = getIntent().getStringExtra("key");
Toast.makeText(this, path, Toast.LENGTH_SHORT).show();
setupViews();
setProgressBarIndeterminateVisibility(true);
loadImages();
}
protected void onDestroy() {
super.onDestroy();
final GridView grid = sdcardImages;
final int count = grid.getCount();
ImageView v = null;
for (int i = 0; i < count; i++) {
v = (ImageView) grid.getChildAt(i);
((BitmapDrawable) v.getDrawable()).setCallback(null);
}
}
// Set up the GridView
private void setupViews() {
sdcardImages = (GridView) findViewById(R.id.gvAlbumView);
// sdcardImages.setNumColumns(display.getWidth()/95);
sdcardImages.setClipToPadding(false);
sdcardImages.setOnItemClickListener(AlbumGridView.this);
imageAdapter = new ImageAdapter(getApplicationContext());
// imageAdapter.setImageList(path);
sdcardImages.setAdapter(imageAdapter);
}
private void addImage(LoadedImage... value) {
for (LoadedImage image : value) {
imageAdapter.addPhoto(image);
imageAdapter.notifyDataSetChanged();
}
}
// Save Bitmap images to a list and return that list
@Override
public Object onRetainNonConfigurationInstance() {
final GridView grid = sdcardImages;
final int count = grid.getChildCount();
final LoadedImage[] list = new LoadedImage[count];
for (int i = 0; i < count; i++) {
final ImageView v = (ImageView) grid.getChildAt(i);
list[i] = new LoadedImage(
((BitmapDrawable) v.getDrawable()).getBitmap());
}
return list;
}
private void loadImages() {
// TODO Auto-generated method stub
final Object data = getLastNonConfigurationInstance();
if (data == null) {
new LoadImagesFromSDCard().execute();
} else {
final LoadedImage[] photos = (LoadedImage[]) data;
if (photos.length == 0) {
new LoadImagesFromSDCard().execute();
}
for (LoadedImage photo : photos) {
addImage(photo);
}
}
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
}
/-------------------------------------------------------------------------------------/
//Adapter for the GridView
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
private String path;
private Bitmap bitmap;
public ImageAdapter(Context context) {
mContext = context;
}
public void addPhoto(LoadedImage photo) {
photos.add(photo);
}
public int getCount() {
return photos.size();
}
public Object getItem(int position) {
return photos.get(position);
}
public long getItemId(int position) {
return position;
}
/*
* public File[] setImageList(String path) {
*
* //this.path = path; //this.imageList = imageList; //File imagesDir =
* new File(path); //imageList = imagesDir.listFiles();
*
* File imagesDir = new File(path); imageList = imagesDir.listFiles();
* for (File image : imageList) try { bitmap =
* BitmapFactory.decodeStream(image.toURL().openStream()); //use bitmap
* and recycle afterwards LoadedImage lm = new LoadedImage(bitmap);
* this.addPhoto(lm); bitmap.recycle();
*
* } catch (IOException e) { e.printStackTrace(); } return imageList;
*
* }
*/
public View getView(int position, View convertView, ViewGroup parent) {
final ImageView imageView;
if (convertView == null) {
imageView = new ImageView(mContext);
} else {
imageView = (ImageView) convertView;
}
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(2, 2, 2, 2);
// imageView.setImageBitmap(photos.get(position).getBitmap());
try {
imageView
.setImageBitmap(BitmapFactory
.decodeStream(imageList[position].toURL()
.openStream()));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageView;
}
}
/*-------------------------------------------------------------------------*/
//AsyncTask to get the images
class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {
@Override
protected Object doInBackground(Object... arg0) {
// Load images from SD card in Background
// Display each image on the screen
File imagesDir = new File(path);
imageList = imagesDir.listFiles();
for (File image : imageList)
try {
if (bitmap != null) {
bitmap.recycle();
bitmap = null;
}
bitmap = BitmapFactory.decodeStream(image.toURL()
.openStream());
Log.e(TAG, "Grabbed Image " + image.getName());
// use bitmap then recycle after
LoadedImage lm = new LoadedImage(bitmap);
// addImage(lm);
// imageAdapter.addPhoto(lm);
// imageAdapter.setImageList(path);
// imageAdapter.addPhoto(lm);
// imageAdapter.setImageList(path);
// bitmap.recycle();
// addImage(lm);
// imageAdapter.addPhoto(lm);
Log.e(TAG, "Added Image " + lm.toString());
// imageAdapter.setImageList(path);
addImage(lm);
// bitmap.recycle();
// bitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Upvotes: 2
Views: 5848
Reputation: 4816
Here's the solution btw, sorry It took so long to I wasn't aware that others were waiting for the answer. Sorry. The relevant code is below.
This is AsyncTask that will query the device's MediaStore and retrieve all the photos. Note that this is retrieving the thumbnails and not the full size images, and more specifically it's the MICRO_KIND. There is also a Thumbnail.MINI_KIND as well.
/*----------------------------ASYNC TASK TO LOAD THE PHOTOS--------------------------------------------------------*/
public class LoadPhotos extends AsyncTask<Object, Object, Object> {
@Override
protected Object doInBackground(Object... params) {
try {
final String[] columns = { MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
null, null, orderBy);
int image_column_index = imagecursor
.getColumnIndex(MediaStore.Images.Media._ID);
AllPhotosActivity.count = imagecursor.getCount();
AllPhotosActivity.windows = new Bitmap[AllPhotosActivity.count];
for (int i = 0; i < AllPhotosActivity.count; i++) {
imagecursor.moveToPosition(i);
// i = index;
int id = imagecursor.getInt(image_column_index);
windows[i] = MediaStore.Images.Thumbnails.getThumbnail(
getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
}
imagecursor.close();
} catch (Exception e) {
e.printStackTrace();
Log.d("AllPhotosActivity",
"Error occured while fetching all photos on device.");
}
return null;
}
@Override
protected void onPostExecute(Object result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
public void run() {
pd.dismiss();
// imageAdapter.notifyDataSetChanged();
// sdcardImages.setAdapter(imageAdapter);
}
});
// pd.dismiss();
imagegrid.setAdapter(imageAdapter);
// pd.dismiss();
}
@Override
protected void onProgressUpdate(Object... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
}
Here's the adapter for the GridView that's going to bind your thumbnails to the gridview. My issue was simply in the getView method of my ImageAdapter, notice I'm setting my ImageView resources from different indexes of an array of Bitmaps I called windows.
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = (ImageView) convertView;
if (i != null) {
i.setImageBitmap(windows[position]);
} else {
i = new ImageView(mContext.getApplicationContext());
// i.setPadding(3, 3, 3, 3);
// i.setScaleType(ImageView.ScaleType.FIT_CENTER);
i.setAdjustViewBounds(true);
// i.setMaxHeight(200);
// i.setMaxWidth(200);
i.setPadding(3, 3, 3, 3);
i.setLayoutParams(new GridView.LayoutParams(92, 92));
i.setImageBitmap(windows[position]);
}
return i;
}
public int getCount() {
// TODO Auto-generated method stub
return count;
}
}
Upvotes: 1