I want to retrieve all the images from gallery from its database and want to display in my application in gridview.
please tell how to do it..
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemLongClickListener;
/**
* Class will Display all gallery images in grid view This class has the
* functionality to move images from public gallery to Private
*
*/
public class AndroidGallery extends Activity implements OnItemLongClickListener {
private GridView sdcardImages;
private ImageAdapter imageAdapter;
private String TAG = this.getClass().getSimpleName();
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
private String thumb_Image_Path;
private String crypto = null;
private FileInputStream is = null;
private BufferedInputStream bis = null;
private Bitmap bitmap;
private ByteArrayOutputStream bytes;
private File galleryThumbFile, galleryImageFile,galleryThumbFolder, galleryImageFolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sdcard);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
photos.clear(); // If photos array list has any previous value then clear it
setViews(); // set views
setProgressBarIndeterminateVisibility(true);
sdcardImages.setAdapter(imageAdapter); // Fill adapter
loadImages(); // Load images from default gallery
}
/**
* Free up bitmap related resources.
*/
protected void onDestroy() {
super.onDestroy();
final GridView grid = sdcardImages;
final int count = grid.getChildCount();
ImageView v = null;
for (int i = 0; i < count; i++) {
v = (ImageView) grid.getChildAt(i);
((BitmapDrawable) v.getDrawable()).setCallback(null);
}
}
/**
* Load images...
*/
private void loadImages() {
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);
}
}
}
/**
* Load images from SD Card in the background, and display each image on the
* screen.
*
* #see android.os.AsyncTask#doInBackground(Params[])
*/
private class LoadImagesFromSDCard extends
AsyncTask<Object, LoadedImage, Object> {
#Override
protected Object doInBackground(Object... params) {
Uri uri = null;
Bitmap bitmap = null;
Bitmap newBitmap = null;
String[] projection = {MediaStore.Images.Thumbnails._ID};
Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
null);
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
int size = cursor.getCount();
int imageID = 0;
for (int i = 0; i < size; i++) {
cursor.moveToPosition(i);
imageID = cursor.getInt(columnIndex);
uri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID);
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
if (bitmap != null) {
newBitmap = Bitmap.createScaledBitmap(bitmap, 70, 70, true);
bitmap.recycle();
if (newBitmap != null) {
publishProgress(new LoadedImage(newBitmap,String.valueOf(imageID)));
}
}
} catch (IOException e) {
//Error fetching image, try to recover
Log.e(TAG, e.toString());
}
}
return null;
}
/**
* Add a new LoadedImage in the images grid.
*
* #param value
* The image.
*/
#Override
public void onProgressUpdate(LoadedImage... value) {
addImage(value);
}
/**
* Set the visibility of the progress bar to false.
*
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(Object result) {
setProgressBarIndeterminateVisibility(false);
}
}
/**
* Add image(s) to the grid view adapter.
*
* #param value
* Array of LoadedImages references
*/
private void addImage(LoadedImage... value) {
for (LoadedImage image : value) {
imageAdapter.addPhoto(image);
imageAdapter.notifyDataSetChanged();
}
}
/**
* Set view function will set views
*
*/
private void setViews() {
sdcardImages = (GridView) findViewById(R.id.sdcard);
sdcardImages.setOnItemLongClickListener(this); // Set Listener on GridView
imageAdapter = new ImageAdapter(getApplicationContext());
imageAdapter.notifyDataSetChanged();
}
/**
* Function will return bitmap of Gallery big image
* #param imagePath
* #return
*/
private Bitmap getImageBitmap(String imagePath) {
// TODO Auto-generated method stub
try {
is = new FileInputStream(new File(imagePath));
bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);
} catch (Exception e) {
// Try to recover
} finally {
try {
if (bis != null) {
bis.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
}
}
System.gc();
return bitmap;
}
/**
* Function will return thumb image of selected from gallery
* #param thumbImagePath
* #return
*/
private Bitmap getThumbnailBitmap(String thumbImagePath) {
try {
is = new FileInputStream(new File(thumbImagePath));
bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);
} catch (Exception e) {
// Try to recover
} finally {
try {
if (bis != null) {
bis.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
}
}
System.gc();
return bitmap;
}
}
/**
* This class is used for image adapter
* #author
*
*/
class ImageAdapter extends BaseAdapter {
private Context mContext;
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 View getView(int position, View convertView, ViewGroup parent) {
final ImageView imageView;
if (convertView == null) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(90, 90));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageBitmap(photos.get(position).getImage());
return imageView;
}
}
}
layout:
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sdcard"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:stretchMode="columnWidth"
android:gravity="center" android:layout_below="#id/RelativeWallTopBar"
android:numColumns="auto_fit" android:columnWidth="90dp"
android:horizontalSpacing="5dip" android:verticalSpacing="15dip" />
Here I have taken main.xml, that contain one button and one Imageview. When I press the button images is displayed from the gallery and when I click on the image then it displayed in the imageview.
main.java
public class GalleryImagePickActivity extends Activity {
/** Called when the activity is first created. */
private static final int SELECT_PICTURE = 1;
ImageView imgBG;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgBG = (ImageView) findViewById(R.id.imgBG);
}
public void btnChooseBGClick(View v) {
Intent i = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, SELECT_PICTURE);
}
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case SELECT_PICTURE:
if (resultCode == RESULT_OK) {
Uri uri = imageReturnedIntent.getData();
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection,
null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
Drawable d = new BitmapDrawable(yourSelectedImage);
imgBG.setBackgroundDrawable(d);
}
}
}
}
I hope it helps you.
Related
Recently I tried to write an app which captures frame buffer from say USB camera (that need to be displayed as preview), and image processed output that need to be overlapped on the preview. Can anybody give me some pointers how to start? Moreover I need to draw some rectangle on the preview.
I was trying to use multiple SurfaceView to draw but not succeeded. Can anybody help me out?
What you need it the bitmap and image view reference counting. Android keeps image data in native array, which is not recycling automatically when the vm GC running. Vm part is garbage collected one way and the native part is another way and much later. You app may run out of memory pretty quickly.
Here is set of classes that can help. I think I've got them from android image tutorial and modified a bit for my own convenience.
package com.example.android.streaming.ui.cache;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* Sub-class of ImageView which automatically notifies the drawable when it is
* being displayed.
*/
public class RecyclingImageView extends ImageView {
public RecyclingImageView(Context context) {
super(context);
}
public RecyclingImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* #see android.widget.ImageView#onDetachedFromWindow()
*/
#Override
protected void onDetachedFromWindow() {
// This has been detached from Window, so clear the drawable
setImageDrawable(null);
super.onDetachedFromWindow();
}
/**
* #see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
*/
#Override
public void setImageDrawable(Drawable drawable) {
// Keep hold of previous Drawable
final Drawable previousDrawable = getDrawable();
// Call super to set new Drawable
super.setImageDrawable(drawable);
// Notify new Drawable that it is being displayed
notifyDrawable(drawable, true);
// Notify old Drawable so it is no longer being displayed
notifyDrawable(previousDrawable, false);
}
#Override
public void setImageResource(int resId) {
// Keep hold of previous Drawable
final Drawable previousDrawable = getDrawable();
super.setImageResource(resId);
// Notify new Drawable that it is being displayed
final Drawable newDrawable = getDrawable();
notifyDrawable(newDrawable, true);
// Notify old Drawable so it is no longer being displayed
notifyDrawable(previousDrawable, false);
}
/**
* Notifies the drawable that it's displayed state has changed.
*
* #param drawable
* #param isDisplayed
*/
private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
if (drawable != null) {
if (drawable instanceof RecyclingBitmapDrawable) {
// The drawable is a CountingBitmapDrawable, so notify it
((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
} else if (drawable instanceof LayerDrawable) {
// The drawable is a LayerDrawable, so recurse on each layer
LayerDrawable layerDrawable = (LayerDrawable) drawable;
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
}
}
}
}
}
And here is another one, a bitmap itself.
package com.example.android.streaming.ui.cache;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import com.example.android.streaming.StreamingApp;
import com.vg.hangwith.BuildConfig;
/**
* A BitmapDrawable that keeps track of whether it is being displayed or cached.
* When the drawable is no longer being displayed or cached,
* {#link Bitmap#recycle() recycle()} will be called on this drawable's bitmap.
*/
public class RecyclingBitmapDrawable extends BitmapDrawable {
private int cacheRefCount = 0;
private int displayRefCount = 0;
private boolean hasBeenDisplayed;
public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
super(res, bitmap);
}
/**
* Notify the drawable that the displayed state has changed. Internally a
* count is kept so that the drawable knows when it is no longer being
* displayed.
*
* #param isDisplayed
* - Whether the drawable is being displayed or not
*/
public void setIsDisplayed(boolean isDisplayed) {
synchronized (this) {
if (isDisplayed) {
displayRefCount++;
hasBeenDisplayed = true;
} else {
displayRefCount--;
}
}
// Check to see if recycle() can be called
checkState();
}
/**
* Notify the drawable that the cache state has changed. Internally a count
* is kept so that the drawable knows when it is no longer being cached.
*
* #param isCached
* - Whether the drawable is being cached or not
*/
public void setIsCached(boolean isCached) {
synchronized (this) {
if (isCached) {
cacheRefCount++;
} else {
cacheRefCount--;
}
}
// Check to see if recycle() can be called
checkState();
}
private synchronized void checkState() {
// If the drawable cache and display ref counts = 0, and this drawable
// has been displayed, then recycle
if (cacheRefCount <= 0 && displayRefCount <= 0 && hasBeenDisplayed && hasValidBitmap()) {
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "No longer being used or cached so recycling. " + toString());
getBitmap().recycle();
}
}
private synchronized boolean hasValidBitmap() {
Bitmap bitmap = getBitmap();
return bitmap != null && !bitmap.isRecycled();
}
}
Now, iun your activity, whatever it does, if it needs to present recyclable image, you add this in xml res:
<com.example.android.streaming.ui.cache.RecyclingImageView
android:id="#+id/ad_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#drawable/bkgd_whitegradient"
android:contentDescription="#string/dummy_desc"
android:padding="20dip"/>
This is just an example, id, background, can be whatever you need.
final RecyclingImageView adImage = (RecyclingImageView) findViewById(R.id.ad_image);
adImage.setImageDrawable(new RecyclingBitmapDrawable(getResources(), getBitmap(this)));
adImage.setVisibility(View.VISIBLE);
Note the getBitmap(), this is an example. It is you who should implement it in a way you need. It returns Bitmap instance. In your case, this Bitmap will be created out of array of bytes you've received from your camera. Let's try to do it here too.
Next, I have a class for managing avatars in my app (long list of users is a good example). It has number of useful static methods, so you may not need to create it.
package com.example.android.streaming.ui.cache;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.util.LruCache;
import com.example.android.streaming.StreamingApp;
import com.example.android.streaming.datamodel.Broadcast;
import com.example.android.streaming.datamodel.Channel;
import com.facebook.model.GraphUser;
import com.parse.ParseFile;
import com.parse.ParseUser;
import com.vg.hangwith.BuildConfig;
import com.vg.hangwith.R;
public class AvatarCache {
private Map<String, LoadImageTask> tasks = new HashMap<String, AvatarCache.LoadImageTask>();
private LruCache<String, RecyclingBitmapDrawable> memoryCache;
public final static int AVATAR_BOUNDS = 100;
private String cacheDir;
private Context context;
public synchronized void addTask(String tag, LoadImageTask task) {
tasks.put(tag, task);
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Added avatar load task for tag " + tag);
}
public synchronized void removeTask(String tag) {
tasks.remove(tag);
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Removed avatar load task for tag " + tag);
}
public synchronized void cancelTasks(int keepLastItems) {
int count = 0;
Iterator<Map.Entry<String, LoadImageTask>> iter = tasks.entrySet().iterator();
while (iter.hasNext() && tasks.size() > keepLastItems) {
Map.Entry<String, LoadImageTask> entry = iter.next();
entry.getValue().cancel(true);
iter.remove();
count++;
}
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Canceled " + count + " avatar load tasks");
}
public void cancelTasks() {
cancelTasks(0);
}
public final static Bitmap downscaleAvatar(Bitmap bitmap) {
if (bitmap.getWidth() > AVATAR_BOUNDS && bitmap.getHeight() > AVATAR_BOUNDS) {
int height = (int) Math.floor(bitmap.getHeight() / ((1.0f * bitmap.getWidth()) / AVATAR_BOUNDS));
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, AVATAR_BOUNDS, height, false);
bitmap.recycle();
bitmap = null;
return scaled;
} else {
return bitmap;
}
}
public final static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public class LoadImageTask extends AsyncTask<Void, Void, RecyclingBitmapDrawable> {
protected RecyclingImageView image;
protected String url, tag;
protected boolean avatar;
public LoadImageTask(String url, String tag, boolean avatar, RecyclingImageView image) {
super();
this.url = url;
this.tag = tag;
this.image = image;
this.avatar = avatar;
image.setTag(R.string.tag_key, tag);
addTask(tag, this);
}
#Override
protected RecyclingBitmapDrawable doInBackground(Void... dummy) {
if (isCancelled() || !isSameImage())
return null;
RecyclingBitmapDrawable drawable = getAvatarFromMemCache(tag);
if (drawable == null) {
drawable = getAvatarFromDiskCache(tag);
if (drawable == null) {
try {
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Loading avatar " + url);
/* First decode bounds to check the image size. */
BitmapFactory.Options options = new BitmapFactory.Options();
/* Calculate if the avatar should be down scaled. */
if (avatar) {
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream(), null, options);
options.inSampleSize = calculateInSampleSize(options, AVATAR_BOUNDS, AVATAR_BOUNDS);
}
options.inJustDecodeBounds = false;
/* Download down scaled avatar. */
Bitmap bitmap = BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream(), null, options);
if (bitmap != null) {
drawable = new RecyclingBitmapDrawable(context.getResources(), bitmap);
if (drawable != null) {
addAvatarToDiskCache(tag, url, drawable);
addAvatarToMemoryCache(tag, drawable);
}
}
} catch (Exception e) {
Log.w(StreamingApp.TAG, "Failed to load and save avatar image. " + e.getMessage());
}
} else {
addAvatarToMemoryCache(tag, drawable);
}
}
return drawable;
}
private synchronized boolean isSameImage() {
// In case that the same image is reused for different avatar (during scroll), this
// function will return false.
Object imageTag = image.getTag(R.string.tag_key);
return imageTag != null && imageTag.equals(tag);
}
private void finishedWithResult(RecyclingBitmapDrawable result) {
if (result != null && isSameImage())
image.setImageDrawable(result);
removeTask(tag);
}
#Override
protected void onPostExecute(RecyclingBitmapDrawable result) {
finishedWithResult(result);
super.onPostExecute(result);
}
#Override
protected void onCancelled(RecyclingBitmapDrawable result) {
finishedWithResult(result);
super.onCancelled();
}
#Override
protected void onCancelled() {
finishedWithResult(null);
super.onCancelled();
}
}
public AvatarCache(Context context) {
super();
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/10th of the available memory for this memory cache. With small avatars like
// we have this is enough to keep ~100 avatars in cache.
final int cacheSize = maxMemory / 10;
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Init avatar cache, size: " + cacheSize + ", max mem size: " + maxMemory);
memoryCache = new LruCache<String, RecyclingBitmapDrawable>(cacheSize) {
#Override
protected int sizeOf(String key, RecyclingBitmapDrawable drawable) {
// The cache size will be measured in kilobytes rather than
// number of items.
Bitmap bitmap = drawable.getBitmap();
int bitmapSize = bitmap != null ? bitmap.getByteCount() / 1024 : 0;
return bitmapSize == 0 ? 1 : bitmapSize;
}
#Override
protected void entryRemoved(boolean evicted, String key, RecyclingBitmapDrawable oldValue,
RecyclingBitmapDrawable newValue) {
// The removed entry is a recycling drawable, so notify it.
// that it has been removed from the memory cache
oldValue.setIsCached(false);
}
};
this.cacheDir = context.getCacheDir().getAbsolutePath();
this.context = context;
}
public void flush() {
int oldSize = memoryCache.size();
memoryCache.evictAll();
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Flush avatar cache, flushed " + (oldSize - memoryCache.size()) + " new size "
+ memoryCache.size());
cancelTasks();
}
public void addAvatarToMemoryCache(String key, RecyclingBitmapDrawable drawable) {
if (getAvatarFromMemCache(key) == null) {
drawable.setIsCached(true);
memoryCache.put(key, drawable);
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Add to avatar cache, size: " + memoryCache.size());
}
}
public RecyclingBitmapDrawable getAvatarFromMemCache(String key) {
return memoryCache.get(key);
}
public void addAvatarToDiskCache(String name, String url, RecyclingBitmapDrawable drawable) throws IOException {
if (drawable == null)
return;
File dir = new File(cacheDir);
if (!dir.exists())
dir.mkdirs();
File file = new File(dir, name);
Bitmap bitmap = drawable.getBitmap();
if (!file.exists() && bitmap != null) {
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
drawable.getBitmap().compress(Bitmap.CompressFormat.PNG, 85, out);
out.flush();
out.close();
}
}
/*
* Update avatar from the network if older than this.
*/
public static final int AVATAR_MAX_AGE_DAYS = 7;
public RecyclingBitmapDrawable getAvatarFromDiskCache(String name) {
File file = new File(cacheDir, name);
/* Check if cached bitmap is old. */
if ((System.currentTimeMillis() - file.lastModified()) > AVATAR_MAX_AGE_DAYS * 24 * 60 * 60 * 1000)
return null;
try {
Bitmap bitmap = BitmapFactory.decodeFile(file.getCanonicalPath());
if (bitmap != null) {
// Log.w(App.TAG, "Loaded " + (bitmap.getByteCount() / 1024.0f) + "K bitmap " + name + " w: "
// + bitmap.getWidth() + " h: " + bitmap.getHeight());
return new RecyclingBitmapDrawable(context.getResources(), bitmap);
}
} catch (Exception e) {
Log.w(StreamingApp.TAG, "Failed to decode avatar image " + name + ". " + e.getMessage());
}
return null;
}
public static boolean isValidURL(String url) {
try {
new URL(url);
return true;
} catch (Exception e) {
}
return false;
}
public void loadUrlAvatar(String url, String name, RecyclingImageView image, int placeholder, boolean checkDiskCache) {
RecyclingBitmapDrawable drawable = getAvatarFromMemCache(name);
if (drawable == null && checkDiskCache) {
drawable = getAvatarFromDiskCache(name);
if (drawable != null)
addAvatarToMemoryCache(name, drawable);
}
if (drawable == null) {
image.setImageResource(placeholder);
if (url != null && isValidURL(url))
new LoadImageTask(url, name, true, image).execute();
} else {
image.setImageDrawable(drawable);
}
}
public static String getUserAvatarURL(ParseUser user) {
if (user == null)
return null;
if (user.get("avatar") == null || user.get("avatar") == JSONObject.NULL)
return user.getString("avatar_url");
if (user.get("avatar") instanceof JSONObject)
Log.w(StreamingApp.TAG, "JSONObject found instead of ParseFile: " + ((JSONObject) user.get("avatar")).toString());
return ((ParseFile) user.get("avatar")).getUrl();
}
public static String getUserAvatarURL(GraphUser user) {
return "http://graph.facebook.com/" + user.getId() + "/picture";
}
public static String getBroadcastAvatarURL(Broadcast broadcast) {
if (broadcast.getThumbnail() == null)
return null;
return broadcast.getThumbnail().getUrl();
}
public void loadUserAvatar(ParseUser user, RecyclingImageView image, int placeholder, boolean checkDiskCache) {
if (user != null)
loadUrlAvatar(getUserAvatarURL(user), user.getUsername(), image, placeholder, checkDiskCache);
}
public void loadUserAvatar(GraphUser user, RecyclingImageView image, int placeholder, boolean checkDiskCache) {
if (user != null)
loadUrlAvatar(getUserAvatarURL(user), user.getId(), image, placeholder, checkDiskCache);
}
public void loadBroadcastAvatar(Broadcast broadcast, RecyclingImageView image, int placeholder,
boolean checkDiskCache) {
if (broadcast != null)
loadUrlAvatar(getBroadcastAvatarURL(broadcast), broadcast.getObjectId(), image, placeholder, checkDiskCache);
}
public void clearUserAvatar(ParseUser user) {
File file = new File(cacheDir, user.getUsername());
if (file.exists())
file.delete();
memoryCache.remove(user.getUsername());
if (BuildConfig.DEBUG)
Log.d(StreamingApp.TAG, "Remove avatar from cache, size: " + memoryCache.size());
}
public static String getChannelImageURL(Channel channel, boolean small, boolean ageRestricted) {
if (ageRestricted) {
if (small && channel.getSmallRestrictedState() != null)
return channel.getSmallRestrictedState().getUrl();
else if (!small && channel.getLargeRestrictedState() != null)
return channel.getLargeRestrictedState().getUrl();
} else {
if (small && channel.getSmallEmptyState() != null)
return channel.getSmallEmptyState().getUrl();
else if (!small && channel.getLargeEmptyState() != null)
return channel.getLargeEmptyState().getUrl();
}
return null;
}
public static final String channelImageCacheName(Channel channel, boolean small, boolean ageRestricted) {
return channel.getObjectId() + "-" + (ageRestricted ? "age" : "empty") + "-" + (small ? "small" : "large");
}
public boolean loadChannelImage(Channel channel, RecyclingImageView image, boolean checkDiskCache, boolean small,
boolean ageRestricted) {
boolean result = false;
if (channel == null)
return false;
String name = channelImageCacheName(channel, small, ageRestricted);
RecyclingBitmapDrawable drawable = getAvatarFromMemCache(name);
if (drawable == null && checkDiskCache) {
drawable = getAvatarFromDiskCache(name);
if (drawable != null)
addAvatarToMemoryCache(name, drawable);
}
if (drawable == null) {
String url = getChannelImageURL(channel, small, ageRestricted);
result = url != null && isValidURL(url);
if (result)
new LoadImageTask(url, name, false, image).execute();
} else {
image.setImageDrawable(drawable);
result = true;
}
return result;
}
public void loadUrlImage(String url, RecyclingImageView image, String name, boolean checkDiskCache) {
RecyclingBitmapDrawable drawable = getAvatarFromMemCache(name);
if (drawable == null && checkDiskCache) {
drawable = getAvatarFromDiskCache(name);
if (drawable != null)
addAvatarToMemoryCache(name, drawable);
}
if (drawable == null) {
if (url != null && isValidURL(url))
new LoadImageTask(url, name, false, image).execute();
} else {
image.setImageDrawable(drawable);
}
}
}
Note, it uses Parse framework at some places. Just ignore it.
In this example, AvatarCache is loading image by url in doInBackground() function. As you can see it gets an input stream of out url. You can modify it to feed it some different input stream that you use for loading your image. Then you also need to modify loadUrlImage(). In other words, just remove the url thing.
And this is how you can use it with Uri. Modify it for using input stream or array of bytes. Just use appropriate BitmapFactory.decodeSomething() method.
public Bitmap getBitmap(Uri uri) {
BitmapFactory.Options options = new BitmapFactory.Options();
AssetFileDescriptor fd = null;
Bitmap b = null;
try {
fd = getContentResolver().openAssetFileDescriptor(uri, "r");
if (fd != null) {
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, options);
options.inSampleSize = AvatarCache.calculateInSampleSize(options, AvatarCache.AVATAR_BOUNDS, AvatarCache.AVATAR_BOUNDS);
options.inJustDecodeBounds = false;
b = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, options);
try {
fd.close();
} catch (IOException e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
As you can see, AvatarCache is only used statically in this example. In case you need to manage a lot of images, like a photo lib preview.create AvatarCache in your app instance. Also add memory mgnt methods.
#Override
public void onCreate() {
super.onCreate();
avatarCache = new AvatarCache(this);
}
public void onTrimMemory(int level) {
if (level == TRIM_MEMORY_COMPLETE || level == TRIM_MEMORY_RUNNING_CRITICAL || level == TRIM_MEMORY_RUNNING_LOW) {
if (avatarCache != null)
avatarCache.flush();
}
super.onTrimMemory(level);
}
#Override
public void onLowMemory() {
Log.w(StreamingApp.TAG, "Low memory event received. Clear avatars cache.");
if (avatarCache != null)
avatarCache.flush();
super.onLowMemory();
}
And then you can use it a way like this:
avatarCache.loadUserAvatar(...);
It will automatically load the image and place it to the cache. When the app is short of memory, cache will be flushed.
Hope this helps. It is quite a lot of stuff here but when you go through this once, you will never have issues with images in your android app. Happy coding!
PS. Ask questions if you need. Just be specific with what you need asking and give also some context of your particular use case.
how can make the first look like BBC News android app using Asynctask (onPreExecute() method). please help me my helper class code is here...
UrlImageViewHelper.java
package com.warriorpoint.androidxmlsimple;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.widget.ImageView;
public final class UrlImageViewHelper {
private static final String LOGTAG = "UrlImageViewHelper";
public static int copyStream(InputStream input, OutputStream output) throws IOException
{
byte[] stuff = new byte[1024];
int read = 0;
int total = 0;
while ((read = input.read(stuff)) != -1)
{
output.write(stuff, 0, read);
total += read;
}
return total;
}
static Resources mResources;
static DisplayMetrics mMetrics;
private static void prepareResources(Context context) {
if (mMetrics != null)
return;
mMetrics = new DisplayMetrics();
Activity act = (Activity)context;
act.getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
AssetManager mgr = context.getAssets();
mResources = new Resources(mgr, mMetrics, context.getResources().getConfiguration());
}
private static BitmapDrawable loadDrawableFromStream(Context context, InputStream stream) {
prepareResources(context);
final Bitmap bitmap = BitmapFactory.decodeStream(stream);
//Log.i(LOGTAG, String.format("Loaded bitmap (%dx%d).", bitmap.getWidth(), bitmap.getHeight()));
return new BitmapDrawable(mResources, bitmap);
}
public static final int CACHE_DURATION_INFINITE = Integer.MAX_VALUE;
public static final int CACHE_DURATION_ONE_DAY = 1000 * 60 * 60 * 24;
public static final int CACHE_DURATION_TWO_DAYS = CACHE_DURATION_ONE_DAY * 2;
public static final int CACHE_DURATION_THREE_DAYS = CACHE_DURATION_ONE_DAY * 3;
public static final int CACHE_DURATION_FOUR_DAYS = CACHE_DURATION_ONE_DAY * 4;
public static final int CACHE_DURATION_FIVE_DAYS = CACHE_DURATION_ONE_DAY * 5;
public static final int CACHE_DURATION_SIX_DAYS = CACHE_DURATION_ONE_DAY * 6;
public static final int CACHE_DURATION_ONE_WEEK = CACHE_DURATION_ONE_DAY * 7;
public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource) {
setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, CACHE_DURATION_THREE_DAYS);
}
public static void setUrlDrawable(final ImageView imageView, final String url) {
setUrlDrawable(imageView.getContext(), imageView, url, null, CACHE_DURATION_THREE_DAYS);
}
public static void loadUrlDrawable(final Context context, final String url) {
setUrlDrawable(context, null, url, null, CACHE_DURATION_THREE_DAYS);
}
public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable) {
setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, CACHE_DURATION_ONE_DAY);
}
public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) {
setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, cacheDurationMs);
}
public static void loadUrlDrawable(final Context context, final String url, long cacheDurationMs) {
setUrlDrawable(context, null, url, null, cacheDurationMs);
}
public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable, long cacheDurationMs) {
setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, cacheDurationMs);
}
private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) {
Drawable d = null;
if (defaultResource != 0)
d = imageView.getResources().getDrawable(defaultResource);
setUrlDrawable(context, imageView, url, d, cacheDurationMs);
}
private static boolean isNullOrEmpty(CharSequence s) {
return (s == null || s.equals("") || s.equals("null") || s.equals("NULL"));
}
private static boolean mHasCleaned = false;
public static String getFilenameForUrl(String url) {
return "" + url.hashCode() + ".urlimage";
}
private static void cleanup(Context context) {
if (mHasCleaned)
return;
mHasCleaned = true;
try {
// purge any *.urlimage files over a week old
String[] files = context.getFilesDir().list();
if (files == null)
return;
for (String file : files) {
if (!file.endsWith(".urlimage"))
continue;
File f = new File(context.getFilesDir().getAbsolutePath() + '/' + file);
if (System.currentTimeMillis() > f.lastModified() + CACHE_DURATION_ONE_WEEK)
f.delete();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, final Drawable defaultDrawable, long cacheDurationMs) {
cleanup(context);
// disassociate this ImageView from any pending downloads
if (imageView != null)
mPendingViews.remove(imageView);
if (isNullOrEmpty(url)) {
if (imageView != null)
imageView.setImageDrawable(defaultDrawable);
return;
}
final UrlImageCache cache = UrlImageCache.getInstance();
Drawable d = cache.get(url);
if (d != null) {
//Log.i(LOGTAG, "Cache hit on: " + url);
if (imageView != null)
imageView.setImageDrawable(d);
return;
}
final String filename = getFilenameForUrl(url);
File file = context.getFileStreamPath(filename);
if (file.exists()) {
try {
if (cacheDurationMs == CACHE_DURATION_INFINITE || System.currentTimeMillis() < file.lastModified() + cacheDurationMs) {
//Log.i(LOGTAG, "File Cache hit on: " + url + ". " + (System.currentTimeMillis() - file.lastModified()) + "ms old.");
FileInputStream fis = context.openFileInput(filename);
BitmapDrawable drawable = loadDrawableFromStream(context, fis);
fis.close();
if (imageView != null)
imageView.setImageDrawable(drawable);
cache.put(url, drawable);
return;
}
else {
//Log.i(LOGTAG, "File cache has expired. Refreshing.");
}
}
catch (Exception ex) {
}
}
// null it while it is downloading
if (imageView != null)
imageView.setImageDrawable(defaultDrawable);
// since listviews reuse their views, we need to
// take note of which url this view is waiting for.
// This may change rapidly as the list scrolls or is filtered, etc.
//Log.i(LOGTAG, "Waiting for " + url);
if (imageView != null)
mPendingViews.put(imageView, url);
ArrayList<ImageView> currentDownload = mPendingDownloads.get(url);
if (currentDownload != null) {
// Also, multiple vies may be waiting for this url.
// So, let's maintain a list of these views.
// When the url is downloaded, it sets the imagedrawable for
// every view in the list. It needs to also validate that
// the imageview is still waiting for this url.
if (imageView != null)
currentDownload.add(imageView);
return;
}
final ArrayList<ImageView> downloads = new ArrayList<ImageView>();
if (imageView != null)
downloads.add(imageView);
mPendingDownloads.put(url, downloads);
AsyncTask<Void, Void, Drawable> downloader = new AsyncTask<Void, Void, Drawable>() {
#Override
protected Drawable doInBackground(Void... params) {
AndroidHttpClient client = AndroidHttpClient.newInstance(context.getPackageName());
try {
HttpGet get = new HttpGet(url);
final HttpParams httpParams = new BasicHttpParams();
HttpClientParams.setRedirecting(httpParams, true);
get.setParams(httpParams);
HttpResponse resp = client.execute(get);
int status = resp.getStatusLine().getStatusCode();
if(status != HttpURLConnection.HTTP_OK){
// Log.i(LOGTAG, "Couldn't download image from Server: " + url + " Reason: " + resp.getStatusLine().getReasonPhrase() + " / " + status);
return null;
}
HttpEntity entity = resp.getEntity();
// Log.i(LOGTAG, url + " Image Content Length: " + entity.getContentLength());
InputStream is = entity.getContent();
FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
copyStream(is, fos);
fos.close();
is.close();
FileInputStream fis = context.openFileInput(filename);
return loadDrawableFromStream(context, fis);
}
catch (Exception ex) {
// Log.e(LOGTAG, "Exception during Image download of " + url, ex);
return null;
}
finally {
client.close();
}
}
#Override
protected void onPostExecute(Drawable result) {
if (result == null)
result = defaultDrawable;
mPendingDownloads.remove(url);
cache.put(url, result);
for (ImageView iv: downloads) {
// validate the url it is waiting for
String pendingUrl = mPendingViews.get(iv);
if (!url.equals(pendingUrl)) {
//Log.i(LOGTAG, "Ignoring out of date request to update view for " + url);
continue;
}
mPendingViews.remove(iv);
if (result != null) {
final Drawable newImage = result;
Drawable newSize=resize(newImage);
final ImageView imageView = iv;
imageView.setImageDrawable(newSize);
}
}
}
private BitmapDrawable resize(Drawable newImage) {
// TODO Auto-generated method stub
Bitmap d = ((BitmapDrawable)newImage).getBitmap();
Bitmap bitmapOrig = Bitmap.createScaledBitmap(d, 75, 75, false);
return new BitmapDrawable(bitmapOrig);
}
};
downloader.execute();
}
private static Hashtable<ImageView, String> mPendingViews = new Hashtable<ImageView, String>();
private static Hashtable<String, ArrayList<ImageView>> mPendingDownloads = new Hashtable<String, ArrayList<ImageView>>();
}
my main activity is MessageList.java.
Like this
private final ProgressDialog dialog = new ProgressDialog(this.context);
#Override
protected void onPreExecute() {
this.dialog.setMessage("Fecthing Image");
this.dialog.setTitle("Please Wait");
this.dialog.setIcon(R.drawable."Any Image here");
this.dialog.show();
}
I am struggling to update a list view with data from a database, this works nicely by using a SimpleCursorAdapter. But the image view on the rows is not updated on the activity start, I have to scroll through the list a few times and only then the images are loaded in the image view.
This is the binder i am using for the SimpleCursorAdapter:
private class PromotionViewBinder implements SimpleCursorAdapter.ViewBinder {
private int done;
public boolean setViewValue(View view, Cursor cursor, int index) {
Log.e(""+cursor.getCount(),"");
View tmpview = view;
if (index == cursor.getColumnIndex(PromotionsTable.SEEN_COL)) {
boolean read = cursor.getInt(index) > 0 ? true : false;
TextView title = (TextView) tmpview;
if (!read) {
title.setTypeface(Typeface.DEFAULT_BOLD, 0);
} else {
title.setTypeface(Typeface.DEFAULT);
}
return true;
} else if (tmpview.getId() == R.id.promotions_list_row_image){
String imageURL = cursor.getString(index);
Log.e("",imageURL);
imageRetriever.displayImage(imageURL, (ImageView)tmpview);
return true;
} else {
return false;
}
}
}
The image retriever class is the LazyList example from here. As you will see this is using a runnable to retrieve the images and once the task is done is automatically updating the given imageView...Do you think that the reference to the imageView is lost somewhere on the way?
Thanx in advance,
Nick
package com.tipgain.promotions;
The image retriever class:
/**
* This class is used for retrieving images from a given web link. it uses local
* storage and memory to store the images. Once a image is downloaded
* successfully the UI gets updated automatically.
*
*
*/
public class ImageRetriever {
private final String TAG = ImageRetriever.class.getName();
private MemoryImageCache memoryImgCache = new MemoryImageCache();
private LocalStorageImageCache localFileCache;
private Map<ImageView, String> imageViewHolders = Collections
.synchronizedMap(new WeakHashMap<ImageView, String>());
private ExecutorService execService;
final int defaultImageID = R.drawable.photo_not_available;
public ImageRetriever(Context context) {
localFileCache = new LocalStorageImageCache(context);
execService = Executors.newFixedThreadPool(5);
}
public void displayImage(String url, ImageView imageView) {
imageViewHolders.put(imageView, url);
Bitmap bmp = memoryImgCache.retrieve(url);
if (bmp != null) {
Log.e("case 1", " " + (bmp != null));
imageView.setImageBitmap(bmp);
} else {
Log.e("case 2", " " + (bmp == null));
addImageToQueue(url, imageView);
imageView.setImageResource(defaultImageID);
}
}
private void addImageToQueue(String url, ImageView imageView) {
NextImageToLoad img = new NextImageToLoad(url, imageView);
execService.submit(new ImagesRetriever(img));
}
/**
* This method is used for retrieving the Bitmap Image.
*
* #param url
* String representing the url pointing to the image.
* #return Bitmap representing the image
*/
private Bitmap getBitmap(String url) {
File imageFile = localFileCache.getFile(url);
// trying to get the bitmap from the local storage first
Bitmap bmp = decodeImageFile(imageFile);
if (bmp != null)
return bmp;
// if the file was not found locally we retrieve it from the web
try {
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imageUrl
.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(imageFile);
Utils.CopyStream(is, os);
os.close();
bmp = decodeImageFile(imageFile);
return bmp;
} catch (MalformedURLException e) {
Log.e(TAG, e.getMessage());
} catch (FileNotFoundException e) {
Log.e(TAG, e.getMessage());
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
return null;
}
/**
* This method is used for decoding a given image file. Also, to reduce
* memory, the image is also scaled.
*
* #param imageFile
* #return
*/
private Bitmap decodeImageFile(File imageFile) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(imageFile), null,
options);
// Find the correct scale value. It should be the power of 2.
// Deciding the perfect scaling value. (^2).
final int REQUIRED_SIZE = 100;
int tmpWidth = options.outWidth, tmpHeight = options.outHeight;
int scale = 1;
while (true) {
if (tmpWidth / 2 < REQUIRED_SIZE
|| tmpHeight / 2 < REQUIRED_SIZE)
break;
tmpWidth /= 2;
tmpHeight /= 2;
scale *= 2;
}
// decoding using inSampleSize
BitmapFactory.Options option2 = new BitmapFactory.Options();
option2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(imageFile),
null, option2);
} catch (FileNotFoundException e) {
Log.e(TAG, e.getLocalizedMessage());
}
return null;
}
private boolean reusedImage(NextImageToLoad image) {
Context c = image.imageView.getContext();
c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);
String tag = imageViewHolders.get(image.imageView);
if ((tag == null) || (!tag.equals(image.url)))
return true;
return false;
}
/**
* Clears the Memory and Local cache
*/
public void clearCache() {
memoryImgCache.clear();
localFileCache.clear();
}
/**
* This class implements a runnable that is used for updating the promotions
* images on the UI
*
*
*/
class UIupdater implements Runnable {
Bitmap bmp;
NextImageToLoad image;
public UIupdater(Bitmap bmp, NextImageToLoad image) {
this.bmp = bmp;
this.image = image;
Log.e("", "ui updater");
}
public void run() {
Log.e("ui updater", "ui updater");
if (reusedImage(image))
return;
Log.e("nick", "" + (bmp == null) + " chberugv");
if (bmp != null){
image.imageView.setImageBitmap(bmp);
Context c = image.imageView.getContext();
c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);
}else
image.imageView.setImageResource(defaultImageID);
}
}
private class ImagesRetriever implements Runnable {
NextImageToLoad image;
ImagesRetriever(NextImageToLoad image) {
this.image = image;
}
public void run() {
Log.e("images retirever", " images retriever");
if (reusedImage(image))
return;
Bitmap bmp = getBitmap(image.url);
memoryImgCache.insert(image.url, bmp);
if (reusedImage(image))
return;
UIupdater uiUpdater = new UIupdater(bmp, image);
Activity activity = (Activity) image.imageView.getContext();
activity.runOnUiThread(uiUpdater);
//Context c = image.imageView.getContext();
//c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);
}
}
/**
* This class encapsulates the image being downloaded.
*
* #author Nicolae Anca
*
*/
private class NextImageToLoad {
public String url;
public ImageView imageView;
public NextImageToLoad(String u, ImageView i) {
url = u;
imageView = i;
}
}
}
Modified Runnable:
class UIupdater implements Runnable {
Bitmap bmp;
NextImageToLoad image;
public UIupdater(Bitmap bmp, NextImageToLoad image) {
this.bmp = bmp;
this.image = image;
}
public void run() {
if (reusedImage(image))
return;
if (bmp != null){
image.imageView.setImageBitmap(bmp);
Context c = image.imageView.getContext();
c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);
}else
image.imageView.setImageResource(defaultImageID);
}
}
Thats an interesting way to do what you are doing. Have you tried extending the Simple Cursor Adapter?
What you do is implement a ViewHolder and put your imageview in it.
Then in your ImageRetriever, write a Listener which will be called once the image is ready and retrieved.
Implement this listener in the Viewholder.
You create the view in getView() and request for the image in BindView().
Once the image gets loaded, the list will be refreshed automatically.
one way to do it is by calling notifyDataSetChenged on listview, and another was is to have adapter as member variable and when something changes on listview you call a function that assigns new listadapter to member adapter. That way your list will be redraw on change.
I guess, you have to use some handler, calling after image load, which will call notifyDataSetChanged for list adapter
String projection[] = new String[]{MediaStore.Images.Media.DATA};
cursor =managedQuery(Media.EXTERNAL_CONTENT_URI, projection,null,null, null);
this cursor is returning null when i am trying to run it on device. it works fine on emulator.
Can someone please point out if there is something that i am missing or doing wrong.
same for this code working
public class LoadImagesFromSDCardActivity extends Activity implements
OnItemClickListener {
/**
* Grid view holding the images.
**/
private GridView sdcardImages;
/**
* Image adapter for the grid view.
**/
private ImageAdapter imageAdapter;
/**
* Display used for getting the width of the screen.
**/
private Display display;
ImageView imgView;
/**
* Creates the content view, sets up the grid, the adapter, and the click listener.
*
* #see android.app.Activity#onCreate(android.os.Bundle)
**/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Request progress bar
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
imgView=(ImageView)findViewById(R.id.imgView);
setupViews();
setProgressBarIndeterminateVisibility(true);
loadImages();
}
/**
* Free up bitmap related resources.
**/
protected void onDestroy() {
super.onDestroy();
final GridView grid = sdcardImages;
final int count = grid.getChildCount();
ImageView v = null;
for (int i = 0; i < count; i++) {
v = (ImageView) grid.getChildAt(i);
((BitmapDrawable) v.getDrawable()).setCallback(null);
}
}
/**
* Setup the grid view.
**/
private void setupViews() {
sdcardImages = (GridView) findViewById(R.id.sdcard);
sdcardImages.setNumColumns(display.getWidth()/95);
sdcardImages.setClipToPadding(false);
sdcardImages.setOnItemClickListener(LoadImagesFromSDCardActivity.this);
imageAdapter = new ImageAdapter(getApplicationContext());
sdcardImages.setAdapter(imageAdapter);
}
/**
* Load images.
*/
private void loadImages() {
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);
}
}
}
/**
* Add image(s) to the grid view adapter.
*
* #param value Array of LoadedImages references
*/
private void addImage(LoadedImage... value) {
for (LoadedImage image : value) {
imageAdapter.addPhoto(image);
imageAdapter.notifyDataSetChanged();
}
}
/**
* Save bitmap images into a list and return that list.
*
* #see android.app.Activity#onRetainNonConfigurationInstance()
*/
#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;
}
/**
* Async task for loading the images from the SD card.
*
* #author Mihai Fonoage
*
*/
class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {
/**
* Load images from SD Card in the background, and display each image on the screen.
*
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected Object doInBackground(Object... params) {
//setProgressBarIndeterminateVisibility(true);
Bitmap bitmap = null;
Bitmap newBitmap = null;
Uri uri = null;
// Set up an array of the Thumbnail Image ID column we want
String[] projection = {MediaStore.Images.Thumbnails._ID};
// Create the cursor pointing to the SDCard
Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
null);
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
int size = cursor.getCount();
// If size is 0, there are no images on the SD Card.
if (size == 0) {
//No Images available, post some message to the user
}
int imageID = 0;
for (int i = 0; i < size; i++) {
cursor.moveToPosition(i);
imageID = cursor.getInt(columnIndex);
uri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID);
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
if (bitmap != null) {
newBitmap = Bitmap.createScaledBitmap(bitmap, 70, 70, true);
bitmap.recycle();
if (newBitmap != null) {
publishProgress(new LoadedImage(newBitmap));
}
}
} catch (IOException e) {
//Error fetching image, try to recover
}
}
cursor.close();
return null;
}
/**
* Add a new LoadedImage in the images grid.
*
* #param value The image.
*/
#Override
public void onProgressUpdate(LoadedImage... value) {
addImage(value);
}
/**
* Set the visibility of the progress bar to false.
*
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(Object result) {
setProgressBarIndeterminateVisibility(false);
}
}
/**
* Adapter for our image files.
*
* #author Mihai Fonoage
*
*/
class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
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 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(8, 8, 8, 8);
imageView.setImageBitmap(photos.get(position).getBitmap());
return imageView;
}
}
/**
* A LoadedImage contains the Bitmap loaded for the image.
*/
private static class LoadedImage {
Bitmap mBitmap;
LoadedImage(Bitmap bitmap) {
mBitmap = bitmap;
}
public Bitmap getBitmap() {
return mBitmap;
}
}
/**
* When an image is clicked, load that image as a puzzle.
*/
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
int columnIndex = 0;
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection,
null,
null,
null);
if (cursor != null) {
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToPosition(position);
String imagePath = cursor.getString(columnIndex);
FileInputStream is = null;
BufferedInputStream bis = null;
try {
is = new FileInputStream(new File(imagePath));
bis = new BufferedInputStream(is);
Bitmap bitmap = BitmapFactory.decodeStream(bis);
Bitmap useThisBitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
Log.i("called","called");
imgView.setImageBitmap(useThisBitmap);
bitmap.recycle();
//Display bitmap (useThisBitmap)
}
catch (Exception e) {
//Try to recover
}
finally {
try {
if (bis != null) {
bis.close();
}
if (is != null) {
is.close();
}
cursor.close();
projection = null;
} catch (Exception e) {
}
}
}
}
}
And
main.xml
<GridView
android:id="#+id/sdcard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imgView"
></ImageView>
</LinearLayout>
http://www.androidsnippets.com/list-all-music-files
i am able to show all images from sdcard into grid but how to show only specified image from sdcard into grid in android.Can anybody help please?
/**
* Loads images from SD card.
* #author padma kumar
*/
public class LoadImagesFromSDCardActivity extends Activity implements
OnItemClickListener {
/**
* Grid view holding the images.
*/
private GridView sdcardImages;
/**
* Image adapter for the grid view.
*/
private ImageAdapter imageAdapter;
/**
* Display used for getting the width of the screen.
*/
private Display display;
/**
* Creates the content view, sets up the grid, the adapter, and the click listener.
*
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Request progress bar
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.sdcard);
display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
setupViews();
setProgressBarIndeterminateVisibility(true);
loadImages();
}
/**
* Free up bitmap related resources.
*/
protected void onDestroy() {
super.onDestroy();
final GridView grid = sdcardImages;
final int count = grid.getChildCount();
ImageView v = null;
for (int i = 0; i < count; i++) {
v = (ImageView) grid.getChildAt(i);
((BitmapDrawable) v.getDrawable()).setCallback(null);
}
}
/**
* Setup the grid view.
*/
private void setupViews() {
sdcardImages = (GridView) findViewById(R.id.sdcard);
sdcardImages.setNumColumns(display.getWidth()/95);
sdcardImages.setClipToPadding(false);
sdcardImages.setOnItemClickListener(LoadImagesFromSDCardActivity.this);
imageAdapter = new ImageAdapter(getApplicationContext());
sdcardImages.setAdapter(imageAdapter);
}
/**
* Load images.
*/
private void loadImages() {
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);
}
}
}
/**
* Add image(s) to the grid view adapter.
*
* #param value Array of LoadedImages references
*/
private void addImage(LoadedImage... value) {
for (LoadedImage image : value) {
imageAdapter.addPhoto(image);
imageAdapter.notifyDataSetChanged();
}
}
/**
* Save bitmap images into a list and return that list.
*
* #see android.app.Activity#onRetainNonConfigurationInstance()
*/
#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;
}
/**
* Async task for loading the images from the SD card.
*/
class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {
/**
* Load images from SD Card in the background, and display each image on the screen.
*
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected Object doInBackground(Object... params) {
//setProgressBarIndeterminateVisibility(true);
Bitmap bitmap = null;
Bitmap newBitmap = null;
Uri uri = null;
// Set up an array of the Thumbnail Image ID column we want
String[] projection = {MediaStore.Images.Thumbnails._ID};
// Create the cursor pointing to the SDCard
Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
null);
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
int size = cursor.getCount();
// If size is 0, there are no images on the SD Card.
if (size == 0) {
//No Images available, post some message to the user
}
int imageID = 0;
for (int i = 0; i < size; i++) {
cursor.moveToPosition(i);
imageID = cursor.getInt(columnIndex);
uri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID);
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
if (bitmap != null) {
newBitmap = Bitmap.createScaledBitmap(bitmap, 70, 70, true);
bitmap.recycle();
if (newBitmap != null) {
publishProgress(new LoadedImage(newBitmap));
}
}
} catch (IOException e) {
//Error fetching image, try to recover
}
}
cursor.close();
return null;
}
/**
* Add a new LoadedImage in the images grid.
*
* #param value The image.
*/
#Override
public void onProgressUpdate(LoadedImage... value) {
addImage(value);
}
/**
* Set the visibility of the progress bar to false.
*
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(Object result) {
setProgressBarIndeterminateVisibility(false);
}
}
/**
* Adapter for our image files.
*/
class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
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 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(8, 8, 8, 8);
imageView.setImageBitmap(photos.get(position).getBitmap());
return imageView;
}
}
/**
* A LoadedImage contains the Bitmap loaded for the image.
*/
private static class LoadedImage {
Bitmap mBitmap;
LoadedImage(Bitmap bitmap) {
mBitmap = bitmap;
}
public Bitmap getBitmap() {
return mBitmap;
}
}
/**
* When an image is clicked, load that image as a puzzle.
*/
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
int columnIndex = 0;
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection,
null,
null,
null);
if (cursor != null) {
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToPosition(position);
String imagePath = cursor.getString(columnIndex);
FileInputStream is = null;
BufferedInputStream bis = null;
try {
is = new FileInputStream(new File(imagePath));
bis = new BufferedInputStream(is);
Bitmap bitmap = BitmapFactory.decodeStream(bis);
Bitmap useThisBitmap = Bitmap.createScaledBitmap(bitmap, parent.getWidth(), parent.getHeight(), true);
bitmap.recycle();
//Display bitmap (useThisBitmap)
}
catch (Exception e) {
//Try to recover
}
finally {
try {
if (bis != null) {
bis.close();
}
if (is != null) {
is.close();
}
cursor.close();
projection = null;
} catch (Exception e) {
}
}
}
}
}