My app takes a photo using the camera. It then gets the URI, then the path of that photo and stores the path in a SQLite database. All of that seems to work fine, however when I go to view the images as bitmaps, this code only shows the same image (the last one) for every record (all others informations on each record displays correctly).
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
mPhoto = BitmapFactory.decodeFile(timage.toString(), options);
viewHolder.img_image = (ImageView) convertView.findViewById(R.id.image);
viewHolder.img_image.setImageBitmap(mPhoto);
This is where I get the information for timage, and the rest of the record details :
public ArrayList<ProductModel> _productlist = new ArrayList<ProductModel>();
ArrayList<ProductModel> product_list = db.getProducts();
for (int i = 0; i < product_list.size(); i++) {
String tidno = product_list.get(i).getIdno();
System.out.println("tidno>>>>>" + tidno);
timage = product_list.get(i).getImage();
System.out.println(timage);
String tname = product_list.get(i).getProductname();
String tdesc = product_list.get(i).getproductdesc();
ProductModel _ProductModel = new ProductModel();
_ProductModel.setIdno(tidno);
_ProductModel.setImage(timage);
_ProductModel.setProductname(tname);
_ProductModel.setproductdesc(tdesc);
_productlist.add(_ProductModel);
}
totalrecords.setText("Total Records :-" + _productlist.size());
listview.setAdapter(new ListAdapter(this));
db.close();
The first 3 lines are based on Vino's answer from Suggestions to avoid bitmap Out of Memory error - scaling the images to get rid of the out of memory errors I was receiving otherwise.
mPhoto is simply a Bitmap variable, timage is the images paths (which prints onto the console correctly).
Anyone able to give me a hint in the right direction to get the app showing every image, rather than just the last one taken ?
That variable timage is conserving the value of the last item in the for iteration.
for (int i = 0; i < product_list.size(); i++)
{
//...
timage = product_list.get(i).getImage();
//...
}
So after exiting the loop timage will have the value of the last item. And of course here
mPhoto = BitmapFactory.decodeFile(timage.toString(), options);
it's being used for all your images. Shouldn't you be using _ProductModel.getImage() instead?
Related
I want to take image in integer Array just like when you take R.drawable.img in integer array.
e.g : int[] images = {R.drawable.a , R.drawable.b , R.drawable.c , R.drawable.d};
I want same like this when you take image from server.
Declaration of Array:
String images[] = new String[1000];
Get Image from server and sets it to int array which is not happening.
public void onResponse(String response) {
Log.d("TAG", "Message Response: " + response.toString());
hideDialog();
try {
JSONObject jsonObj = new JSONObject(response);
boolean error = false;
p = jsonObj.getJSONArray("response");
for (int i = 0 ; i < p.length(); i++) {
JSONObject c = p.getJSONObject(i);
String profilepicture = c.getString("profile_picture");
byte[] decodedString = Base64.decode(profilepicture, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
Drawable drawable = new BitmapDrawable(getResources(),decodedByte);
images[i] = drawable;
}
The drawable values is android.graphics.drawable.BitmapDrawable#269a3b6d. But it not sets on the integer array.
You're getting a Drawable. You can't save a Drawable to an integer array or a String array- you have to make it a Drawable array. This approach is really NOT recommended btw- you're storing all of your images in memory, which will take a lot of memory. If its a non-trivial number you'll likely hit an OOM exception. For that matter, sending down all these images as Base64 encoded strings is not recommended either. The better way to do things is to have the server send down a URL of the image to download, and to download it only when you're sure you need it.
create an array for drawables then it would work, and you can get the image from that array via its integer index. but the case you are trying is that, you would have got that number BitmapDrawable#269a3b6d from debugging the code? right? this is a reference to the object in the memorey and not an integer! so don't try to put it in the integer array.
now either make your array type to drawable or change your scenario!
I am developing an app that once a button is clicked I go to a new activity where 3 random images are set to an imageView. If the user does not like the 3 images selected, they can then click a button to generate 3 new random images. I am having two problems...
I have the imageView set to a specific size but when the images show up they are sometimes smaller and are showing horizontally. I would like them to show up vertically and all as the size of the imageView. How do I change the code to do this?
I am getting the new images to show up when I click the button but I am getting an error saying that I am running out of memory after I do it a few times. How do I change the code so I stop using all my memory?
Here is my code
public ImageView shirts;
public ImageView pants;
public ImageView shoes;
Button reload;
private Bitmap currentBitmap = null;
String[] projection = new String[]{
MediaStore.Images.Media.DATA,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.suggested_outfit);
shirts = (ImageView)findViewById(R.id.shirtImage);
pants = (ImageView)findViewById(R.id.pantsImage);
shoes = (ImageView)findViewById(R.id.shoesImage);
shirts.setImageBitmap(getImage());
pants.setImageBitmap(getImage());
shoes.setImageBitmap(getImage());
reload = (Button)findViewById(R.id.getNewOutfit);
reload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
startActivity(getIntent());
}
});
}
public Bitmap getImage () {
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cur = getContentResolver().query(images,
projection,"", null, ""
);
final ArrayList<String> imagesPath = new ArrayList<String>();
if (cur.moveToFirst()) {
int dataColumn = cur.getColumnIndex(
MediaStore.Images.Media.DATA);
do {
imagesPath.add(cur.getString(dataColumn));
} while (cur.moveToNext());
}
cur.close();
final Random random = new Random();
final int count = imagesPath.size();
int number = random.nextInt(count);
String path = imagesPath.get(number);
currentBitmap = BitmapFactory.decodeFile(path);
return currentBitmap;
}
}
I read that it isn't good practice to reload the activity but I can't figure out a way to generate 3 new random images. I am open for any suggestions if there is a better way to do this.
Obtaining images through an onClick method would have to have
do {
String path = cur.getString(dataColumn);
if(path.contains("yourDirectory")){ //in your case, your image directory
imagesPath.add(path);
}
} while (cur.moveToNext());
within the requested intent/activity
Decoding Bitmap consumes much memory, on your code you decode Bitmap many times when click button maybe causes OutOfMemory. Try to decode all your Bitmap once times and save them to a list. When a click to generate random Bitmap, you create random index of the list Bitmap and retrieve object by that index. Hope this help!
you can use this utils: image loader
it has memory manager.and you can set imageview when image load completed.
Update
i know i can use array or list for it but i want to use an efficient way for it with out using arrays or collection thanks to all of you
special thanks to mussharapp
hi i want to access Imageview using its id
for example i have an imageview which is created using loop like
for(int i=1;i<10;i++) {
Imageview mv=new ImageView(this);
mv.setid(i);
// and so on for image properties
}
now i want to get all images which i have created in loop how i can get these images is there any way using id or some thing else ???
the same problem i am facing
declare a private arraylist:
private ArrayList<Imageview> images = new ArrayList<Imageview>();
then store all your views into that list:
for(int i=1;i<10;i++) {
Imageview mv=new ImageView(this);
mv.setid(i);
// and so on for image properties
images.add(mv);
}
Finally, you can get them based on position/id (since position == id):
ImageView imageView = images.get(position);
Remember to clear list when done or onDestroy().
images.clear();
Given that you are sure that the image view id's will be unique you can do something like this
//Your code
for(int i=1;i<10;i++) {
Imageview mv=new ImageView(this);
mv.setid(i);
// and so on for image properties
}
//...
List<Drawable> drawables = new ArrayList<Drawable>();
for (int i = 1; i < 10; i++) {
ImageView mv = (ImageView) findViewById(i);
drawables.add(mv.getDrawable());
}
Not sure what you are trying to do is efficient. You are probably better off with the other suggestions they have mentioned.
First you have to set Array of images with its path and then you can use it...
You can keep an array of ImageViews.
ImageView[] mImageViews = new ImageView[10];
for(int i=1;i<10;i++) {
mImageViews[i] = new ImageView(this);
}
And access these like mImageViews[2] or mImageViews[5]
I am attempting to create a music player app for a Nexus 7 tablet. I am able to retrieve music files from a specific directory as well as information that is associated with them such as title, artist, etc. I have loaded the files's titles into a clickable list view. When the user clicks on a title, it takes them to an activity that plays the associated song. I was attempting to sort the titles alphabetically and ran into a snag. When I sort just the titles, they no longer match with the correct songs. This is to be expected since I only ordered the titles and not the actual files. I attempted to modify the sorting algorithm by doing this:
//will probably only work for Nexus 7
private final static File fileList = new File("/storage/emulated/0/Music/");
private final static File fileNames[] = fileList.listFiles(); //get list of files
public static void sortFiles()
{
int j;
boolean flag = true;
File temp;
MediaMetadataRetriever titleMMR = new MediaMetadataRetriever();
MediaMetadataRetriever titleMMR2 = new MediaMetadataRetriever();
while(flag)
{
flag = false;
for(j = 0; j < fileNames.length - 1; j++)
{
titleMMR.setDataSource(fileNames[j].toString());
titleMMR2.setDataSource(fileNames[j+1].toString());
if(titleMMR.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE).compareToIgnoreCase(titleMMR2.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)) > 0)
{
temp = fileNames[j];
fileNames[j] = fileNames[j+1]; // swapping
fileNames[j+1] = temp;
flag = true;
}//end if
}//end for
}//end while
}
This is supposed to retrieve the song titles from two files, compare them, and swap the files in the File array if the first comes after the second alphabetically. For some reason, when I run the activity that calls this method, the app crashes. If I remove the + 1 from titleMMR2's data source
titleMMR2.setDataSource(fileNames[j].toString());
the app no longer crashes but the list is not in order. Again this is understandable since it compares the song titles to themselves. I don't know why the + 1 would make the program crash. It is not an array out of bounds error. There are a total of 6 .mp3 files in the directory and they are the only files in that directory. I have also tried using Arrays.sort(fileNames) but that only orders them by their file name and not song title. I also tried this:
Arrays.sort(fileNames, new Comparator<File>(){
public int compare(File f1, File f2)
{
titleMMR.setDataSource(f1.toString());
titleMMR2.setDataSource(f2.toString());
return titleMMR.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE).compareToIgnoreCase(titleMMR2.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE));
} });
That snippet also resulted in a crash. There are no errors in the java code and all appropriate classes have been imported. I'm really at a loss as to what is wrong. Any help will be appreciated and if any new info is needed I will gladly provide it. Thanks in advance.
FIXED
The correct code snip is this:
public static void sortFiles()
{
int j;
boolean flag = true;
File temp;
MediaMetadataRetriever titleMMR = new MediaMetadataRetriever();
MediaMetadataRetriever titleMMR2 = new MediaMetadataRetriever();
while(flag)
{
flag = false;
for(j = 0; j < fileNames.length - 1; j++)
{
titleMMR.setDataSource(fileNames[j].toString());
titleMMR2.setDataSource(fileNames[j+1].toString());
String title1;
String title2;
if(titleMMR.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) == null)
title1 = fileNames[j].getName();
else
title1 = titleMMR.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if(titleMMR2.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) == null)
title2 = fileNames[j+1].getName();
else
title2= titleMMR2.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if(title1.compareToIgnoreCase(title2) > 0)
{
temp = fileNames[j];
fileNames[j] = fileNames[j+1]; // swapping
fileNames[j+1] = temp;
flag = true;
}//end if
}//end for
}//end while
}
I have created a database of objects. Each of these objects contains two strings and two bitmaps. When I do a getAllContacts() call to my database, the loading takes quite a while. For me its not a problem, but for the end-users, this would be annoying. When I load an object I set this options to my bitmaps saying:
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Which will shrink the Bitmaps to 1/8 of the original height and width. But still, it takes around 10-15 seconds to load 50 records and fill this into a ListView. Is there any way I can check if the object I try to load is in the memory, also called paging? Or maybe I can load the Bitmaps, when the users presses one of the items in the ListView?
Thanks in advance!
You set the sample size but it's still reading (I assume) large images. Why not set your bitmaps so that they are already small and then you can read small images without the scale factor applied?
I had a listView in my own code doing similar things and it was very slow until I wrote code to shrink each new image as it was created and then always just dealt with small images. And the code lived happily ever after.
The solution:
So, finally I found a solution to my problem. Instead of getting all of the Bitmaps when I do a getAllContact() call, the bitmap's is loaded when the user presses a row in the ListView This is whats done in the setOnClickListener method in CustomAdapter for my ListView
String PCN = cases.get(position).getCaseNumber();
int tempPCN = Integer.valueOf(PCN);
tempBitMapArray = dbHandler.getFinger(tempPCN);
Bitmap left = tempBitMapArray[0];
Bitmap right = tempBitMapArray[1];
ByteArrayOutputStream bs1 = new ByteArrayOutputStream();
left.compress(Bitmap.CompressFormat.PNG, 100, bs1);
ByteArrayOutputStream bs2 = new ByteArrayOutputStream();
right.compress(Bitmap.CompressFormat.PNG, 100, bs2);
And the getFinger(...) method:
public Bitmap[] getFinger(int pcn) {
Bitmap[] fingers = new Bitmap[2];
String SQLQUERY = "SELECT " + RIGHTFINGER + ", " + LEFTFINGER +" FROM " + TABLE_CASES + " WHERE " + KEY_ID + "=" + pcn + ";";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(SQLQUERY, null);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 2;
if (cursor.moveToFirst()) {
do {
byte[] blob1 = cursor.getBlob(cursor.getColumnIndexOrThrow("leftFinger"));
Bitmap bmp1 = BitmapFactory.decodeByteArray(blob1, 0, blob1.length, options);
byte[] blob2 = cursor.getBlob(cursor.getColumnIndexOrThrow("rightFinger"));
Bitmap bmp2 = BitmapFactory.decodeByteArray(blob2, 0, blob2.length, options);
fingers[0] = bmp1;
fingers[1] = bmp2;
return fingers;
} while(cursor.moveToNext());
}
return null;
}
I hope this example will give other people a pinpoint in the right direction.