After an image is selected and the onActivityResult is called, I create a thumbnail to update the original activity view. I also scale the image down and store it in a temporary folder from where it is then picked up by the sync adapter to be uploaded to the server.
To store the scaled-down version of the image I use AsyncTask. The problem is that the file storing routine is slow and can take up to 10 seconds.
File pictureFile = getOutputMediaFile();
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close;
While image storing is in process, there is a high chance that users can click to upload the image before the storing routine is done. So, I either have to come up with a way to keep retrying the action until the image file is ready, or make storing routine part of the UI thread which will still make users wait, but this time for the thumbnail to appear.
Has anyone done something similar? Are there patterns for handling similar situations etc?
I have done something like this in one of my application, You can do the saving of the image in a async task and, have an loading spinner (On action bar or anywhere you like) until the file is been saved,
And also by the time async task runs and finished up the saving of the file, You can enable the upload button.
Related
So I am displaying video files from specific folder when the folder is selected but in the video list I am showing file name with the video thumbnail and that's where the problem starts i am using this way to get the thumb
Bitmap bmThumbnail = ThumbnailUtils.
extractThumbnail(ThumbnailUtils.createVideoThumbnail(info.getFilename(),
MediaStore.Video.Thumbnails.MINI_KIND), 60, 60);
if(bmThumbnail != null) {
imageView.setImageBitmap(bmThumbnail);}
and even if I don't set the bitmap or not the process is taking way too much time to open the new fragment whereas just displaying the name is smooth if I call the following bitmap it takes around 6-7 sec to display the list. The following thing are happening in the adapter as I test the app in adapter then recycler view
so I would like to know what is the best way to do it .
For using image loader i need the url which is not there as i am getting the album art using the file url but it will not produce the album art url directly.
Dealing with images and videos like that takes time. Particularly when dealing with a large group of them. It's unlikely you can speed up the operation but you can make it so your application doesn't have to wait for it by sending it to the background. I recommend Kotlin coroutines if you are up for converting to Kotlin. Otherwise I recommend making a thumbnail work manager
public class VideoThumbnailWorker extends Worker {
}
We are developing an android application for document scanner.
This application is having feature to edit the image like adding magic color, grey mode, Black white,etc. this application has the option to scan "N" number of pages and convert it into PDF at the end.
The flow of the application is First activity is taking photo of the image and the second activity for cropping the image and third activity for editing the image like applying magic color, grey mode and black/white conversion. And in the third activity we have add button,clicking on it will go back to first activty and the same process continues.Once all the images scanned, third activity is haivng done button, clicking on it will create pdf and close the application.
Now the problem is after scanning some 35 pages, it throws out of memory error because we are always keeping original and modified bitmaps as List in the code because its possible for the user to go back to previous images and edit it. At that time i need original version of the image also.
Could you please help me out on the below items.
1) where to keep the bitmaps in this scenario?
2) Is there any way to store the image in the external card and reading it everytime on need basis?
Thanks in advance.
Store the bitmap as cache.
out = new FileOutputStream(filename);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
It is prefetable to use cache directory to store such a file rather than storing it persistently. getCacheDir() will return the path to the directory.
I want fresco to download and save images to sd-card when connected to internet.
Later when offline and even if cache is cleared, still I need fresco to show saved images.
Is this possible? If yes, how?
Simply saving images to disk cache doesnt seem to work when cache is cleared.
Fresco caches images for you. If you are offline, the images should still be displayed. You should not need to do anything.
However, when the cache is cleared (e.g. when the user presses the button or when device space is low), images are obviously deleted from the cache - which is the desired behavior that should not be changed.
There are 2 options: save selected items, move the cache
Save selected items
If you want to persist selected images (e.g. a "Save" button), you can get the encoded image and save it somewhere on the device.
You should not do this for all images since they will be on the disk 2 times and clearing the cache / uninstalling the app will leave 1 copy on the device.
Something like this could work:
DataSource<CloseableReference<PooledByteBuffer>>
dataSource = Fresco.getImagePipeline().fetchEncodedImage(imageRequest, callerContext);
dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
#Override
protected void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
CloseableReference<PooledByteBuffer> encodedImage = dataSource.getResult();
if (encodedImage != null) {
try {
// save the encoded image in the PooledByteBuffer
} finally {
CloseableReference.closeSafely(encodedImage);
}
}
}
#Override
protected void onFailureImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
// something went wrong
}
}, executorService);
}
More information on how to use the pipeline to get the encoded image: http://frescolib.org/docs/using-image-pipeline.html
Move the cache
Keep in mind that this will persist the cache when it is moved to an external directory, so be careful since this will leave files when the app is uninstalled.
Fresco also allows you to supply a custom DiskCacheConfig and you can create a new DiskCacheConfig.Builder and call setBaseDirectoryPath(File) to change the path to a different folder (e.g. one on the SD card) and you can also change the directory name with setBaseDirectoryName(String)
More information on how Fresco does caching: http://frescolib.org/docs/caching.html
You need to manually save the images to disk when downloaded. When displaying the images, check if image is in disk: if its not, download from url (and save to disk).
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.
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