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.artinapplications.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 *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 2 other subscribers