package edu.mit.mitmobile2.mit150; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.os.Handler; import android.util.Log; import edu.mit.mitmobile2.Global; import edu.mit.mitmobile2.MobileWebApi; import edu.mit.mitmobile2.MobileWebApi.JSONObjectResponseListener; import edu.mit.mitmobile2.MobileWebApi.ServerResponseException; /* * Here be more dragons than the rest of the code * This code has a somewhat confused notion of caching * the database is mainly just used to cache images * and the rest of the data is cached in a json snipper */ public class MIT150Model { private static ArrayList<MIT150FeatureItem> features = null; public static ArrayList<MIT150MoreFeaturesItem> more_features = null; private boolean mainImagesFetched = false; private long lastModified; private String json; private MIT150DB mit150db; //HashMap<String, Bitmap> mThumbnails = new HashMap<String, Bitmap>(); static private String PREF_150_LAST_SAVED = "pref_150_last_saved"; static private String PREF_150_JSON = "pref_150_json"; //private SharedPreferences.Editor editor; /********************************************************************/ MIT150Model(Context ctx) { mit150db = MIT150DB.getInstance(ctx); } /********************************************************************/ public ArrayList<MIT150FeatureItem> getFeatures(Context ctx) { return features; } /********************************************************************/ public void fetchMIT150(final Context context, final Handler uiHandler) { if(features != null && more_features != null && mainImagesFetched) { MobileWebApi.sendSuccessMessage(uiHandler); return; } final SharedPreferences pref = context.getSharedPreferences(Global.PREFS,Context.MODE_WORLD_READABLE|Context.MODE_WORLD_READABLE); final long cachedLastSaved = pref.getLong(PREF_150_LAST_SAVED, -1); // keep for 6 hours if(System.currentTimeMillis() - cachedLastSaved < 6L * 60L * 60L * 1000L) { // cache less than 6 hours json = pref.getString(PREF_150_JSON, null); // don't download again but flag success if (json!=null) { try { handleJSON(new JSONObject(json)); } catch (JSONException e) { e.printStackTrace(); } } features = mit150db.getCachedFeatures(); mainImagesFetched = true; MobileWebApi.sendSuccessMessage(uiHandler); return; } MobileWebApi webApi = new MobileWebApi(false, true, "MIT150", context, uiHandler); HashMap<String, String> query = new HashMap<String, String>(); query.put("module", "features"); query.put("command", "list"); webApi.requestJSONObject(query, new JSONObjectResponseListener(new MobileWebApi.DefaultErrorListener(uiHandler), null) { @Override public void onResponse(JSONObject object) throws ServerResponseException, JSONException { handleJSON(object); json = object.toString(); new Thread() { @Override public void run() { if(cachedLastSaved == -1 || cachedLastSaved > lastModified) { // do not bother downloading new images // since data has not been modified since last saved mainImagesFetched = fetchMainImages(); if(!mainImagesFetched) { // early exit failed to receive main button images MobileWebApi.sendErrorMessage(uiHandler); return; } mit150db.updateFeatures(features); SharedPreferences.Editor editor = pref.edit(); editor.putLong(PREF_150_LAST_SAVED, System.currentTimeMillis()); editor.putString(PREF_150_JSON, json); editor.commit(); } else { features = mit150db.getCachedFeatures(); } MobileWebApi.sendSuccessMessage(uiHandler); } }.start(); } }); } private void handleJSON(JSONObject object) throws JSONException { lastModified = object.getLong("last-modified"); features = new ArrayList<MIT150FeatureItem>(); more_features = new ArrayList<MIT150MoreFeaturesItem>(); JSONArray fs = object.getJSONArray("features"); for(int i = 0; i < fs.length(); i++) { JSONObject jo = fs.getJSONObject(i); MIT150FeatureItem f = new MIT150FeatureItem(); f.id = jo.getString("id"); f.title = jo.getString("title"); f.subtitle = jo.optString("subtitle"); f.url = jo.getString("url"); f.photo_url = jo.getString("photo-url"); f.setTintColor(jo.getString("tint-color")); if(jo.has("title-color")) { f.setTitleColor(jo.getString("title-color")); } if(jo.has("arrow-color")) { f.setArrowColor(jo.getString("arrow-color")); } JSONObject dim = jo.getJSONObject("dimensions"); f.dim = f.new Dimension(); f.dim.height = dim.getInt("height"); f.dim.width = dim.getInt("width"); features.add(f); } fs = object.getJSONArray("more-features"); for(int i = 0; i < fs.length(); i++) { JSONObject jo = fs.getJSONObject(i); MIT150MoreFeaturesItem m = new MIT150MoreFeaturesItem(); m.section_title = jo.getString("section-title"); JSONArray fs2 = jo.getJSONArray("items"); m.items = new ArrayList<MIT150MoreItem>(); for (int j=0; j<fs2.length(); j++) { MIT150MoreItem mi = new MIT150MoreItem(); JSONObject joo = fs2.getJSONObject(j); mi.thumbnail152_url = joo.getString("thumbnail152-url"); mi.title = joo.getString("title"); mi.subtitle = joo.getString("subtitle"); mi.url = joo.getString("url"); m.items.add(mi); } more_features.add(m); } } /********************************************************************/ public boolean fetchMainImages() { BitmapFactory.Options opts = new BitmapFactory.Options(); for (MIT150FeatureItem f : features) { f.bm = getImage(f.photo_url,opts); if(f.bm == null) { return false; } } return true; } /********************************************************************/ public void fetchThumbnails(final Handler uiHandler, final ArrayList<MIT150MoreItem> items) { Thread t = new Thread() { @Override public void run() { Bitmap bm; BitmapFactory.Options opts = new BitmapFactory.Options(); for (MIT150MoreItem m : items) { if (m.thumbnail152_url==null) continue; if (m.bd!=null) continue; bm = getImage(m.thumbnail152_url,opts); //mThumbnails.put(m.thumbnail152_url, bm); if(bm != null) { m.bd = new BitmapDrawable(bm); mit150db.saveMoreThumbnail(m); } } // TODO cache? uiHandler.sendEmptyMessage(0); } }; t.start(); } /********************************************************************/ public Bitmap getImage(String url, BitmapFactory.Options decodeOptions) { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet request = new HttpGet(url); HttpResponse response; Log.d("MIT150", "requesting image " + url); try { response = httpClient.execute(request); if(response.getStatusLine().getStatusCode() == 200) { byte[] imageData = EntityUtils.toByteArray(response.getEntity()); return BitmapFactory.decodeByteArray(imageData, 0, imageData.length, decodeOptions); } } catch (IOException e) { e.printStackTrace(); } return null; } }