I am designing an Android application which will be displaying some news that will be retrieved from a remote URL in xml format, say http://adomain/latest.xml
The XML file has the following format:
<articles>
<article>
<id>6</id>
<title>A sample title</title>
<image>http://adomain/images/anImage.jpg</image>
<lastupdate>1326938231</lastupdate>
<content><![CDATA[Sample content]]></content>
</article>
...
</articles>
I have created an Updater Service which listens to Connectivity Changes and when the system has a connection over the internet, it tries to download the xml file. Then parse it and save data. The Updater runs on a separate thread, every 10 minutes.
My question is:
What is the best way to handle the images?
a) Should I perform lazy loading on images when a news item is displayed
OR
b) Should I download the image when I parse the xml file?
I recommend lazy loading as the news item is displayed, so you don't use excessive bandwidth (and potentially cost for the user). No point in downloading images if the user never wants to look at them.
for images, I think you always follow lazy loading because, image loading may take some time, and also an efficient lazy loader can help you to avoid any future memory issue.
Just fetch <Image> tag data from your XMl.
String imgURL = your <Image> value;
ImageView imageView = new ImageView(this);
Bitmap bmp = BitmapFactory.decodeStream(new java.net.URL(imgURL).openStream());
imageView.setId(i);
imageView.setImageBitmap(bmp);
This will work to set image and you also get image in "bmp".
Android provide directly show image from URL:
For Store Image to Sd Card:
File file = new File (pathOfSdCard, iamgeName);
try {
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Put Line to your AndroidMenifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
This all i using in my app. it works fine.
I hope this will helps you a lot.
Related
I need to download images from server and store as thumbnails directly.
and for display images also i need to use images from .thumbnails folder directly. i am not getting how to create and save images as .thumbnail . and how to use images from that .thumbnail file.i searched online but everywhere only this below code present.
Bitmap thumb = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(file.getPath()), width, height);
any help?
Please check below code which helps you.
Follow below steps:
Calculate the maximum possible inSampleSize that still yields an image larger than your target.
Load the image using BitmapFactory.decodeFile(file, options), passing inSampleSize as an option.
Resize to the desired dimensions using Bitmap.createScaledBitmap().
Now you have your bitmap ready and you can save it any where using the following code
Bitmap thumbnail;
File thumbnailFile = ...;
FileOutputStream fos = new FileOutputStream(thumbnailFile);
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
hope it helps you and save your time.
Or use Glide library which store image as a full image and 1 thmbnail image which is power caching library which loads image quickly and once download image after load image from cache not from network.
Below is a Glide link please read it advantages and features and after used into your applications.
https://github.com/bumptech/glide
My application takes pictures via camera intent. How should I display their small size version in a grid view for viewing purpose. Should I create their thumbnails and store them in cache or external storage Or should I use the thumbnails created by Default Gallery application. My pictures are stored in external storage so I am expecting that Default Gallery Application would make their thumbnails automatically. If yes, then how should I map each image with the thumbnail created by Default Gallery Application.
Well, I have found that Async class could handle the memory usage scenario.
The relevant link is: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
Well, I have got an answer
public Bitmap getbitpam(String path) {
Bitmap imgthumBitmap = null;
try {
final int THUMBNAIL_SIZE =300 ;
FileInputStream fis = new FileInputStream(path);
imgthumBitmap = BitmapFactory.decodeStream(fis);
imgthumBitmap = Bitmap.createScaledBitmap(imgthumBitmap,
THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream bytearroutstream = new ByteArrayOutputStream();
imgthumBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytearroutstream);
} catch (Exception ex) {
}
return imgthumBitmap;
}
However, this is taking a lot of RAM. I Have also found a strange behavior. That as I am scrolling in grid view, it is taking more RAM. The growth in memory used is cumulative and finally the app is crashing due to Memory_Low exception. Any workaround for it??
Got answer for second problem too:-- Async class.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am new to android. I have some images stored at some path on server. In my application i want that the images should be loaded once from the server and next time the user opens the application the app should not load it again. Please tell me how should i store these images. Please help.
For store image on app cache or internal storage(sdcard0) you can use library like Universal-Image-Loader , Aquery, Picasso etc.
These library helps you to make image loading faster, save images on cache memory or data.
You can download this library from here
Universal Image Loader : https://github.com/nostra13/Android-Universal-Image-Loader (Just import library in your workspace and use it)
Aquery : https://github.com/androidquery/androidquery (You can use Aquery-android.jar file for use Aquery)
Universal image loader has more functionality than Aquery.
Hope this helps you out.
You can store image in file. You need only set unique name to image file, an example md5 hash of url.
You can save image in file use follow code:
File file = File(filePath)
try {
FileOutputStream outStream = FileOutputStream(file)
bitmap!!.compress(Bitmap.CompressFormat.PNG, 100, outStream)
outStream.flush()
outStream.close()
}catch(e: Exception){
Log.e("log", "error save image to cache $filePath")
}
}
and read from file:
try{
BitmapFactory.Options optionsBitmapFactory = BitmapFactory.Options()
optionsBitmapFactory.inPreferredConfig = Bitmap.Config.ARGB_8888
Bitmap bitmap = BitmapFactory.decodeFile(filePath, optionsBitmapFactory)
}catch(e: Exception){
Log.e("log", "error load image from cache $filePath")
}
There are several image loader libraries for it. One of them is Universal Image loader and Glide
You can refer this Picasso v/s Imageloader v/s Fresco vs Glide
It will store images in cache and next time will provide image from cache. For server images Universal Image loader and Glide library is highly recommended. You can also set placeholder image.
There are two way :-
Do cache images for an example just look at picaso library.
//Code how to use picaso :-
/Initialize ImageView
ImageView imageView = (ImageView) findViewById(R.id.imageView);
//Loading image from below url into imageView
Picasso.with(this)
.load("YOUR IMAGE URL HERE")
.into(imageView);
Store images to storage either external or internal and fetch second time from storage. you can use again picaso callback to save bitmap cio.economictimes.indiatimes.com
There are some third party libraries available for these purpose which would save some development effort.
Below are some of them:
Picasso
Glide
Universal image loader
Here is some libs for loading image from URL and it will store image in to memory as cache.
UIL : flexible and highly customizable instrument for image loading, caching and displaying. It provides a lot of configuration options and good control over the image loading and caching process.
PICASSO :
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
First you must make sure your application has permission to write to the sdcard. To do this you need to add the uses permission write external storage in your applications manifest file. See Setting Android Permissions
Then you can you can download the URL to a file on the sdcard. A simple way is:
URL url = new URL ("file://some/path/anImage.png");
InputStream input = url.openStream();
try {
//The sdcard directory e.g. '/sdcard' can be used directly, or
//more safely abstracted with getExternalStorageDirectory()
File storagePath = Environment.getExternalStorageDirectory();
OutputStream output = new FileOutputStream (new File(storagePath,"myImage.png"));
try {
byte[] buffer = new byte[aReasonableSize];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
} finally {
output.close();
}
} finally {
input.close();
}
EDIT : Put permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I am using the following method to get an image from a given URL.
protected Bitmap doInBackground(String... urls) {
String urlDisplay = urls[0];
Bitmap scaledImage = null;
try {
InputStream in = new java.net.URL(urlDisplay).openStream();
scaledImage = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), 380, 250, false);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return scaledImage;
}
Is there anyway to get a scaled image without having to download the full sized image first? It would greatly increase load times.
Sadly, server side manipulations can't be done and before downloading, there's no way to scale it. However, if you still want to save the load time on consecutive refreshes, then you probably can go ahead with saving the bitmap received in a shared preference. This way if the image is already stored in the shared preference, you don't need to download it again and apply scaling to it.
CAUTION: In case the image you are downloading is changing after a while, you can put a check to download it after every "n" (say 7) days and replace the existing stored image with this one.
NOTE: Though there are many answers already available which tells you how to store the image bitmap in Shared Preference / local storage, let me know in case you need that info/ code-snippet too.
You can not perform bitmap operations on a remote image without downloading it first. Therefore there is no way to do what you want to do unless the server you are getting the image from supports different image sizes or a parameter to resize it on the server side.
I am using following example to display internet images in my activity.
http://developer.android.com/resources/tutorials/views/hello-gridview.html
In custom image adapter I'm directly loading images from internet and assigning it to imageview.
Which shows images in gridview and every thing works fine but it is not efficient way.
When ever i scroll gridview it again and again loads images and thats why gridview scrolls very slow
Is there caching or some useful technique available to make it faster?
Create a global and static method which returns a Bitmap. This method will take parameters: context,imageUrl, and imageName.
in the method:
check if the file already exists in the cache. if it does, return the bitmap
if(new File(context.getCacheDir(), imageName).exists())
return BitmapFactory.decodeFile(new File(context.getCacheDir(), imageName).getPath());
otherwise you must load the image from the web, and save it to the cache:
image = BitmapFactory.decodeStream(HttpClient.fetchInputStream(imageUrl));
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(context.getCacheDir(), imageName));
}
//this should never happen
catch(FileNotFoundException e) {
if(Constants.LOGGING)
Log.e(TAG, e.toString(), e);
}
//if the file couldn't be saved
if(!image.compress(Bitmap.CompressFormat.JPEG, 100, fos)) {
Log.e(TAG, "The image could not be saved: " + imageName + " - " + imageUrl);
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_cached_image);
}
fos.flush();
fos.close();
return image;
preload a Vector<SoftReference<Bitmap>> object with all of the bitmaps using the method above in an AsyncTask class, and also another List holding a Map of imageUrls and imageNames(for later access when you need to reload an image), then set your GridView adapter.
i recommend using an array of SoftReferences to reduce the amount of memory used. if you have a huge array of bitmaps you're likely to run into memory problems.
so in your getView method, you may have something like(where icons is a Vector holding type SoftReference<Bitmap>:
myImageView.setImageBitmap(icons.get(position).get());
you would need to do a check:
if(icons.get(position).get() == null) {
myImageView.setImageBitmap(defaultBitmap);
new ReloadImageTask(context).execute(position);
}
in the ReloadImageTask AsyncTask class, simply call the global method created from above with the correct params, then notifyDataSetChanged in onPostExecute
some additional work may need to be done to ensure you don't start this AsyncTask when it is already running for a particular item
You will need to implement the caching yourself. Create a proxy class that will download the images. In the getView ask this class to download an image by passing a url. In the proxy class create a HashMap that will map a url to a Bitmap. If the key for the passed url doesn't exist, download the image and store it. Otherwise returned the stored bitmap converted to an imageView.
Of course you can't afford to store as many images as you like. You need to set a limit, for example 10 images, based on the image size you expect to have. When the limit is exceeded, you need to discard old images in the favor of new ones.
You could try DroidFu. My app uses the ImageCache. There's also some manner of web-based imageview or something of the sort in the library. See in particular WebImageView and WebGalleryAdapter: http://mttkay.github.com/droid-fu/index-all.html
Edited to add: The droid-fu project is deprecated in favor of Ignition. https://github.com/mttkay/ignition