I am working on an Android application in which I am getting image url from the server. Now I have to do save that image url and image file in my local storage, because for the first time if I want to check if the same url is available in my internal storage then it will get that image file from my local storage, if not then it will first save that image url reference and image file in my internal storage.
My code is given below. I wish to save image url and image file in my internal storage and according to the above conditions.
new DownloadImageTask((ImageView) view.findViewById(R.id.imageViewProfile))
.execute(imageURL);
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
If you are looking for saving image once and reusing it many times this may help you Google Volley Library. Universal Image Loader which is widely used after Volley.
EDIT :
Now there are bunch of libaries which are so popular.
Picasso
Glide
Fresco
Choose according to your requirement.Here is comparison.
You can store url in table and check your condition whatever
download file from server and store it in external/internal storage.
Related
I have to convert an Image into base 64 and upload user_image into server using camera. After uploading into server what I have to show is in ImageView.
After upload into server the image is not changing. While I am closing the app and opening again then only it is changing the image.
public void onCropImageClick()
{
Bitmap cropped = mCropImageView.getCroppedImage(550, 550);
if (cropped != null)
//this is imageView
user_imageView.setImageBitmap(cropped);
//here i am converting image to base64 ByteArrayOutputStream stream = new
ByteArrayOutputStream();
cropped.compress(Bitmap.CompressFormat.JPEG, 100, stream);
base64Image = Base64.encodeToString(stream.toByteArray(), 0);
// here I am upload image into server
sendImageUrl(base64Image);
}
public void sendImageUrl(String base64Image) {
// progress_bar.setVisibility(View.VISIBLE);
System.out.println("Image profile came here:4 sendImageUrl");
uploadImage(base64Image);
}
I have got a solution for this .
i was a problem of Glide and Picasso image loader .
We need clear Cache every time before setting image into image view .
add this before adding image
CacheClearAsyncTask task = new CacheClearAsyncTask();
task.execute();
class CacheClearAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Glide.get(getApplicationContext()).clearDiskCache();
return null;
}
#Override
protected void onPostExecute(Void result) {
Glide.get(getApplicationContext()).clearMemory();
}
}
I'm workin with Volley API in my WebServices, and then I'll write the data in with SQLITE.
Webservices that comes with a JSON with many itens, each of then has data and a image, and I need to keep this image in my cache to display offline in a ListView and later on a detail screen. In the future the user will clean these itens and clear the imagens of them too.
Well, how can I save these images in my local DB and link with each Item that I have from the JSON?
I will be, in 90% of the time, offline. I will only stay online for synchronizing and download the updated server items.
For dealing with images in Android the benchmark is to use Picasso library. It takes care of:
Handling ImageView recycling and download cancelation in an adapter;
Complex image transformations with minimal memory use;
Automatic memory and disk caching.
Besides that, if you're going to display images in lists and need animation to enhance your UI, I strongly recommend changing from ListView to RecyclerView. It is not recommended to store the images in the DB, you would lose time converting this from/to blobs (check here and here). Said that, what I suggest is:
Use Picasso to load the images from the URL provided in the JSON;
Implement a Custom target to handle the image file downloaded by Picasso;
Save the image in a folder inside your app directory;
Use RecyclerView to display the images; (optional)
If you need a project example where those things are done, you can check this. In this project I follow the approache I've described above. You can download the app from the store and see how it will download the images.
Quicky-guide:
To use Picasso add this to you module's gradle file: compile 'com.squareup.picasso:picasso:2.5.2'
Create a class that implements import com.squareup.picasso.Callback;:
public class ImageWarehouse implements Callback {
private static final String TAG = "ImageWarehouse";
private String mDirectory;
private String mFileName;
private ImageView mContainer;
#Inject
App mApplication;
public ImageWarehouse(String fileName, ImageView container, String directory) {
this.mFileName = fileName;
this.mContainer = container;
this.mDirectory = directory;
this.getStorageDir();
}
#Override
public void onSuccess() {
if (this.isExternalStorageWritable()) {
final Bitmap bitmap = ((BitmapDrawable) this.mContainer.getDrawable()).getBitmap();
new AsyncTask<Void, Void, File>() {
#Override
protected File doInBackground(Void... params) {
File file = null;
try {
file = new File(ImageWarehouse.this.getStorageDir().getPath().concat("/").concat(ImageWarehouse.this.mFileName.concat(Constants.MEDIA_EXTENSION)));
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
ostream.close();
} catch (Exception e) {
Log.e(TAG, "External Storage is not available");
}
return file;
}
}.execute();
} else {
Log.e(TAG, "External Storage is not available");
}
}
#Override
public void onError() {
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
public File getStorageDir() {
File file = new File(Environment.getExternalStorageDirectory(), Constants.MEDIA_DIRECTORY.concat(this.mDirectory));
if (!file.mkdirs()) {
}
return file;
}
}
Call Picasso in order to display the image in the layout and save it to the specified path:
Picasso
.load(URL)
.fit()
.centerCrop()
.into(viewHolder.cover,
new ImageWarehouse(
name,
viewHolder.cover,
Constants.MEDIA_CHARACTER
)
);
You can user Android-Universal-Image-Loader it is also cache image in memory. it is show from cache when next time same url used in imageloader for get image
see below link for complete source code of Universal Image Loader Example.
Android - Universal Image Loader
You can save your images in Sqlite as blob and can retrieve it when required. Create table as
create table sometable(id integer primary key autoincrement,photo BLOB);
And save the image as
//convert image into byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.common)).getBitmap();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] photo = baos.toByteArray();
//And now store this image
ContentValues initialValues = new ContentValues();
initialValues.put("photo",photo);
return db.insert("sometable", null, initialValues);
And retrieve image as
Cursor cur=your query;
while(cur.moveToNext())
{
byte[] photo=cur.getBlob(index of blob cloumn);
}
I use the "imgUrl" to save the URL where I download the image and "BitmapFactory" to zoom out and not waste RAM, but it takes a lot because there are several pictures, Do you know a better way?.
public class DownloadImage extends AsyncTask<Object, Void, Bitmap> {
ImageView imagen;
String imgUrl="";
Bitmap bitm;
protected Bitmap doInBackground(Object... params){
imgUrl = (String) params[0];
imagen = (ImageView) params[1];
try {
URL imageUrl = new URL(imgUrl); /*Using the URL for download the image*/
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
conn.connect();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
bitm = BitmapFactory.decodeStream(conn.getInputStream(), new Rect(0, 0, 0, 0), options);
} catch (IOException e) {
Log.e("catch", e+"");
}
return bitm;
}
protected void onPostExecute(Bitmap result){
imagen.setImageBitmap(result);
super.onPostExecute(result);
}
}
Not sure what do you want to optimize, but there are several ways to optimize the images used in an app which are fetched online.
If images are large and your app will show different sizes of it, you can store different sizes of the same image on the server, and based on the need you can download the size you need. This saves in data transfer, and makes the image loading (e.g. in lists which thumbnails) faster and more smooth.
You can obviously use a cache, usually a two level cache which uses both RAM and disk, to store downloaded image on the disk and not to download it again.
You can use different APIs to analyze the image before loading and load the size you need. This way you load the image faster and use less memory in your view/cache to hold it.
You can read more details about this here
I have a small query, is it possible to get an image dynamically every-time the app is launched over the internet and then that Image can be used to be shown on UI(via xml file)please let me know if this can be achieved in android and with any sample code.
Thanks & Regards.
In this case the best way to do it is to load image via HTTP GET, store it in Bitmap object and inject programmatically into ImageView element defined in layout.
You can't override resource image so you cant use #drawable.
Here you have loadBitmap method that loads image by url and stores it in Bitmap: How to load an ImageView by URL in Android?
Next thing is to inject it into ImageView:
ImageView image = (ImageView) findViewById(R.id.image);
Bitmap bitmap = loadBitmap("http://www.android.com/images/logo.png");
image.setImageBitmap(bitmap);
Not possible through XML.
I'd recommend having a placebo bitmap also in case there is no Internet access available at the time. Use AsyncTask when downloading.
new GetAndSetBitmap.execute(url)
private class GetAndSetBitmap extends AsyncTask<String, Void, Bitmap>
{
protected Bitmap doInBackground(String... urls)
{
Bitmap bitmap = loadBitmap(url[0]);
// Used the loadBitmap from other answer. Anything goes wrong
// load a local resource with the same dimensions.
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bm)
{
yourImageView.setImageBitMap(bm);
}
}
Guys found a better solution
try {
ImageView i = (ImageView)findViewById(R.id.image);
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
i.setImageBitmap(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I am downloading images from server into the ListView , now to perform this task i am using ImageDownloader example code. so far its working fine.
But i want to save images of ListView in a SD card but i am confused when to store the images as images are being downloaded Asynchronously and because of ViewHolder pattern its little tough for me to judge.
Once i stored it in a SD card next time i want to read it from memory only.
ImageDownload is storing bitmap in cache and fetching it from there once it gets downloaded.But the problem is its behavior is not predictable.
Sometimes it downloads from server and sometimes from cache.
so can anyone help me in finding what is the proper place to store the images in sd card once.
Modify your ImageDownloader class to save the image like this :
add a parameter to download method like :
download(String url, ImageView imageView, Boolean saveData)
make a global variable saveData in yout ID class :
private Boolean saveData;
and store in it the value given as parameter in download dmethod:
this.saveData = saveData;
and the BitmapDownloaderTask's onPostExecute method should look like this :
#Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
addBitmapToCache(url, bitmap);
if (saveData == true) {
try {
FileOutputStream out = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
} catch (Exception e) {
e.printStackTrace();
}
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with it
if (this == bitmapDownloaderTask) {
imageView.setImageBitmap(bitmap);
}
}
}
where path is the path were you want to save the image .
and next time before you want to load the image you have to see if it is already downloaded and load it from the path otherwise call ImageDownloader.
that's it! enjoy!