com.partytv.server.ImageManager.java Source code

Java tutorial

Introduction

Here is the source code for com.partytv.server.ImageManager.java

Source

/*
 * Copyright (C) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.partytv.server;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.partytv.server.R;

import android.content.Context;
import android.database.DataSetObserver;
import android.os.Handler;
import android.util.Log;

/**
 * This class is responsible for downloading and parsing the search results for
 * a particular area. All of the work is done on a separate thread, and progress
 * is reported back through the DataSetObserver set in
 * {@link #addObserver(DataSetObserver). State is held in memory by in memory
 * maintained by a single instance of the ImageManager class.
 * 
 */
public class ImageManager {
    private static final String TAG = "Panoramio";

    /**
     * Base URL for Panoramio's web API
     */
    private static final String THUMBNAIL_URL = "//www.panoramio.com/map/get_panoramas.php?" + "order=popularity"
            + "&set=public" + "&from=0" + "&to=300" + "&miny=%f" + "&minx=%f" + "&maxy=%f" + "&maxx=%f"
            + "&size=original";
    //private static final String THUMBNAIL_URL = "//www.panoramio.com/map/get_panoramas.php?"
    //      + "order=popularity" + "&set=public" + "&from=0" + "&to=300" + "&miny=%f" + "&minx=%f"
    //    + "&maxy=%f" + "&maxx=%f" + "&size=original";
    //    private static final String THUMBNAIL_URL = "//www.panoramio.com/wapi/template/list.html?user=6863529";
    //            + "order=popularity" + "&set=public" + "&from=0" + "&to=300" + "&miny=%f" + "&minx=%f"
    //          + "&maxy=%f" + "&maxx=%f" + "&size=original";

    /**
     * Used to post results back to the UI thread
     */
    private static Handler mHandler = new Handler();

    /**
     * Holds the single instance of a ImageManager that is shared by the
     * process.
     */
    private static ImageManager sInstance;

    /**
     * Holds the images and related data that have been downloaded
     */
    private final ArrayList<PanoramioItem> mImages = new ArrayList<PanoramioItem>();

    private int mCurrentPosition;

    /**
     * Observers interested in changes to the current search results
     */
    private final ArrayList<WeakReference<DataSetObserver>> mObservers = new ArrayList<WeakReference<DataSetObserver>>();

    /**
     * True if we are in the process of loading
     */
    private static boolean mLoading;

    private static Context mContext;

    private volatile static String query;

    /**
     * Key for an Intent extra. The value is the zoom level selected by the
     * user.
     */
    public static final String ZOOM_EXTRA = "zoom";

    /**
     * Key for an Intent extra. The value is the latitude of the center of the
     * search area chosen by the user.
     */
    public static final String LATITUDE_E6_EXTRA = "latitudeE6";

    /**
     * Key for an Intent extra. The value is the latitude of the center of the
     * search area chosen by the user.
     */
    public static final String LONGITUDE_E6_EXTRA = "longitudeE6";

    /**
     * Key for an Intent extra. The value is an item to display
     */
    public static final String PANORAMIO_ITEM_EXTRA = "item";

    public static ImageManager getInstance(Context c) {
        if (sInstance == null) {
            sInstance = new ImageManager(c);
        }
        return sInstance;
    }

    private ImageManager(Context c) {
        mContext = c;
    }

    /**
     * @return True if we are still loading content
     */
    public boolean isLoading() {
        return mLoading;
    }

    /**
     * Clear all downloaded content
     */
    public void clear() {
        File cacheDir = mContext.getCacheDir();
        for (File file : cacheDir.listFiles()) {
            file.delete();
        }
        cacheDir.delete();
        for (PanoramioItem item : mImages) {
            item.clear();
            item = null;
        }
        mImages.clear();
        notifyInvalidateObservers();
    }

    public PanoramioItem getNext() {
        if (mCurrentPosition + 1 <= mImages.size() - 1) {
            mCurrentPosition = mCurrentPosition + 1;
            return mImages.get(mCurrentPosition);
        }
        return null;
    }

    public PanoramioItem getPrevious() {
        if (mCurrentPosition - 1 >= 0) {
            mCurrentPosition = mCurrentPosition - 1;
            return mImages.get(mCurrentPosition);
        }
        return null;
    }

    /**
     * Add an item to and notify observers of the change.
     * 
     * @param item The item to add
     */
    private void add(PanoramioItem item) {
        if (item.getLocation() != query) {
            return;
        }
        mImages.add(item);
        notifyObservers();
    }

    /**
     * @return The number of items displayed so far
     */
    public int size() {
        return mImages.size();
    }

    /**
     * Gets the item at the specified position
     */
    public PanoramioItem get(int position) {
        mCurrentPosition = position;
        if (mImages.size() > position) {
            return mImages.get(position);
        }
        return null;
    }

    /**
     * Adds an observer to be notified when the set of items held by this
     * ImageManager changes.
     */
    public void addObserver(DataSetObserver observer) {
        final WeakReference<DataSetObserver> obs = new WeakReference<DataSetObserver>(observer);
        mObservers.add(obs);
    }

    Thread mPrevThread = null;

    /**
     * Load a new set of search results for the specified area.
     * 
     * @param minLong The minimum longitude for the search area
     * @param maxLong The maximum longitude for the search area
     * @param minLat The minimum latitude for the search area
     * @param maxLat The minimum latitude for the search area
     * @throws JSONException
     * @throws URISyntaxException
     * @throws IOException
     */
    public void load(String query) throws IOException, URISyntaxException, JSONException {

        //this.query = query;
        this.query = "San Jose";
        clear();
        mLoading = true;

        GeoResponse location = null;
        try {
            location = new GeoCoderTask().execute(query).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        if (location != null) {

            mPrevThread = new ImageLoader(location.getMinLatitude(), location.getMinLongitude(),
                    location.getMaxLatitude(), location.getMaxLongitude(), query);
            //                 mPrevThread = new ImageLoader(0, 0,
            //                  0, 0, query);
            mPrevThread.start();

        } else {
            Log.e(TAG, "Geocoder returned no location");
        }
    }

    /**
     * Called when something changes in our data set. Cleans up any weak
     * references that are no longer valid along the way.
     */
    private void notifyObservers() {
        final ArrayList<WeakReference<DataSetObserver>> observers = mObservers;
        final int count = observers.size();
        for (int i = count - 1; i >= 0; i--) {
            final WeakReference<DataSetObserver> weak = observers.get(i);
            final DataSetObserver obs = weak.get();
            if (obs != null) {
                obs.onChanged();
            } else {
                observers.remove(i);
            }
        }
    }

    /**
     * Called when something changes in our data set. Cleans up any weak
     * references that are no longer valid along the way.
     */
    private void notifyInvalidateObservers() {
        final ArrayList<WeakReference<DataSetObserver>> observers = mObservers;
        final int count = observers.size();
        for (int i = count - 1; i >= 0; i--) {
            final WeakReference<DataSetObserver> weak = observers.get(i);
            final DataSetObserver obs = weak.get();
            if (obs != null) {
                obs.onInvalidated();
            } else {
                observers.remove(i);
            }
        }
    }

    /**
     * This thread does the actual work of fetching and parsing Panoramio JSON
     * response data.
     */
    private static class ImageLoader extends Thread {
        double mMinLong;

        double mMaxLong;

        double mMinLat;

        double mMaxLat;

        String mQuery;

        public ImageLoader(double minLatitude, double minLongitude, double maxLatitude, double maxLongitude,
                String query) {
            mMinLong = minLongitude;
            mMaxLong = maxLongitude;
            mMinLat = minLatitude;
            mMaxLat = maxLatitude;
            mQuery = query;
        }

        @Override
        public void run() {
            String url = THUMBNAIL_URL;
            //String url = "https://api-content.dropbox.com/1/files/dropbox/PartyTV";

            //String thumb_url = "https://api-content.dropbox.com/1/thumbnails/dropbox/PartyTV";
            //url = String.format(url, mMinLat, mMinLong, mMaxLat, mMaxLong);
            try {
                final URI uri = new URI("http", url, null);
                final HttpGet get = new HttpGet(uri);
                final HttpClient client = new DefaultHttpClient();
                final HttpResponse response = client.execute(get);
                final HttpEntity entity = response.getEntity();
                final String str = Utilities.convertStreamToString(entity.getContent());
                final JSONObject json = new JSONObject(str);
                parse(json);
            } catch (final Exception e) {
                Log.e(TAG, e.toString());
            }
        }

        private void parse(JSONObject json) {
            try {
                final JSONArray array = json.getJSONArray("photos");
                final int count = array.length();

                for (int i = 0; i < count; i++) {
                    if (!mQuery.equals(query)) {
                        break;
                    }
                    final boolean done = i == count - 1;
                    final JSONObject obj = array.getJSONObject(i);

                    final long id = obj.getLong("photo_id");
                    String title = obj.getString("photo_title");
                    final String owner = obj.getString("owner_name");
                    final String thumb = obj.getString("photo_file_url");
                    final String ownerUrl = obj.getString("owner_url");
                    final String photoUrl = obj.getString("photo_url");
                    final double latitude = obj.getDouble("latitude");
                    final double longitude = obj.getDouble("longitude");
                    final double width = obj.getDouble("width");
                    final double height = obj.getDouble("height");

                    /*
                    final double b_size = obj.getDouble("size");
                    final double b_bytes = obj.getDouble("bytes");
                    final String b_photoUrl = obj.getString("path");
                    final boolean b_is_dir = obj.getBoolean("is_dir");
                    final boolean b_is_deleted = obj.getBoolean("is_deleted");
                    final String b_rev = obj.getString("rev");
                    final boolean b_thumb_exists = obj.getBoolean("thumb_exists");
                    final String b_root = obj.getString("root");
                        
                    final String owner = "";
                    final String thumb = obj.getString("photo_file_url");
                    final String ownerUrl = obj.getString("owner_url");
                    final String photoUrl = obj.getString("photo_url");
                    final double latitude = 0.0;
                    final double longitude = 0.0;
                    final double width = obj.getDouble("width");
                    final double height = obj.getDouble("height");
                    */

                    if (title == null) {
                        title = mContext.getString(R.string.untitled);
                    }
                    // ignore small pictures, they appear pixelated on Google TV
                    // screen.2000 is a randomly chosen number.
                    if (width < 2000 || height < 2000) {
                        mHandler.post(new Runnable() {
                            public void run() {
                                sInstance.mLoading = !done;
                                sInstance.notifyObservers();
                            }
                        });
                        continue;
                    }
                    final PanoramioItem item = new PanoramioItem(mContext, id, thumb, (int) (latitude),
                            (int) (longitude), title, owner, ownerUrl, photoUrl, mQuery, mHandler);
                    // final PanoramioItem item = new PanoramioItem(mContext, b_rev, thumb,
                    //              (int) (latitude), (int) (longitude), title, owner, ownerUrl, b_photoUrl,
                    //            mQuery, mHandler);
                    item.loadLargeBitmap();
                    mHandler.post(new Runnable() {
                        public void run() {
                            sInstance.mLoading = !done;
                            sInstance.add(item);
                        }
                    });
                }

            } catch (final JSONException e) {
                Log.e(TAG, e.toString());
            }
        }
    }
}