package edu.mit.mobile.android.livingpostcards.app; /* * Copyright (C) 2012-2013 MIT Mobile Experience Lab * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import java.io.IOException; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.stackoverflow.ArrayUtils; import edu.mit.mobile.android.imagecache.ImageCache; import edu.mit.mobile.android.imagecache.ImageCache.OnImageLoadListener; import edu.mit.mobile.android.flipr.R; import edu.mit.mobile.android.livingpostcards.data.Card; import edu.mit.mobile.android.locast.maps.LocatableMapFragment; public class CardMapFragment extends LocatableMapFragment { public static String[] CARD_PROJECTION = ArrayUtils.concat(LocatableMapFragment.PROJECTION, new String[] { Card.COL_THUMBNAIL, Card.COL_PRIVACY }); public static final String ARG_SHOW_MY_LOCATION = "edu.mit.mobile.android.livingpostcards.app.ARG_SHOW_MY_LOCATION"; private static final String TAG = CardMapFragment.class.getSimpleName(); public static CardMapFragment instantiate(Uri cardDir, boolean showMyLocation) { final Bundle args = new Bundle(1); args.putParcelable(ARG_LOCATABLE_DIR, cardDir); args.putBoolean(ARG_SHOW_MY_LOCATION, showMyLocation); final CardMapFragment f = new CardMapFragment(); f.setArguments(args); return f; } private ImageCache mImageCache; private CardInfoWindowAdapter mInfoWindowAdapter; private final OnImageLoadListener mOnImageLoadListener = new OnImageLoadListener() { @Override public void onImageLoaded(long id, Uri imageUri, Drawable image) { } @Override public void onImageLoaded(int id, Uri imageUri, Drawable image) { final Marker m = mPendingLoads.get(id); if (m != null) { m.showInfoWindow(); } } }; private void clearPendingLoads() { mPendingLoads.clear(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mImageCache = ImageCache.getInstance(getActivity()); }; @Override public void onPause() { super.onPause(); mImageCache.unregisterOnImageLoadListener(mOnImageLoadListener); } @Override public void onResume() { super.onResume(); mImageCache.registerOnImageLoadListener(mOnImageLoadListener); }; private final SparseArray<Marker> mPendingLoads = new SparseArray<Marker>(); private Drawable loadMarkerImage(Marker marker, Uri image) { final int id = mImageCache.getNewID(); Drawable imageDrawable = null; try { imageDrawable = mImageCache.loadImage(id, image, 320, 240); if (imageDrawable == null) { mPendingLoads.put(id, marker); } } catch (final IOException e) { Log.e(TAG, "error loading image", e); } return imageDrawable; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mImageCache = ImageCache.getInstance(getActivity()); final boolean showMyLocation = getArguments().getBoolean(ARG_SHOW_MY_LOCATION, false); setShowMyLocation(showMyLocation); final GoogleMap map = getMap(); // bail if there's no map if (map == null) { return; } mInfoWindowAdapter = new CardInfoWindowAdapter(getActivity(), this); map.setInfoWindowAdapter(mInfoWindowAdapter); // the map doesn't automatically snap to our current location, so we need to do that // somehow. if (showMyLocation) { final LocationManager lm = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE); final Location myLoc = lm.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); // XXX this returns null // final Location myLoc = getMap().getMyLocation(); if (myLoc != null) { map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLoc.getLatitude(), myLoc.getLongitude()), 16)); } } } @Override protected String[] getProjection() { return CARD_PROJECTION; } @Override protected MarkerOptions getMarker(Cursor c) { final MarkerOptions mo = super.getMarker(c); final boolean isCollaborative = Card.isCollaborative(c); mo.icon(BitmapDescriptorFactory .fromResource(isCollaborative ? R.drawable.ic_map_marker_collaborative : R.drawable.ic_map_marker_normal)); return mo; } public static class CardInfoWindowAdapter implements InfoWindowAdapter { private static final String[] PROJECTION_INFO_WINDOW = new String[] { Card.COL_THUMBNAIL, Card.COL_COVER_PHOTO, Card.COL_PRIVACY, Card.COL_AUTHOR }; private final CardMapFragment mCardMapFragment; private final View mContent; private final ContentResolver mCr; private final Context mContext; public CardInfoWindowAdapter(Context context, CardMapFragment cmf) { mCardMapFragment = cmf; final LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mContent = inflater.inflate(R.layout.card_map_info_window, null); mCr = context.getContentResolver(); mContext = context.getApplicationContext(); } @Override public View getInfoContents(Marker marker) { final View v = mContent; mCardMapFragment.clearPendingLoads(); final Uri item = mCardMapFragment.getItem(marker); final Cursor c = mCr.query(item, PROJECTION_INFO_WINDOW, null, null, null); try { String thumb; boolean isCollaborative = false; if (c.moveToFirst()) { isCollaborative = Card.isCollaborative(c); thumb = c.getString(c.getColumnIndex(Card.COL_COVER_PHOTO)); if (thumb == null) { thumb = c.getString(c.getColumnIndex(Card.COL_THUMBNAIL)); } if (thumb != null) { final Drawable d = mCardMapFragment.loadMarkerImage(marker, Uri.parse(thumb)); final ImageView imgView = (ImageView) v .findViewById(R.id.card_media_thumbnail); if (d != null) { imgView.setImageDrawable(d); } else { imgView.setImageResource(R.drawable.image_placeholder); } } ((TextView) v.findViewById(R.id.author)).setText(c.getString(c .getColumnIndex(Card.COL_AUTHOR))); } } finally { c.close(); } ((TextView) v.findViewById(R.id.title)).setText(marker.getTitle()); return v; } @Override public View getInfoWindow(Marker marker) { return null; } } }