Kotlin: Error 503 when loading image from flickr with Picasso

Viewed 174

My app loads images from flickr using Android's Picasso library. Curiously it was working fine sometime ago after migrating my app to Kotlin, but now I've started to have "random" 503 errors.

I've set all the permissions in flickr control panel for each image so they're fully public and set security to lowest level to no avail.

At first I thought lowering security in flickr was the key, but was wrong, because I'm still having this issue. Maybe it is not related to Kotlin migration at all, but I remember it was working fine not so long ago.

The weird thing is that if I debug and copy the url and paste it in a browser it just loads fine.

This next is the method where I load the Home Screen image:

private fun setTodaysThoughtPainting() {
    binding!!.ivTtodaysThought.setOnClickListener { v: View? -> startThoughtActivity("") }
    val isTodayThought = AWPreferences.todayThoughtPrefIsToday(this)
    mainPainting = mainViewModel!!.getTodaysPainting(isTodayThought)
    //FLICKR URL EXAMPLE: mainPainting.setUrl("https://live.staticflickr.com/xxx/xxx_xxx_o_d.jpg");
    if (mainPainting != null) {
        Picasso.get().load(mainPainting!!.url)
            .transform(RoundedTransformation(cornerRadius, 0))
            .into(binding!!.ivTtodaysThought, object : Callback {
                override fun onSuccess() {
                    trackId = mainViewModel!!.getTodaysTrack(isTodayThought)
                    mainThought = mainViewModel!!.getTodaysThought(
                        mainPainting,
                        isTodayThought,
                        idLanguage,
                        trackId
                    )
                    if (mainThought != null) {
                        setMainShortenThought(mainThought!!)
                        setMainThoughtDate(Calendar.getInstance())
                        binding!!.ivTtodaysThought.viewTreeObserver.addOnGlobalLayoutListener(
                            object : OnGlobalLayoutListener {
                                override fun onGlobalLayout() {
                                    binding!!.ivTtodaysThought.viewTreeObserver.removeOnGlobalLayoutListener(
                                        this
                                    )
                                    val realImgSize = ImageHelper.getRealImageSize(
                                        binding!!.ivTtodaysThought
                                    )
                                    setThoughtMargin(realImgSize[0])
                                }
                            })
                    }
                }

                override fun onError(e: Exception) {
                    e.printStackTrace()
                }
            })
    }
}

Any help?

Edit 1:

This is the Picasso stack trace:

2022-06-15 23:59:03.231 32258-32258/com.xxx.xxx W/System.err: com.squareup.picasso.NetworkRequestHandler$ResponseException: HTTP 503
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.NetworkRequestHandler.load(NetworkRequestHandler.java:51)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:219)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:175)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.lang.Thread.run(Thread.java:929)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:354)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err: com.squareup.picasso.NetworkRequestHandler$ResponseException: HTTP 503
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.NetworkRequestHandler.load(NetworkRequestHandler.java:51)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:219)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:175)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.lang.Thread.run(Thread.java:929)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:354)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err: com.squareup.picasso.NetworkRequestHandler$ResponseException: HTTP 503
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.NetworkRequestHandler.load(NetworkRequestHandler.java:51)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:219)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:175)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2022-06-15 23:59:03.232 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2022-06-15 23:59:03.233 32258-32258/com.xxx.xxx W/System.err:     at java.lang.Thread.run(Thread.java:929)
2022-06-15 23:59:03.233 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:354)
2022-06-15 23:59:03.282 32258-32258/com.xxx.xxx W/System.err: com.squareup.picasso.NetworkRequestHandler$ResponseException: HTTP 503
2022-06-15 23:59:03.282 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.NetworkRequestHandler.load(NetworkRequestHandler.java:51)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:219)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:175)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at java.lang.Thread.run(Thread.java:929)
2022-06-15 23:59:03.283 32258-32258/com.xxx.xxx W/System.err:     at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:354)

enter image description here

Edit 1:

After struggling my head for months I finally found that this issue has nothing to do with Picasso.

I store my images in Flickr, and my conclusion is Flickr team have probably made changes (like security changes or whatever) because I tried with a different domain test image, in concrete this and its working. I've written Flickr support with no response yet.

I'm still stuck with this.

Edit 2:

It doesn't make any sense, but there are images that work and images that doesn't, when the configuration of each image is the same.

More stuck than ever :)

4 Answers

Error 503 means:

503 Service Unavailable: The HyperText Transfer Protocol (HTTP) 503 Service Unavailable server error response code indicates that the server is not ready to handle the request.

Maybe they have some works on servers. I can suggest you try later.

I am aware of the issue but for some reason it works with Glide library and not Picasso library.

I was also getting 503 error, which means 'service unavailable'. At first I also thought that the issue is related to Flickr servers but I am not 100% sure if it actually is an issue or it was designed that way. I am guessing that Flickr has a limit of how many requests you can make with free tier and when/if you cross that limit you will get 503 error.

My guess is that Glide is queuing up the requests where as Picasso isn't. I actually created a separate class to test this theory in which I handle the queuing of image requests and it worked.

Let me know if my answer helped you in any way.

I had this 503 error from flickr as well. The only difference was that I'm using Coil with Compose. In my case I've just added headers and stopped received 503 error.

@Composable
private fun PhotoItem(
    photoUrl: String,
) {
    val model = ImageRequest.Builder(LocalContext.current)
        .data(photoUrl)
        .addHeader("Accept-Encoding", "keep-alive")
        .addHeader("Connection", "gzip, deflate, br")
        .addHeader("User-Agent", "SomeUserAgent")
        .build()
    AsyncImage(
        modifier = Modifier
            .fillMaxWidth(),
        model = model,
        contentDescription = null,
        onState = { state ->
            when (state) {
                is AsyncImagePainter.State.Error -> {
                    // logs
                }
                else -> {}
            }
        }
    )
}

Still don't know if it helped because later it started to work without headers as well.

Ok, after a lot of time and headaches I've finally come with a solution.

Apparently (and according to my investigations) the problem comes from an Android security restriction regarding https and http connections. Since Marshmallow http connections are disabled by default, so the working solution I've found was to add the next setting in "application" tag in AndroidManifest.xml with removes this restriction.

android:usesCleartextTraffic="true"

I don't know if it is the best solution, not even know if it is secure, but given the huge amount of time I've invested on this for the moment I'll leave it like this.

I think the right solution should go in the direction of:

https://stackoverflow.com/a/61890208/2807741

But I did a quick test to no avail.

Edit 1

I'm fed up with this, what it seemed to be a solution ended not being it. Today I'm testing again and even with android:usesCleartextTraffic="true" set, I get a http 503 when loading the image with Picasso.

Related