I have been using Picasso for quite some time, but I had to upgrade OkHttp library to 2.0.0 and, consequently, I had to upgrade Picasso to version 2.3.2.
However, now Picasso does not load any image at all, the imageviews are left empty. No error shows up at any time, but when I turned Picasso logging on, the "Hunter" seems to be dispatched and starts executing, but never finishes.
All the images are accessible and rather small (around 200px by 100px).
I'm loading the images through Picasso's "typical" method:
Picasso.with(context).load(url).error(R.drawable.errorimg).into(imageView);
However, the errorimg is never shown.
What could I be doing wrong?
EDIT:
Here is the code of one of the places where Picasso is not working (PlaceListAdapter.java - getView function)
public View getView(int position, View convertView, ViewGroup parent)
{
final PBNPlace ev = values.get(position);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.places_list_item, parent, false);
TextView titleView = (TextView)rowView.findViewById(R.id.place_title);
ImageView placeImage = (ImageView)rowView.findViewById(R.id.place_image);
Picasso picasso = Picasso.with(context);
picasso.load(ev.imageURL).error(R.drawable.chat).into(placeImage);
titleView.setText(ev.name);
return rowView;
}
When you upgraded OKHttp, did you also upgrade the okhttp-urlconnection dependency?
I had this issue and it turned out I was still calling for version 1.6.0 of okhttp-urlconnection in my build.gradle file. There were no error messages that made it readily apparent to me that I had overlooked this.
Changing that to 2.0.0 solved the problem.
Picasso does not have an HTTP client inside of it so saying that is "supports HTTPS" means little.
When you pass in a url (whether it has a scheme of http:// or https://) we pass that along to the most appropriate HTTP client there is.
Maybe that's java.net.HttpURLConnection. Maybe it's that sexy bundle of bytecode OkHttp. The bottom line is that whatever the scheme is we just let the HTTP client handle it.
Any problems you are having with http:// vs https:// are in the configuration of the client, not Picasso.
Said By JakeWharton
So for loading images you just need to add below dependencies in your gradle file.
compile 'com.squareup.okhttp:okhttp:2.2.+'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.+'
compile 'com.squareup.picasso:picasso:2.5.2'
Reference : https://github.com/square/picasso/issues/500
<uses-permission android:name="android.permission.INTERNET"/>
this might be the stupidest answer but sorry for that. Sometimes small things are what we forget. Have you checked your permission.
Related
So I have been struggling with the best way to load images in a ListView in Android for a while.
The images come from a server, so can take some time to load. From what I understand there are only 2 ways to implement this:
1 - Load the images on the main thread - This leads to have the correct images display immediately when the view displays and scrolls, but gives poor scrolling performance and can lead to the app hanging and crashing.
2 - Load the images in an AsyncTask. This means the images will be blank when the list display or scroll, but eventually display. Because of caching done by the list, you can also get the wrong image for an item. But this gives good performance and scrolling, and does not hang/crash.
Seems like neither solution works correctly. There must be a solution that works?? I have seen other posts like this, but the answer seems to always be 1 or 2, but neither is a good solution...
My code for the list adapter is below.
The HttpGetImageAction.fetchImage() method either executes an async task, or fetches the image on the main thread depending on a flag I set. I also cache the images locally and on disk once they have been loaded, so the issue mainly occur the first time (but the cache is only for 100 images, and the list has 1000s)
public class ImageListAdapter extends ArrayAdapter<WebMediumConfig> {
Activity activity;
public ImageListAdapter(Activity activity, int resourceId, List<WebMediumConfig> items) {
super(activity, resourceId, items);
this.activity = activity;
}
class ImageListViewHolder {
ImageView imageView;
TextView nameView;
TextView descriptionView;
TextView statView;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageListViewHolder holder = null;
WebMediumConfig config = getItem(position);
LayoutInflater mInflater = (LayoutInflater)this.activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.image_list, null);
holder = new ImageListViewHolder();
holder.imageView = (ImageView)convertView.findViewById(R.id.imageView);
holder.nameView = (TextView) convertView.findViewById(R.id.nameView);
holder.descriptionView = (TextView)convertView.findViewById(R.id.descriptionView);
holder.statView = (TextView)convertView.findViewById(R.id.statView);
convertView.setTag(holder);
} else {
holder = (ImageListViewHolder) convertView.getTag();
}
holder.nameView.setText(Utils.stripTags(config.name));
holder.descriptionView.setText(Utils.stripTags(config.description));
holder.statView.setText(config.stats());
if (MainActivity.showImages) {
HttpGetImageAction.fetchImage(this.activity, config.avatar, holder.imageView);
} else {
holder.imageView.setVisibility(View.GONE);
}
return convertView;
}
}
You should never load images on the main thread. Any network calls should be done asynchronously and should not be done on the main thread. Your images might load quickly (on the main thread) because you may have a good internet connection, have small images and/or have few images. But imagine what would happen if someone using your app has a slower internet and then one day your list grows to hundreds!
The approach below is a well accepted practice for loading scrollview content
a) load your text content as you load the scrollview. Again the loading should be done async but you can show a loading view until the download completes
b) Show image
placeholders while the image loads on each cell
c) Load the images
asynchronously
Using a library such as Picasso would help immensely because there is a lot of boilerplate code which you'd need to handle otherwise such as
cancelling image download when a cell is reused and
starting a new download for a reused cell
caching
retrying a failed download
Hope this helps.
Use Glide [https://github.com/bumptech/glide] or Picasso [http://square.github.io/picasso/] - both libraries are very similar, and easy to use, have caching, work in background, allow placeholders ets.
Usage is as simple as:
Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);
Simple Solution: Glide.
Glide is a fast and efficient open source media management and image
loading framework for Android that wraps media decoding, memory and
disk caching, and resource pooling into a simple and easy to use
interface. Glide supports fetching, decoding, and displaying video
stills, images, and animated GIFs.
You can load the image like:
GlideApp.with(context)
.load("http://via.placeholder.com/300.png")
.into(imageView);
Refer for more info:
https://guides.codepath.com/android/Displaying-Images-with-the-Glide-Library
https://github.com/bumptech/glide
Use Glide library.. Its recommended by Google.
Step 1:
Use latest Glide Version 4 dependency (https://github.com/bumptech/glide)
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
Step 2:
Glide.with(MainActivity.this)
.load(url)
.apply(new RequestOptions().placeholder(R.drawable.placeholder).error(R.drawable.error_image))//this line optional - you can skip this line
.into(imageview);
use picasso or Glide Library
What these library do , is that they image url from u and download them and save it in cache so that whenever you open the same image another time it will load faster and it prevents the usage of the network
Picasso
http://square.github.io/picasso/
Glide
https://github.com/bumptech/glide
You can try UnivarsalImageLoader which is quite Fast and Optimised.
It supports Multithread image loading (async or sync) and high level of customization.
https://github.com/nostra13/Android-Universal-Image-Loader
Here's how I do it
First I always create the RecyclerView.ViewHolder to which I pass a Func<int, Bitmap> image_provider (or you can pass some sort of lamda?) which when called will retrieve the image for a specific Id, if it can't it will show the default loading image
Everything is stored in a fragment (which I call a DataFragment) which has retainstate set to true.
First load a list of json objects that tell me which images I must show, this happens inside the data fragment so it will go on if there is a configuration change
I send that info to the adapter using a method like SetItems(MyImages)
Then I start a new thread that will load the images (while allowing the user to work)
I do this with the TPL library, the closest approximation for Android is Anko Async but you can also do it with AsyncTask, the problem is that I send a lot of messages to the main thread, so to do it with AsyncTask you have to give it a handler to the main thread which will send messages.
In the thread I loop through all the images I have to download, and download them and send a message to the DataFragment which sends it to the currently attached Activity which triggers the NotifyItemChanged method in the adapter
The adapter on creation receives a Func<int, Bitmap> image_provider which it invokes and retrieves the image from memory
I know it sounds a bit messy, so if you want code examples I can give them , but they are in C#
In your app level gradle implement below repository:
implementation 'com.squareup.picasso:picasso:2.5.2'
Put below line where you want to load image
Picasso.with(getApplicationContext()).load(config.avatar).into(imageview);
just use Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView); or
Glide.with(getApplicationContext()).load("image_url").asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView)
in adapter like any view and done no extra efforts required
I have a ListView extending ArrayAdapter. I am using a view holder patter for the getView and here is a part of my getView method which loads images using picasso. The following code is expected to load images into my image view inside every list item.
Picasso.with(mContext).load(imageURL).fit().into(holder.myImageView,
new Callback(){
#Override
public void onError() {
holder.myImageView.setVisibility(View.INVISIBLE);}
#Override
public void onSuccess() {}});
So here is the problem: this works fine for OS < Android 5.0, but in the case of Android 5.0 (Lollipop), it looks like Picasso is fetching these images when my app is installed and run for the very first time, but when I launch the app again, the images don't load. Not at all sure what the problem is. I am not loading huge images, you can assume all the images that I am loading are only of the size of a small icon/thumbnail (around 120X120). I am using Picasso 2.4.0 for my application and the phone that I am using for testing is the Nexus 4.
Open Issue as of this edit: https://github.com/square/picasso/issues/633
Alternative:
I struggled to find an answer for very long time yesterday night. I explored Picasso really intimately trying several stuff. None did work. So right now what I am doing is:
if(api>=21) //Keeping in mind about any updates beyond 21
Use Android-Universal-Image-Loader
else
Use Picasso
For more information on Andorid Universal Image Loader.
Please visit https://github.com/nostra13/Android-Universal-Image-Loader
Its awesome with its cusotmization.
Agian, dont get me wrong, I am 100% +ve there is a solution with Picasso, I am sure I will find it someday, I will post it here then, but for anyone who have problems like me, I think the above is the way to go. Please suggest if you have anuy other better way.
************************ ISSUE FIXED **************************
https://github.com/square/picasso/issues/632
https://github.com/square/picasso/pull/860
************************** ISSUE FIXED ****************************
I'm trying to add an image to a docx file using docx4j library within Android.
I've faced to an exception:
E/AndroidRuntime(21818): java.lang.ExceptionInInitializerError
E/AndroidRuntime(21818): at org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.newSource(AbstractImageSessionContext.java:134)
E/AndroidRuntime(21818): at org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.needSource(AbstractImageSessionContext.java:280)
E/AndroidRuntime(21818): at org.apache.xmlgraphics.image.loader.cache.ImageCache.needImageInfo(ImageCache.java:123)
E/AndroidRuntime(21818): at org.apache.xmlgraphics.image.loader.ImageManager.getImageInfo(ImageManager.java:122)
E/AndroidRuntime(21818): at org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.getImageInfo(BinaryPartAbstractImage.java:696)
E/AndroidRuntime(21818): at org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.ensureFormatIsSupported(BinaryPartAbstractImage.java:352)
E/AndroidRuntime(21818): at org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.ensureFormatIsSupported(BinaryPartAbstractImage.java:331)
E/AndroidRuntime(21818): at org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(BinaryPartAbstractImage.java:298)
E/AndroidRuntime(21818): at org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(BinaryPartAbstractImage.java:158)
...
E/AndroidRuntime(21818): Caused by: java.lang.NoClassDefFoundError: sun.awt.AppContext
E/AndroidRuntime(21818): at ae.javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:155)
E/AndroidRuntime(21818): at ae.javax.imageio.ImageIO.<clinit>(ImageIO.java:65)
...
It is referring to this code:
WordprocessingMLPackage wordMLPackage;
File file;
...
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, file);
I've already added all necessary libraries from AndroidDocxToHtml example (and ae-awt.jar too) to libs folder of my app.
Without images my app generates docx files perfectly.
Is there any way to solve it?
Thanks!
I got this to work but it required overriding about 8 files from ae-awt and ae-xmlgraphics-commons. And I hardcoded it to handle jpg files only.
Remove all references to sun.security.action.LoadLibraryAction and just call System.loadLibrary("jpeg")
Remove AppContext and replace it with ThreadGroup from ImageIO, like this:
private static synchronized CacheInfo getCacheInfo() {
ThreadGroup group = Thread.currentThread().getThreadGroup();
CacheInfo info = (CacheInfo) instances.get(group);
//CacheInfo info = (CacheInfo)context.get(CacheInfo.class);
if (info == null) {
info = new CacheInfo();
instances.put(group, info);
}
return info;
}
Same with imageio.spi.IIORegistry
In ae-xmlgraphics-commons, made a few changes to ImageManager.java, DefaultImageContext and BinaryPartAbstractImage. The first 2 I dont remember what I did (i can't diff them easily, maybe no changes were needed), but there were many changes to BinaryPartAbstractIMage. I hardcoded the getImageInfo() to IMAGE_JPEG because of problems with the sessionContext / Context type (that somehow tried to determine the image type and call the appropriate preloader). So I made the assumption that all images are jpegs and force it to always use the JPEG preloader.
getImageInfo()
ImageInfo info = new ImageInfo(url.toURI().toString(), ContentTypes.IMAGE_JPEG);
That got a warped image to appear in the doc. I still have to figure out the width/height formula to get it to embed correctly.
For everyone, who faced this problem too.
Here are necessary steps to make docx4j works fine with images:
Add missed classes from OpenJDK to appropriate packages with ae.
Change references to new classes, for example sun.awt.AppContext to ae.sun.awt.AppContext.
In org.apache.xmlgraphics.util.Service manually fill list with preloaders:
private static List<String> getProviderNames(Class<?> cls, ClassLoader cl) {
...
if (fillDefautsProviderNames(cls, l))
return l;
...
}
private static boolean fillDefautsProviderNames(Class<?> cls, List<String> l) {
if (cls == org.apache.xmlgraphics.image.loader.spi.ImagePreloader.class) {
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderTIFF");
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderGIF");
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderJPEG");
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderBMP");
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderEMF");
l.add("org.apache.xmlgraphics.image.loader.impl.PreloaderEPS");
l.add("org.apache.xmlgraphics.image.loader.impl.imageio.PreloaderImageIO");
return true;
}
return false;
}
Delete function displayImageInfo(ImageInfo info) in org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.
I've prepared repositories with changes: ae-awt, ae-xmlgraphics-commons, docx4j-android.
You can find compiled libs here: docx4j_images_prepared_libs.zip
Enjoy!
To all of you out there, who are trying to generate a docx file from android studio, please do not try the apache poi library. I lost too many days trying to integrate apache poi and xwpfdocument in my app. You can generate some text, but if you want to add pictures, then it is not possible to do it with apache poi, you will get at the end in the doxc file a rectangle instead of your picture saying the the picture can't be displayed.
I switched than to doxc4j I was having there also issues becuase android is not java, and you need to customize some libs and dependecies as #kirik88 mentioned.
What you need to do is you need to insert all jars of this repo: https://github.com/plutext/AndroidDocxToHtml/tree/master/libs to your android project as local libs. You import all of them except the three jars mentioned in the kirik88's comment: https://stackoverflow.com/a/23710079/20718567, there you download the zip folder with the three jars: ae-awt, ae-xmlgraphics-commons, docx4j-android and you insert then these three jars also in you android project, maybe you need to still do some small changes in these jars if android complains, but yeah this thing is working, and after too many days this is the only solution that is working to create doxc file from android with text+images. Thank you #kirik88 and #Jason Harrop(plutext).
I'm currently using Picasso 2.0.1(also tried 1.0.2 before) and obtaining bitmaps from pictures on the web.
All is working great, I've seen improvements in loading the images ... at least it seems faster.
My question is, how can I get statistics from the activities done by PICASSO? I wanted to know if the picture was obtained from the cache or downloaded ...
I'm trying to obtain information with com.squareup.picasso.StatsSnapshot, however it doesn't seem to get updated... or I'm not using it correctly.
Picasso pi = Picasso.with(getActivity().getApplicationContext());
Bitmap bitmap = pi.load(url.toString()).get();
Log.d(this.getClass().getSimpleName(),"Cache hits:" + pi.getSnapshot().cacheHits + " Cache misses:" + pi.getSnapshot().cacheMisses);
adding a log before and / or after the load call always return the same result
Cache hits:0 Cache misses:0
What am I doing wrong or how can I obtain this information?
Thanks in advance!
Marc
To get the colored triangle that David Hewitt is describing, you actually have to use setIndicatorsEnabled like so
Picasso.with(mContext).setIndicatorsEnabled(true);
You can get stats in your logs for Picasso by using setLoggingEnabled like so
Picasso.with(mContext).setLoggingEnabled(true);
You can search the log with a "Picasso" filter and see where Picasso gets the image and how long it takes. Very handy!
According to the website here:
http://square.github.io/picasso/
You can do setDebugging(true) and it will place coloured triangles in the corner or each image that will indicate whether they were loaded from the web, the disk or memory. I can't find any specific reference to the functions you were using on the website, but this may meet your needs instead.
You can call this from the onStop() or onPause of your Activity or Fragment
StatsSnapshot picassoStats = Picasso.with(context).getSnapshot();
Log.d("Picasso stats ", picasspStats.toString());
then from the Android logcat select verbose and filter by Picasso.
You will get a log something like the following:
Picasso stats: [main] StatsSnapshot{maxSize=76695844, size=75737296, cacheHits=656, cacheMisses=1091, downloadCount=8, totalDownloadSize=213376, averageDownloadSize=26672, totalOriginalBitmapSize=437547196, totalTransformedBitmapSize=609434304, averageOriginalBitmapSize=527801, averageTransformedBitmapSize=735143, originalBitmapCount=829, transformedBitmapCount=826, timeStamp=1484426664382}
'get()' is synchronous and skips the cache. Use one of the 'load()' methods to harness Picasso's full powers.
I need to arbitrarily replace a cached image by requesting it again from server.
I'm currently using removeFromCache as follows:
public void loadImage(String url, ImageView view, boolean updateCache){
if(updateCache){
MemoryCacheUtil.removeFromCache(url, ImageLoader.getInstance().getMemoryCache());
}
ImageLoader.getInstance().displayImage(url, view);
}
The problem is sometimes it throws ConcurrentModificationException.
What's the best way to do it?
Can I synchronize my call to remove on the Collection used internally
in the library somehow?
Does the library give me another way to tell
I want to "cache miss" one image arbitrarily?
UIL version is 1.8.4
Stack trace:
FATAL EXCEPTION: main
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:350)
at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:370)
at java.util.HashSet.(HashSet.java:76)
at com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache.keys(LruMemoryCache.java:124)
at com.nostra13.universalimageloader.core.assist.MemoryCacheUtil.removeFromCache(MemoryCacheUtil.java:102)
at uk.frequency.glance.android.util.ImageLoadingManager.loadImage(ImageLoadingManager.java:120)
This is known bug: https://github.com/nostra13/Android-Universal-Image-Loader/issues/265
Fixed in UIL v1.8.5.