I'm pretty new to Android Development and spent all day looking into issues with my ListAdapter, but couldn't find any answers that helped me solve my problem.
I Have a JSON NewsString parsed from an URL and need to load the Thumbnail into the ListView.
I tried to Load it via Imageloader (https://github.com/novoda/ImageLoader#directloader-utility) and then convert the Bitmap to a Drawable so I can use it in my ListView (Did that before).
I Have the permissions in the Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
And the JsonObject is parsed in an AsyncTask where I try to load the image from Url.
try {
String url = e.getString("imageThumb");
Bitmap bmp = new DirectLoader().download(url);
Drawable d = new BitmapDrawable(null,bmp);
Log.d("getBitmap", d.toString());
row.put("thumb", d);
}catch (Exception e5) {
Log.e("IMG", "Failed to load Thumbnail From URL: "+e5.toString());
Drawable d = MainActivity.hweb_icon;
row.put("thumb", d);
}
but I always get the Same Error Message:
I tried several tutorials and other stuff, but it never worked out for me.
The URL is correct and does not need any encoding.
My previous approach looked like this :
try {
String url = e.getString("imageThumb");
InputStream in = new java.net.URL(url).openStream();
Bitmap bmp = BitmapFactory.decodeStream(in);
Drawable d = new BitmapDrawable(null,bmp);
row.put("thumb", d);
}catch (Exception e5) {
// handle it
Log.e("IMG", "Failed to load Thumbnail From URL : "+e5.toString());
}
Sorry if this question was already answered, but I found many solutions and tried them, but none of them helped me out.
Thx
pwittke
EDIT:
I created a new Testproject and the code below worked fine, so I started to deactivate every part that uses drawables somehow and turned out, that the SimpleAdapter cant load images that way... It can only load images from the resurces and not from an url... thx for your script britzl, it works fine, now I need to find a way to change my adapter for the images...
There are many ways to load a Bitmap from a URL. If you want to roll your own you can try something like:
public Bitmap loadImage(String url) {
DefaultHttpClient client = new DefaultHttpClient();
Bitmap bitmap = null;
try {
HttpResponse response = client.execute(new HttpGet(url));
HttpEntity entity = response.getEntity();
if(entity != null) {
InputStream in = entity.getContent();
bitmap = BitmapFactory.decodeStream(in);
}
}
catch (Exception e) {
}
return bitmap;
}
There's some things to consider, for instance if you run into Skia decoder errors you may have to wrap the stream. Read more here.
I would however recommend that you take a look at existing libraries. The up and coming Picasso library from Square is probably your best bet. Example:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Related
I'm having trouble with loading an image from a URL into my Android app using the Google Places API.
I got the part with the API working and I can see the image if I type the URL in my browser. The code fails in the below line:
Bitmap myBitmap = BitmapFactory.decodeStream(input);
The strange thing is, it simply jumps to the return null in the catch clause without executing the println commands.
I should also explain that I'm using two URL's since the first URL in the google API is a redirect page.
I assume that the problem is that the final page that's being loaded isn't actually a "real" image (I mean it looks like
https://lh4.googleusercontent.com/XXX/s1600-w400/
rather than something like
http://something/image.jpg)
Below is the entire method I'm using:
public Bitmap getImageData(Place p) {
try {
String src= "https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference="+
p.getPhoto_reference()+
"&key="+
this.context.getResources().getString(places_api);
Log.d("srcsrc", src);
URL url = new URL(src);
HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
ucon.setInstanceFollowRedirects(false);
URL secondURL = new URL(ucon.getHeaderField("Location"));
HttpsURLConnection connection = (HttpsURLConnection) secondURL.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Bitmap exception" + e);
return null;
}
}
Appreciate your help.
use Picasso like this :
Picasso.with(context).load(src).into(imageView );
It will do the following:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
I have Multiple images on the server. What I want to do is I want to retrieve these images from the server and set it on the imageView.
I have worked with getting the blob type images from the server, decoding it to byte array and then convert it to Bitmap images.
I am confused about how to get Bitmap images from the server.
I have been through many questions on SO like
Retriving image from server to android app
Load Large Image from server on Android
Please can any one help with a Link or a code.
Thank You for your precious time.
I was trying things and here is the code:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bitmap bitmap = DownloadImage("http://www.allindiaflorist.com/imgs/arrangemen4.jpg");
ImageView img = (ImageView) findViewById(R.id.img);
img.setImageBitmap(bitmap);
}
private InputStream OpenHttpConnection(String urlString)
throws IOException
{
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
}
catch (Exception ex)
{
throw new IOException("Error connecting");
}
return in;
}
private Bitmap DownloadImage(String URL)
{
Bitmap bitmap = null;
InputStream in = null;
try {
in = OpenHttpConnection(URL);
BufferedInputStream bis = new BufferedInputStream(in, 8190);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
System.out.println("BAF= "+baf);
int current = 0;
while ((current = bis.read()) != -1)
{
baf.append((byte)current);
}
byte[] imageData = baf.toByteArray();
System.out.println("imageData= "+imageData);
bitmap =BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
in.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
return bitmap;
}
}
This returns the image but he url that i have used consists of the image name. What if i have more images and I want to retrieve all of the them as my application loads.
I recommend you a different way that works like a charm: Android Query.
You can download that jar file from here: http://code.google.com/p/android-query/downloads/list
AQuery androidAQuery=new AQuery(this);
As an example:
androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);
Using above code you can directly show your Image through url. Now below code is to get Bitmap Directly from the url:
androidAQuery.ajax(YOUR IMAGE URL,Bitmap.class,0,new AjaxCallback<Bitmap>(){
#Override
public void callback(String url, Bitmap object, AjaxStatus status) {
super.callback(url, object, status);
//You will get Bitmap from object.
}
});
This library is provided by Android itself, so use it and see the result whatever you want.
It's very fast and accurate, and using this you can find many more features like Animation when loading; getting a bitmap, if needed; etc.
I would recommend you use the Volley library (The presentation is here), the same library used by Google in its application Google Play. At the Google I/O 13, Ficus Kilkpatrick presented Volley. Volley is an HTTP library that aims at removing lots of boilerplate code, simplifying the handling of images in lists, be faster, abstract the complexity of one or another HTTP client.
Initialization
Volley relies on a RequestQueue, that handle a queue of request, and on an ImageLoader, that is in charge of loading the images. We need one of each
public static ImageLoader mImageLoader;
public static RequestQueue mRequestQueue;
We also need to initialize them. The queue needs a Context, the ImageLoader needs an ImageCache. Here, I use a basic wrapper to LruCache.
mRequestQueue = Volley.newRequestQueue(this);
mImageLoader = new ImageLoader(mRequestQueue, new BitmapLru(64000));
The initialization is done in the onCreate() of the first activity.
Getting an image
Suppose you have to fill a gridview with images downloaded from a server. The ImageUrlAdapter populates a GridView (or any AdapterView) with NetworkImageView. This is a class provided by Volley to put images from the network into an ImageView. It actually extends ImageView, meaning you can use it anywhere you use an ImageView. It is extremely simple to use. The only code in the adapter is the getView.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
NetworkImageView imageView;
if (convertView == null) {
imageView = new NetworkImageView(getContext());
} else {
imageView = (NetworkImageView) convertView;
}
String url = getItem(position);
imageView.setImageUrl(url, MainActivity.mImageLoader);
return imageView;
}
The only new thing here is imageView.setImageUrl(url, MainActivity.mImageLoader);
That’s it. Nothing more is required.
Use the Universal Image Loader
Since your confused I'll explain
Download the jar file by clicking here and paste it into your libs folder
In your manifest add these two lines of permission
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Use this code
ImageLoader imageLoader = ImageLoader.getInstance();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.createDefault(getApplicationContext())
imageLoader.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher)
.cacheInMemory()
.cacheOnDisc()
.build();
imageLoader.displayImage("http://www.allindiaflorist.com/imgs/arrangemen4.jpg",your_IMAGEVIEW,options,null);
Or if you just want the bitmap then use this
Bitmap bmp = imageLoader.loadImageSync("http://www.allindiaflorist.com/imgs/arrangemen4.jpg");
I would strongly recommend using the Square's Picasso library. It's very easy to work with and takes away all the pain of retrieving-caching.
I would suggest using Prime Library , it has functioning to download images asynchronously and then a callback with a listener having the url and bitmap image as the parameters.
I've started getting a
DEBUG/skia(xxxx): --- decoder->decode returned false
issue on a few profile images from Facebook that I use in ImageViews. Most work perfectly, but every once in a while I discover one that never works.
I am compiling my application against Android 1.6 for backward compatibility reasons.
I did some digging and discovered a number of threads on the issue. I'm already using the FlushedInputStream discussed here: http://code.google.com/p/android/issues/detail?id=6066
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
Here's an example that's causing me trouble:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg
Can someone check out the image and help me figure out what's causing the trouble?
Here is a way that worked for me:
HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);
The source code from this ImageDownloader.java is a good orientation. It has a bug fix which addresses the Issue 6066 by providing a patched FlushedInputStream class.
Another thing which you might want to take care of, is to execute the decoding in the same thread as the HTTP request was executed:
#Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
I had done the decoding in the onPostExecute(), which is executed in the UI thread, and it would not work anymore, giving me the same error.
Here is a way that worked for me:
public static Bitmap loadImageFromUrl(String url) {
URL m;
InputStream i = null;
BufferedInputStream bis = null;
ByteArrayOutputStream out =null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
bis = new BufferedInputStream(i,1024 * 8);
out = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while((len = bis.read(buffer)) != -1){
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Drawable d = Drawable.createFromStream(i, "src");
return bitmap;
}
I loaded the image by multithreading, and then I had to loop reading the inputStream when the thread's time was held by another. Make sure the inputStream is read fully.
Here is what the issue was for me:
From the emulator I would save the jpg file locally (on the emulated sdcard) and then attempt to read it up and display it using decode on the emulator and it worked. Then, as a test, I copied the file (using adb pull) to my development (xp) machine and it would display using 'paint'. Then, from the emulator, I uploaded the file (via http post) to my win2003 server. Using 'paint' it displayed there as well. But when I downloaded it back to the emulator (via http get), it failed during the decode.
Then I noticed that the file uploaded to the win2003 server was two bytes smaller than the original. Not totally sure how that happened because I've been using the same upload logic for years and never noticed the issue before. As a test, I simply appended two more random bytes during the upload so the file size was exactly the same. Then, when downloaded back to the emulator, it decoded and displayed properly.
Just as a check, I appended two random bytes over on my xcode projects and then those jpg files also displayed on the android emulator as well.
So, although the files which were two bytes smaller displayed everywhere else, they would not on the emulator. Apparently decode is doing some sort of CRC before it attemps to decode and decides it cannot continue. And hence the error.
Others who are facing issues in Android KitKat 4.4 , following would be helpful
Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is));
imageView.setImageBitmap(b);
I was facing this issue in Nexus series After updating to 4.4.
I ran into this issue as well using Xamarin. To fix it I simply used the Universal Image Loader Xamarin Component and it worked like a charm.
Hope this helps!
I have a bit of code that was working, but now isn't and I can't figure out why. I am trying to download an image from a URL, but nothing is being retrieved. I have the following code:
URL u;
u = new URL("https://sites.google.com/site/mymoneymobilesite/rugbynut/leagues/league%20six%20nations.png");
URLConnection ucon = u.openConnection();
InputStream is = ucon.getInputStream();
Bitmap tmp_bmp = BitmapFactory.decodeStream(is);
Like I say, this was working months ago, but I've come to update some other code and found that it isn't anymore.
Can anyone help please?
UPDATE:
I have tried the code:
InputStream iStream = (InputStream) u.getContent();
Drawable d = Drawable.createFromStream(iStream, "test");
but d is null. I use the same URL as above (the image is publicly available) and the application has no issues with connecting to the internet, as it is managing to download other data.
Any more ideas?
You might have not given permission for internet access in the manifest file.
Note that to fetch the image from URL either use AsyncTask or a different thread, as the fetch operation can't be performed in the main thread.
Try images at other links maybe the link you are trying is not valid.
use this code
public static Drawable LoadImageFromWebOperations(String url) {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
return null;
}
}
You can use this code..
public static Drawable ImageOperations(String url) {
try {
InputStream is = (InputStream) fetch(url);
Drawable d = Drawable.createFromStream(is, "src");
return d;
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
}
public static Object fetch(String address) throws MalformedURLException,IOException {
URL url = new URL(address);
Object content = url.getContent();
return content;
}
It is working cool for me. I also faced this kind of error before, It is hard to find the exact error. Basically when internet is slow or image is large then it occurs . But this code works every times..
I've started getting a
DEBUG/skia(xxxx): --- decoder->decode returned false
issue on a few profile images from Facebook that I use in ImageViews. Most work perfectly, but every once in a while I discover one that never works.
I am compiling my application against Android 1.6 for backward compatibility reasons.
I did some digging and discovered a number of threads on the issue. I'm already using the FlushedInputStream discussed here: http://code.google.com/p/android/issues/detail?id=6066
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
Here's an example that's causing me trouble:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg
Can someone check out the image and help me figure out what's causing the trouble?
Here is a way that worked for me:
HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);
The source code from this ImageDownloader.java is a good orientation. It has a bug fix which addresses the Issue 6066 by providing a patched FlushedInputStream class.
Another thing which you might want to take care of, is to execute the decoding in the same thread as the HTTP request was executed:
#Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
I had done the decoding in the onPostExecute(), which is executed in the UI thread, and it would not work anymore, giving me the same error.
Here is a way that worked for me:
public static Bitmap loadImageFromUrl(String url) {
URL m;
InputStream i = null;
BufferedInputStream bis = null;
ByteArrayOutputStream out =null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
bis = new BufferedInputStream(i,1024 * 8);
out = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while((len = bis.read(buffer)) != -1){
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Drawable d = Drawable.createFromStream(i, "src");
return bitmap;
}
I loaded the image by multithreading, and then I had to loop reading the inputStream when the thread's time was held by another. Make sure the inputStream is read fully.
Here is what the issue was for me:
From the emulator I would save the jpg file locally (on the emulated sdcard) and then attempt to read it up and display it using decode on the emulator and it worked. Then, as a test, I copied the file (using adb pull) to my development (xp) machine and it would display using 'paint'. Then, from the emulator, I uploaded the file (via http post) to my win2003 server. Using 'paint' it displayed there as well. But when I downloaded it back to the emulator (via http get), it failed during the decode.
Then I noticed that the file uploaded to the win2003 server was two bytes smaller than the original. Not totally sure how that happened because I've been using the same upload logic for years and never noticed the issue before. As a test, I simply appended two more random bytes during the upload so the file size was exactly the same. Then, when downloaded back to the emulator, it decoded and displayed properly.
Just as a check, I appended two random bytes over on my xcode projects and then those jpg files also displayed on the android emulator as well.
So, although the files which were two bytes smaller displayed everywhere else, they would not on the emulator. Apparently decode is doing some sort of CRC before it attemps to decode and decides it cannot continue. And hence the error.
Others who are facing issues in Android KitKat 4.4 , following would be helpful
Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is));
imageView.setImageBitmap(b);
I was facing this issue in Nexus series After updating to 4.4.
I ran into this issue as well using Xamarin. To fix it I simply used the Universal Image Loader Xamarin Component and it worked like a charm.
Hope this helps!