I am trying to pass an imageview to a non activity class that will handle looking up the image from online and then subsequently set the image. My error that I am receiving is that when trying to set the image, the bitmap is read as null even though it has been received.
my constructor
ImageView iview_image;
public ImageLoader(String url, Context newContext, ItemsDto items, ImageView imageView)
{
try
{
Log.e("IMGURL",url);
str_img=url;
context=newContext;
this.context=newContext;
itemsDto=items;
iview_image=imageView;
iview_image.findViewById(R.id.icon);
}
my async task
protected Void doInBackground(Void... arg0)
{
try
{
Log.e("Async Img Load", "Before the try");
//Sets image status to help other classes know when image is ready
//image lookups
URL url = new URL(str_img);
HttpGet httpRequest = null;
httpRequest = new HttpGet(url.toURI());
//http get
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity b_entity = new BufferedHttpEntity(entity);
InputStream input = b_entity.getContent();
bm_productImage = BitmapFactory.decodeStream(input);
setBm_productImage(bm_productImage);
str_imgStatus="Image recieved";
}
catch (Exception e)
{
Log.e("IMG_ERROR",e.toString());
}
try{iview_image.setImageBitmap(getBm_productImage());}
catch(Exception e){ Log.e("more errors wheee", e.toString());}
doPendingActivity();
return null;
}
#Override
protected void onPostExecute(Void result)
{
// TODO Auto-generated method stub
super.onPostExecute(result);
try
{
}
catch(Exception e)
{
Log.e("Post_ERROR", e.toString());
}
}
I've been where you are, and I'll give you a recommendation. However, first, I'll answer your question. The way I downloaded a stream from a URL and saved it into a Bitmap was:
try {
URL url_obj = new URL(url);
Bitmap imageToReturn = BitmapFactory.decodeStream(url_obj.openConnection().getInputStream());
return imageToReturn; // or do whatever you want
} catch (MalformedURLException e) {
return null;
} catch (SocketTimeoutException e) {
return null;
} catch (IOException e) {
return null;
}
However, this solution is far from ideal when dealing with a lot of images. Android does not handle Bitmaps in memory well, and after you allocate a lot of Bitmaps in memory, it's a matter of time before you get an OutOfMemoryError exception thrown in your face.
I'd recommend using an image downloading/caching library like Picasso (http://square.github.io/picasso/). You can download the JAR file and include it in your project (it's really just that simple!). The default usage scenario is:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
but that's not the only possibility. If you want to save the bitmap or do something else with it, you can do:
Picasso.with(context).load(url).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
// do what you want to do with the bitmap
// if it has already been downloaded, it will be loaded from
// cache (memory or disk). The loaded bitmap is in the parameter
}
#Override
public void onBitmapFailed(Drawable drawable) {
// whatever you want to do if if could not load the image
}
#Override
public void onPrepareLoad(Drawable drawable) {
// do whatever you want to do right before your request is submitted
}
});
Any of the methods can be empty if you want, use it as needed (all of the methods need to be there though, or the interface implementation will give you a compilation error).
I think you'll find this solution to be better and it will save you headaches in the future when you start to run out of memory. I hope it was useful!
Related
Hi guys i started developing an android application and i am bit confused on which is the best way to accomplish it
Application Flow
when the activity starts it fetches data from the database(sqlite), the database returns a list of data ,this list of data contains text and url for image.
so now i want that as soon as activity start the listview will be populated with the text data and the images.
The images will be first searched locally if not present then the images will be fetched from url after the fetching is completed the image will be added to its respective view and also stored on the device
These images once downloaded should remain on device until the app is uninstalled
Issues
as soon we start the activity the list view gets populated with the data from local database but the images takes time to download
so i tried asynchronous image loader but the problem was if the activity was started and the device isn't connect to net the image wont show but after that if we connect to internet these images wont show
is their any easier way to handle the images so that if i need to delete these images in future i can. If some one can provide refrence to any project or available libraries to handle these task .Thnx in advance
I don't the way you are loading the images to list but i suggest you to use picasso a library to load images :
for url:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
for Resource :
Picasso.with(context).load(R.drawable.landing_screen).into(imageView1);
loading from file:
Picasso.with(context).load(new File(...)).into(imageView2);
more details are here: http://square.github.io/picasso/
To download image and save to disk:
new ImageDownloader().execute(downloadUrl);
private class ImageDownloader extends AsyncTask {
#Override
protected String doInBackground(String... param) {
// TODO Auto-generated method stub
return downloadBitmap(param[0]);
}
#Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
}
#Override
protected void onPostExecute(String result) {
Log.i("Async-Example", "onPostExecute Called");
Bitmap myBitmap = BitmapFactory.decodeFile(result));
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
simpleWaitDialog.dismiss();
}
private String downloadBitmap(String url) {
// initilize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
//forming a HttoGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap that android understands
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return SaveBitmapToDir(bitmap);
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// You Could provide a more explicit error message for IOException
getRequest.abort();
Log.e("ImageDownloader", "Something went wrong while" +
" retrieving bitmap from " + url + e.toString());
}
return null;
}
private String SaveBitmapToDir(Bitmap bmp)
{
FileOutputStream out = null;
File file = null;
try {
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyy_hhmmss");
String dateTime = s.format(new Date());
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
file = new File(path, "MyApp_"+dateTime+".jpg");
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
To store key-value pair i suggest you to use android's shared preference to store the image name and the location on the disk.
Here is a tutorial for Shared Preference
To store values in shared preferences:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("image name","image path oon disk");
editor.apply();
To retrieve values from shared preferences:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String imagePath = preferences.getString("image name","");
if(!imagePath.equalsIgnoreCase(""))
{
//your action here with the image path
}
How can declared dynamically multiple images URL and i want to display selected one image not display all images.Images retrieved in Server.
I tried this code only one image is retrieved from server. I need to how declare and retrieve multiple images and this same code can declare images.
The coding is as follow,..
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class Image_Async extends AsyncTask<Bitmap,Bitmap,Bitmap>
{
#Override
protected Bitmap doInBackground(Bitmap... arg0) {
// TODO Auto-generated method stub
Bitmap bmp= null;
try {
URL url =
new URL("http://fc02.deviantart.net/fs42/i/2009/132/7/2/DIWA_boy_animation_by_LunarRain27.jpg");
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bmp;
}
Anybody give your suggestion...
Create an array of URL string and Bitmap..
And process them one by one adding the result if the InputStream to the Bitmap array on each URL..
The problem..
Lets say you have a lot of URL with BitMaps it may result to OutOfMemoryException
Hmmm, I'm not sure what you are asking for exactly.
If you want to be able to cache images (download many and display one at a time) use Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader
If you are just looking for a way to download multiple images, then instead of decoding the bitmap, open the input stream and write to a file.
try {
final File file = new File(getCacheDir(), "imagename goes here");
final OutputStream output = new FileOutputStream(file);
try {
try {
final byte[] buffer = new byte[1024];
int read;
// this is the input stream from your url connection
while ((read = inputstream.read(buffer)) != -1)
output.write(buffer, 0, read);
output.flush();
} finally {
output.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} finally {
inputstream.close();
}
as you are not going to want to have that many images in RAM for no reason. (but maybe you do have a reason?
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
anyways, you run one of the above in a loop for as many images as you have, on a background thread, have it notify you when it is done. example
class EZAsyncTask extends AsyncTask<Void, Void, List<Bitmap>>
{
private AsyncTaskListener listener;
private List<String> urlList;
public EZAsyncTask(List<String> urlList, AsyncTaskListener listener)
{
super();
this.urlList = urlList;
this.listener = listener;
}
#Override
protected String doInBackground(Void... params)
{
List<Bitmap> bitmapList = new ArrayList<Bitmap>();
for (String url : urlList)
{
bitmapList.add(getBitmapFromURL(url));
}
return bitmapList;
}
#Override
protected void onPostExecute(List<Bitmap> bitmapList)
{
super.onPostExecute(bitmapList);
listener.onCompletion(bitmapList);
}
public interface AsyncTaskListener
{
public void onCompletion(List<Bitmap> bitmapList);
}
}
and use it like this
urlList = new ArrayList<String>();
urlList.add("http://images.fastcompany.com/upload/Simple.jpg");
EZAsyncTask ezTask = new EZAsyncTask(urlList, new AsyncTaskListener() {
#Override
public void onCompletion(List<Bitmap> bitmapList)
{
// TODO handle response
}
});
ezTask.execute();
Anyways there is a lot there. Try to understand it all if you can, it will help greatly in the long run ;)
I'm trying to get the app to show an image from a URL, im fairly certain the issue is with the AsyncTask but I've returned to this code several times over the past week and I still cant see where I'm going wrong.
The Internet permission is set and I am getting no LogCat
ImageView eventImage2;
eventImage2 = (ImageView) findViewById(R.id.eventImage2);
new imageupdate().execute();
public class imageupdate extends AsyncTask<Bitmap, Void, Bitmap> {
#Override
protected Bitmap doInBackground(Bitmap... url) {
URL url1;
try {
url1 = new URL("http://masterzangetsu.eu/Apps/NowIGetYou/banner.png");
HttpURLConnection connection = (HttpURLConnection) url1.openConnection();
InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return img;
}
protected void onPreExecute(String result) {
}
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
eventImage2.setImageBitmap(result);
}
}
As far as I can tell the img variable defined with the
img = BitmapFactory.decodeStream(is);
isnt being linked to the variable being returned
return img;
Both variables result and img are coming back as null
Change this
Bitmap result = null;
InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is);
img = result;
to
Bitmap img = null;
InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is);
result = img;
and return result in doInBackground(). You have them switched around so 'img' will be null no matter what happens.
Also, you can't use Toast in doInBackground() as this method isn't run on the UI thread. You will need to make that a Log or put your Toast in onPostExecute() or onProgressUpdate(). These are the things I see. If you are still having problems then you need to be a little more clear on what specifically. You will need to debug and use breakpoints to see what isn't being returned that should be and pinpoint a little more what the problem is
AsyncTask - any UI updates must be done in one of the other methods of AsyncTask other than doInBackground() or you can pass a value back to the Activity to update the UI there.
I am building a news paper app for that I need to show news paper images(epaper) in gallary view... I need to download about 100 images. for that I use asyncTask and for every download image I create new AsyncTask object and,when I am trying to download image and set into gallary I have the error in middle "VM won't let us allocation... bytes" and crash the app.
new AsyncTask<String, Void, Bitmap> () {
#Override
protected Bitmap doInBackground(String... params) {
HttpGet httpRequest;
try {
httpRequest = new HttpGet(new URL(params[0]).toURI());
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpClient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufHttpEntity.getContent();
return BitmapFactory.decodeStream(is);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}/* catch (Error e) {
e.printStackTrace();
}*/
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
if(result != null) {
img.setImageBitmap(ePaperInfo.getImgJpg1());
notifyDataSetChanged();
}
}
}
show the error in logcat:
Please help me
Thanks in advance.
You should definetly not keep 100 Bitmaps on memory at the same time. You need to download only the Bitmaps needed and then call recycle() before downloading new Bitmaps.
Have a look at this exaple for the preferred way of doing what you want: ImageDownloader
Another option for image loading that I use is Prime, I use it in all of my projects and its pretty simple and efficient.
I have been following a tutorial that remotely downloads an image to an imageview, but i'm not sure how to add a progress dialog (image or something) to show the user that image is downloading, instead of just a blank screen.
Hope someone can help
ImageView imView;
String imageUrl="http://domain.com/images/";
Random r= new Random();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
WindowManager.LayoutParams.FLAG_FULLSCREEN );
setContentView(R.layout.galleryshow);
Button bt3= (Button)findViewById(R.id.get_imagebt);
bt3.setOnClickListener(getImgListener);
imView = (ImageView)findViewById(R.id.imview);
}
View.OnClickListener getImgListener = new View.OnClickListener()
{
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
int i =r.nextInt(114);
downloadFile(imageUrl+"image-"+i+".jpg");
Log.i("im url",imageUrl+"image-"+i+".jpg");
}
};
Bitmap bmImg;
void downloadFile(String fileUrl){
URL myFileUrl =null;
try {
myFileUrl= new URL(fileUrl);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
bmImg = BitmapFactory.decodeStream(is);
imView.setImageBitmap(bmImg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You should look at this : asynctask is the way to go.
Android : Loading an image from the Web with Asynctask
Regards,
Stéphane
You need to look at ProgressBar class and basically use that while the image is loading. Alternatively you could put default image while the image is being downloaded.
To put the progress bar in your code, the easiest basically just flip their visibility in the layout.
In your layout, you have two things. One placeholder for ProgressBar and the other is for the image
The progressbar is set to VISIBLE initially and the image to GONE
After you execute the AsyncTask (see below), you need to flip the visibility. Basically change the progressBar to GONE and the image to VISIBLE
Here is what you should try to do. Check the NOTE and TODO comment in the code. Note: I just modified your code, but haven't run it, but this should be enough to illustrate the idea.
Some key points:
Long running task that might block UI Thread should get executed in AsyncTask. In your case, this would be downloading the image
Post execution that needs to be handled in UI Thread should be handle in postExecute()
Doing e.printStacktrace() during catching Exception is not a good practice. Without appropriate handles, this exception is not being handled correctly and might cause bugs in the future. In addition, during production, this information doesn't help you at all when bugs occur on the client's side since it is merely printing out in the console
View.OnClickListener getImgListener = new View.OnClickListener()
{
#Override
public void onClick(View view) {
// NOTE: here you need to show the progress bar, you could utilize ProgressBar class from Android
// TODO: Show progress bar
AsyncTask asyncTask = new AsyncTask() {
#Override
public Bitmap doInBackground(Void... params) {
int i =r.nextInt(114);
// NOTE: move image download to async task
return downloadFile(imageUrl+"image-"+i+".jpg");
}
#Override
public void onPostExecute(Bitmap result) {
// TODO: hide the progress bar here
// and flip the image to VISIBLE as noted above
if(result != null) {
imView.setImageBitmap(result);
} else {
// NOTE 3: handle image null here, maybe by showing default image
}
}
};
// NOTE: execute in the background so you don't block the thread
asyncTask.execute();
}
};
// Change the return type to Bitmap so we could use it in AsyncTask
Bitmap downloadFile(String fileUrl){
URL myFileUrl =null;
try {
myFileUrl= new URL(fileUrl);
} catch (MalformedURLException e) {
// NOTE: You should not have e.printStacktrace() here. In fact
// printStacktrace is a bad practice as it doesn't really do anything
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
Bitmap bmImg = BitmapFactory.decodeStream(is);
// return image this to the main Thread
return bmImg;
} catch (IOException e) {
return null;
}
}