Android: load image from URL

This post will be on an update I am working on for my puzzle games. With a 50mb upload limit for the base APK (zip file) for Google Play, I am limited to how many images I can supply in the application. I managed to get over a hundred different images but with each new image set I have to update the version for the APK. If I am loading the images from a web service, I no longer have to update the application itself. I can now just upload the file urls to the application from my server, and the application will take each url and load an image for each one. From here I can then store the scaled down image in the application folder and then not have to use the service to download from thereafter.

Code to start my service to get the JSON file with artwork data including title, artists and url for image download.

Intent intent = new Intent(getContext(), ArtworkJsonRetrievalService.class);
getContext().startService(intent);

Service class for downloading the file and converting it to a list of Artworks. Make sure you class implements Parcelable to send with the Intent. I have included some error handling for file error on retrieval and for validating an artwork is valid based on data existing.

package rick.artpuzzles0001.service;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;

/**
 * A class to get the JSON file with artwork information.
 */
public class ArtworkJsonRetrievalService extends IntentService {

    public static final String ARTWORK_SERVICE = "ARTWORK_SERVICE";
    public static final String ARTWORK_SERVICE_ERROR = "ARTWORK_SERVICE_ERROR";

    final String FILE_NAME = "artworklist.json";

    public ArtworkJsonRetrievalService() {
        super("ArtworkJsonRetrievalService");
    }

    @Override
    public void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String jsonString = getJsonFileString();
            try {
                if (jsonString != null && !jsonString.equals("")) {

                    // convert string to artworks
                    JSONObject obj = new JSONObject(jsonString);
                    GsonBuilder gsonBuilder = new GsonBuilder();
                    gsonBuilder.registerTypeAdapter(Artwork.class, new JsonDeserializer<Artwork>() {

                        @Override
                        public Artwork deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                            JsonObject jobject = json.getAsJsonObject();
                            try {
                                String titleOfArtwork = jobject.get("titleOfArtwork").getAsString();
                                if (titleOfArtwork.equals("")) return null;
                                String titleOfArtist = jobject.get("titleOfArtist").getAsString();
                                if (titleOfArtist.equals("")) return null;
                                String urlOfArtist = jobject.get("urlOfArtist").getAsString();
                                if (urlOfArtist.equals("")) return null;
                                String imageUrl = jobject.get("imageUrl").getAsString();
                                if (imageUrl.equals("")) return null;

                                return new Artwork(titleOfArtwork, titleOfArtist, urlOfArtist, imageUrl);
                            } catch (NullPointerException npe) {
                                return null;
                            }
                        }
                    });
                    Gson gson = gsonBuilder.create();
                    final Artworks artworks = gson.fromJson(obj.toString(), Artworks.class);

                    // remove nulls from list
                    if (artworks.getArtworks() != null) {
                        artworks.getArtworks().removeAll(Collections.singleton(null));
                    }

                    if (artworks.getArtworks() == null || artworks.getArtworks().isEmpty()) {
                        errorHandler();
                    } else {
                        new Handler(Looper.getMainLooper()).post(new Runnable() {
                            @Override
                            public void run() {
                                Intent intent = new Intent(ARTWORK_SERVICE);
                                intent.putExtra(Artworks.TAG, artworks);
                                sendBroadcast(intent);
                            }
                        });
                    }
                } else {
                    errorHandler();
                }
            } catch (JSONException e) {
                errorHandler();
            }
        }
    }

    private void errorHandler() {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(ARTWORK_SERVICE_ERROR);
                sendBroadcast(intent);
            }
        });
    }

    /**
     * Use the internet to get the json file or if on fail check for a backup
     *
     * @return the string that will be parsed into our artwork list
     */
    public String getJsonFileString() {

        // hit the server first
        HttpURLConnection urlConnection = null;
        String result = "";
        try {
            String jsonUrl = "https://www.mobileapplications009.com/puzzles/android/" + FILE_NAME;
            URL url = new URL(jsonUrl);
            urlConnection = (HttpURLConnection) url.openConnection();
            InputStream in = new BufferedInputStream(urlConnection.getInputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            result = sb.toString();

            // save to local private storage for re use later
            String fileContents = result;
            FileOutputStream outputStream;

            try {
                outputStream = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
                outputStream.write(fileContents.getBytes());
                outputStream.close();
            } catch (Exception e) {
                // don't worry if this breaks we will just run service again for it next time
            }
        } catch (MalformedURLException e) {

            // on bad url check for backup
            result = loadLocalJson();
            if (result.equals("")) {
                errorHandler();
            }
        } catch (IOException e) {

            // something went wrong, check for backup
            result = loadLocalJson();
            if (result.equals("")) {
                errorHandler();
            }
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }

        return result;
    }

    private String loadLocalJson() {
        File directory = getBaseContext().getFilesDir();
        File file = new File(directory, FILE_NAME);
        String result = "";
        if (file.exists()) {
            int length = (int) file.length();
            byte[] bytes = new byte[length];
            FileInputStream in = null;
            try {
                in = new FileInputStream(file);
                in.read(bytes);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            result = new String(bytes);
        }
        return result;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe for Post Notifications