i have the folowing custom adapter for a Gallery widget. everything works great except when i change screen orientation, the app crashes due to
12-03 12:45:48.897: ERROR/AndroidRuntime(3594): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
i know that the maximum VM budget is 16 mb. but how did i pass it? is there a way to clear the memory that is not used or on orientation change? i know there is a recycle method for bitmaps but how do i use it in my case?
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Uri[] mUrls;
String[] mFiles=null;
public ImageAdapter(Context c) {
mContext = c;
readImagesFromSd();
TypedArray a = c.obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
public void readImagesFromSd(){
File images = new File(Environment.getExternalStorageDirectory().toString()+CameraView.FOLDER+"/");
images.mkdirs();
File[] imagelist = images.listFiles();
//Toast.makeText(mContext, String.valueOf(imagelist.length), Toast.LENGTH_LONG).show();
/*new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return ((name.endsWith(".jpg")) || (name.endsWith(".png")));
}
});*/
mFiles = new String[imagelist.length];
for (int i = 0; i < imagelist.length; i++) {
mFiles[i] = imagelist[i].getAbsolutePath();
}
mUrls = new Uri[mFiles.length];
for (int i = 0; i < mFiles.length; i++) {
mUrls[i] = Uri.parse(mFiles[i]);
}
}
public int getCount() {
// return mImageIds.length;
return mUrls.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
// i.setImageResource(mImageIds[position]);
i.setImageURI(mUrls[position]);
i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
Related
I want show image in gridview from sdcard directory.i use this code.But when i load image by type : bitmap.getView in gridview adapter need Integer[] array.how i can fix it?
public class LoadPic extends Activity {
Integer[] imageIDs = {
R.drawable.user,
R.drawable.user,
R.drawable.user,
R.drawable.user,
R.drawable.user,
R.drawable.user,
R.drawable.user
};
int numberOfImages=0;
Bitmap[] m;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.load_pic);
Intent gett = getIntent();
String _area = gett.getStringExtra("area");
String _domain = gett.getStringExtra("domain");
String _block = gett.getStringExtra("block");
String _melk = gett.getStringExtra("melk");
String _build = gett.getStringExtra("build");
String _apar = gett.getStringExtra("apar");
String _senfi = gett.getStringExtra("senfi");
File dir = new File(Environment.getExternalStorageDirectory()
+ "/momayezi/"+_area+"-"+_domain+"-"+_block+"-"+_melk+"-"+_build+"-"+_apar+"-"+_senfi);
File[] files = dir.listFiles();
numberOfImages=files.length;
for (int i=1;i<=numberOfImages;i++)
{
File img = new File("/sdcard/momayezi/"+_area+"-"+_domain+"-"+_block+"-"+_melk+"-"+_build+"-"+_apar+"-"+_senfi+"/pic"+i+".png");
if(img.exists())
{
Bitmap bit = BitmapFactory.decodeFile(img.getAbsolutePath());
}
}
GridView gridView = (GridView) findViewById(R.id.gridview);
gridView.setAdapter(new ImageAdapter(this));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {
Toast.makeText(getBaseContext(),
"pic" + (position + 1) + " selected",
Toast.LENGTH_SHORT).show();
}
});
}
public class ImageAdapter extends BaseAdapter
{
private Context context;
public ImageAdapter(Context c)
{
context = c;
}
//---returns the number of images---
public int getCount() {
return numberOfImages;
}
//---returns the ID of an item---
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
//---returns an ImageView view---
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(185, 185));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(7, 7, 7, 7);
} else {
imageView = (ImageView) convertView;
}
/**/
imageView.setImageResource(imageIDs[position]);
/**/
return imageView;
}
}
}
please help how i can use image in this class(adapter).
If you want to show images from sdcard into your grid view use any imageloader library
Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader
then you need to create a string array or a model class instead of that integer array.
Please refer the below tutorials.
http://wptrafficanalyzer.in/blog/loading-thumbnail-images-in-a-gridview-and-opening-original-images-in-alertdialog-using-media-content-providers/
replace
public int getCount() {
return numberOfImages;
}
with
public int getCount() {
return imageIDs.length();
}
First properly explain what do want to set Drawable or Bitmap?
If Bitmap then this is how you should set bitmap(make a list of bitmaps and then):
imageView.setImageBitmap(bitmaps[position]);
if Drawable then(make list of drawable id's)
imageview.setImageResource(drawables[position]);
This is how make bitmap list:
ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
File dir = new File(Environment.getExternalStorageDirectory()
+ "/momayezi/"+_area+"-"+_domain+"-"+_block+"-"+_melk+"-"+_build+"-"+_apar+"-"+_senfi);
File[] files = dir.listFiles();
numberOfImages=files.length;
for (int i=1;i<=numberOfImages;i++)
{
File f = new File("/sdcard/momayezi/"+_area+"-"+_domain+"-"+_block+"-"+_melk+"-"+_build+"-"+_apar+"-"+_senfi+"/pic"+i+".png");
Bitmap bmp = BitmapFactory.decodeFile(f.getAbsolutePath());
if(bmp!=null){
bitmaps.add(bmp);
}
}
I have different integer array of drawables like this:
Integer[] imagesR = {
R.drawable.albacoretuna, R.drawable.almonds
};
Integer[] imagesACE = {
R.drawable.captopril, R.drawable.lisinopril, R.drawable.vasotec
};
Each integer array should only display which is based on user's click.
Below is what I have tried:
Gallery gallery = (Gallery) findViewById (R.id.gallery3);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String value = extras.getString("medication");
if( value.equals("Angiotensin II Receptor Blockers") ){
header.setText("Angiotensin II Receptor Blockers");
note.setText(R.string.receptorblockers);
gallery.setAdapter(new ImageAdapter.IMAGE_SET_ONE);
}
else if( value.equals("Angiotensin Converting Enzyme (ACE) Inhibitors") ){
header.setText("Angiotensin Converting Enzyme (ACE) Inhibitors");
note.setText(R.string.aceinhibitorsdescription);
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
Integer[] mImageIds = {
};
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
// mGalleryItemBackground = a.getResourceId(
// R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
}
public ImageAdapter(Context c,Integer gallery[]) {
mContext = c;
mImageIds=gallery;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static final int IMAGE_SET_ONE = 1;
public static final int IMAGE_SET_TWO = 2;
private int mImageSet;
public void setImageSet(int imageSet) {
mImageSet = imageSet;
}
public View getView(int pos, View convertView, ViewGroup arg2) {
ImageView i;
//= new ImageView(mContext);
if (convertView == null) { // if it's not recycled, initialize some attributes
i = new ImageView(mContext);
i.setLayoutParams(new GridView.LayoutParams(85, 85));
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
i.setPadding(8, 8, 8, 8);
} else {
i = (ImageView) convertView;
}
if(mImageSet == IMAGE_SET_ONE) {
// load the correct image in...
Integer[] imagesACE = {
R.drawable.captopril, R.drawable.lisinopril, R.drawable.vasotec
};
i.setImageResource(imagesACE[pos]);
} else if(mImageSet == IMAGE_SET_TWO) {
// load the correct image in...
Integer[] imagesR = {
R.drawable.albacoretuna, R.drawable.almonds
};
i.setImageResource(imagesR[pos]);
}
//i.setImageResource(mImageIds[arg0]);
return i;
}
}
But I can't seem to figure out how to accomplish this correctly. Has anybody already tried something like this? Can you help me finish this? I'd appreciate your help. Thanks.
1) change the constructor of your ImageAdapter to be like this :
public ImageAdapter(Context c,int imageSet) {
this.mContext = c;
this.mImageSet=imageSet;
}
2) and when you try to set the adapter to your Gallery instance , use this code :
//case to display drawables in array1
gallery.setAdapter(new ImageAdapter(YourActivity.this, ImageAdapter.IMAGE_SET_ONE));
//case to display drawables in array2
gallery.setAdapter(new ImageAdapter(YourActivity.this, ImageAdapter.IMAGE_SET_TWO));
i am not able to access my folder Diary in which images are saved,
i want to display all the images from this folder into gallery,
please give some suggestion how to do it
//get the gallery view---------------------------------------------------------------------
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this, SDCard()));
//displaying first image on image view
Bitmap bm = BitmapFactory.decodeFile( ((List<String>) tFileList).get(0).toString());
picView.setImageBitmap(bm);
msg="first image of gallry";
showToastMessage(msg);
g.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
Bitmap bm = BitmapFactory.decodeFile( ((List<String>) tFileList).get(position).toString());
picView.setImageBitmap(bm);
}
});
}
private List<String> SDCard()
{
tFileList = new ArrayList<String>();
try
{
File dir = Environment.getExternalStorageDirectory();
File f = new File( dir, "/Diary/");
File[] files=f.listFiles();
for(int i=0; i<files.length; i++)
{
File file = files[i];
tFileList.add(file.getPath());
}
}
catch(Exception e)
{
e.printStackTrace();
msg="Folder Not Found";
showToastMessage(msg);
}
return tFileList;
}
public class ImageAdapter extends BaseAdapter
{
int mGalleryItemBackground;
private Context mContext;
private List<String> FileList;
public ImageAdapter(Context c, List<String> fList)
{
mContext = c;
FileList = fList;
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground,0);
a.recycle();
}
public int getCount()
{
return FileList.size();
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return (position);
}
public View getView(int position, View convertView,ViewGroup parent)
{
ImageView i = new ImageView(mContext);
Bitmap bm = BitmapFactory.decodeFile(
FileList.get(position).toString());
i.setImageBitmap(bm);
i.setLayoutParams(new Gallery.LayoutParams(70,50));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
what to do in this case,where i am going wrong
I'm trying to get all of the image that stored in sdcard to show in a gallery view by the code below. But when I use ImageFilter nothing shows up, just a blank screen without any error. Any suggestion?
public class Galmix extends Activity {
/** Called when the activity is first created. */
private Gallery g;
private ImageView imv;
private Uri[] mUrls;
String[] mFiles=null;
class ImageFilter implements FilenameFilter
{
public boolean accept(File dir, String name)
{
return (name.endsWith(".JPG"));
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File images = new File("/sdcard/");
File[] imagelist = images.listFiles(new ImageFilter());
// File[] imagelist = images.listFiles();
// File[] imagelist = images.listFiles(new FilenameFilter(){
// #Override
// public boolean accept(File dir, String name){
// return ((name.endsWith(".JPG")));
// }
// });
// File images = new File(Environment.getExternalStorageDirectory().toString());
// images.mkdirs();
// File[] imagelist = images.listFiles();
mFiles = new String[imagelist.length];
for(int i= 0 ; i< imagelist.length; i++){
mFiles[i] = imagelist[i].getAbsolutePath();
}
mUrls = new Uri[mFiles.length];
for(int i=0; i < mFiles.length; i++){
mUrls[i] = Uri.parse(mFiles[i]);
}
// i = (ImageView)findViewById(R.id.ImageView01);
// i.setImageResource(mImageIds[0]);
g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this));
g.setFadingEdgeLength(40);
// g.setOnItemClickListener(new OnItemClickListener() {
// public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// imv.setImageURI(mUrls[position]);
// }
// });
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = a.getResourceId(R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
}
public int getCount() {
return mUrls.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageURI(mUrls[position]);
i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
}
I would suggest that u make use of MediaStore . Also check for permissions in ur manifest file
Did you check that File images = new File("/sdcard/"); is returning the actual sdcard root folder? Try using File images = Environment.getExternalStorageDirectory(); instead.
Also, add a line Log.d ("Galmix", mFiles[i]); after mFiles[i] = imagelist[i].getAbsolutePath(); so you know if you are getting the file list or not.
Also, try
return (name.toUpperCase().endsWith(".JPG"));
This might be helpful:
Drawable mImage;
// you can use loop over here
mImage = Drawable.createFromPath("pathName");
//create one Imageview & set its resource mImage
i have a question about using GalleryView.
At first, i set five "default images" to show from drawable directory.
But after, i want to run an Async Task in which i download the images, save them and show them in the gallery.
For that i created the following Adapter:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private ArrayList<Integer> mImageIds = new ArrayList<Integer>();
private ArrayList<Drawable> mImageDrawables = new ArrayList<Drawable>();
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
public void setPlaces(int count) {
for (int i = 0; i < count; i++) {
mImageIds.add(R.drawable.tournoimg);
mImageDrawables.add(null);
}
}
public void setDrawable(String resource, int position) {
Drawable image = Drawable.createFromPath(resource);
mImageDrawables.add(position, image);
}
public int getCount() {
return mImageIds.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
if (mImageDrawables.get(position) == null)
i.setImageResource(mImageIds.get(position));
else
i.setImageDrawable(mImageDrawables.get(position));
i.setLayoutParams(new Gallery.LayoutParams(60, 78));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
}
and the following Async Task
private class FillImages extends AsyncTask<ArrayList<Place>, Void, Void> {
protected Void doInBackground(ArrayList<Place>... listplaces) {
ArrayList<Place> places = listplaces[0];
Iterator<Place> it = places.iterator();
int position = 0;
while (it.hasNext()) {
Place p = it.next();
saveImage(p.getImage(), p.getURLImage());
// Gallery g = (Gallery) findViewById(R.id.gallery);
mImageAdapter.setDrawable(p.getImage(), position);
position++;
mImageAdapter.notifyDataSetChanged();
}
return (null);
}
But when i run it i have this error:
Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Any idea?
Thanks
You should implement onPostExecute() and move any code that interacts with the UI (perhaps notifyDataSetChange()) to that method. Android requires that interaction with the GUI happen from the UI thread.
For that you have to put this code into onPostExecute() method of Async task :
ArrayList<Place> places = listplaces[0];
Iterator<Place> it = places.iterator();
int position = 0;
while (it.hasNext()) {
Place p = it.next();
saveImage(p.getImage(), p.getURLImage());
// Gallery g = (Gallery) findViewById(R.id.gallery);
mImageAdapter.setDrawable(p.getImage(), position);
position++;
mImageAdapter.notifyDataSetChanged();
}