Search code examples
javaandroidsplitandroid-image

How to replace low res image reference at end of URL string with the higher res image reference available


From an API I'm getting a thumbnail image from the URL string similar to this format: https://website.com/05b8a817448d0e2/0_167_3000_1799/500.jpg. However, it looks very blotchy for android app development.

There is no high-res image available from the API. However, I have discovered that by changing the end of the URL, the images exist at 1000px and even 2000px.

I want to change the URL string to the higher res version that exists at the same location with the improved suffix: https://website.com/05b8a817448d0e2/0_167_3000_1799/1000.jpg

Extra requirements:

  • Rarely the API gives different sizes other than 500, like 1000 or 250
  • In rare cases it ends with .png instead of .jpg (possibly even other formats)
  • In rare cases the image doesn't exist at a higher res and should be left alone

So the solution needs to be quite a lot more robust that my current coding capabilities.

This is my code block in Android Studio which works fine, but doesn't cover the extra requirements. I have only been coding in Java and Android Studio a few months so there may be some issues with it:

 /**
 * Load an image from a URL and return a {@link Bitmap}
 *
 * @param url string of the URL link to the image
 * @return Bitmap of the image
 */
private static Bitmap downloadBitmap(String url) {
    Bitmap bitmap = null;
    String newUrlString = url;

    try {
        // Change 500px image to 1000px image
        URL oldUrl = new URL(url);
        if (url.endsWith("500.jpg")) {
            newUrlString = oldUrl.toString().replaceFirst("500.jpg", "1000.jpg");
        }

        InputStream inputStream = new URL(newUrlString).openStream();
        bitmap = BitmapFactory.decodeStream(inputStream);
    } catch (Exception e) {
        Log.e(LOG_TAG, e.getMessage());
    }
    return bitmap;
}

Solution

  • try the following:

    protected class ImageLoader extends AsyncTask<String, Void, Bitmap> {
            protected Bitmap doInBackground(String... urls) {
                Bitmap bitmap = null;
                String originalUrl = urls[0];
                String url = urls[0].replaceFirst("/500.", "/1000.");
                try {
                    InputStream inputStream = new URL(url).openStream();
                    bitmap = BitmapFactory.decodeStream(inputStream);
                } catch (Exception e) {
                    try {
                        InputStream inputStream = new URL(originalUrl).openStream();
                        bitmap = BitmapFactory.decodeStream(inputStream);
                    } catch (Exception ignored) {
                    }
                }
                return bitmap;
            }
    
            protected void onPostExecute(Bitmap bitmap) {
                //do whatever you want with the result.
                if(bitmap!=null)
                image.setImageBitmap(bitmap);
            }
        }
    

    What I did here, is that I created an AsyncTask (since your original code will throw NetworkOnMainThreadException ) called ImageLoader. It will handle requesting the image url; if it fails to get the 1000px version, it will failover to the 500px version of the image. Hope this helps.