/** * Copyright 2010 Tauno Talimaa */ package com.joelapenna.foursquared.providers; import com.joelapenna.foursquare.Foursquare; import com.joelapenna.foursquare.error.FoursquareError; import com.joelapenna.foursquare.error.FoursquareException; import com.joelapenna.foursquare.types.Group; import com.joelapenna.foursquare.types.Venue; import com.joelapenna.foursquared.Foursquared; import com.joelapenna.foursquared.FoursquaredSettings; import com.joelapenna.foursquared.error.LocationException; import com.joelapenna.foursquared.location.BestLocationListener; import com.joelapenna.foursquared.location.LocationUtils; import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.MatrixCursor; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.util.Log; import java.io.IOException; /** * A ContentProvider for Foursquare search results. * * @author Tauno Talimaa (tauntz@gmail.com) */ public class GlobalSearchProvider extends ContentProvider { // TODO: Implement search for friends by name/phone number/twitter ID when // API is implemented in Foursquare.java private static final String TAG = GlobalSearchProvider.class.getSimpleName(); private static final boolean DEBUG = FoursquaredSettings.DEBUG; private static final String[] QSB_COLUMNS = { "_id", SearchManager.SUGGEST_COLUMN_ICON_1, SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2, SearchManager.SUGGEST_COLUMN_QUERY, SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING, SearchManager.SUGGEST_COLUMN_INTENT_DATA, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID }; private static final int URI_TYPE_QUERY = 1; private static final int URI_TYPE_SHORTCUT = 2; private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sUriMatcher.addURI(Foursquared.PACKAGE_NAME, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_TYPE_QUERY); sUriMatcher.addURI(Foursquared.PACKAGE_NAME, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", URI_TYPE_SHORTCUT); } public static final String VENUE_DIRECTORY = "venue"; public static final String FRIEND_DIRECTORY = "friend"; // TODO: Use the argument from SUGGEST_PARAMETER_LIMIT from the Uri passed // to query() instead of the hardcoded value (this is available starting // from API level 5) private static final int VENUE_QUERY_LIMIT = 30; private Foursquare mFoursquare; @Override public boolean onCreate() { synchronized (this) { if (mFoursquare == null) mFoursquare = Foursquared.createFoursquare(getContext()); } return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String query = uri.getLastPathSegment(); MatrixCursor cursor = new MatrixCursor(QSB_COLUMNS); switch (sUriMatcher.match(uri)) { case URI_TYPE_QUERY: if (DEBUG) { Log.d(TAG, "Global search for venue name: " + query); } Group<Group<Venue>> venueGroups; try { venueGroups = mFoursquare.venues(LocationUtils .createFoursquareLocation(getBestRecentLocation()), query, VENUE_QUERY_LIMIT); } catch (FoursquareError e) { if (DEBUG) Log.e(TAG, "Could not get venue list for query: " + query, e); return cursor; } catch (FoursquareException e) { if (DEBUG) Log.w(TAG, "Could not get venue list for query: " + query, e); return cursor; } catch (LocationException e) { if (DEBUG) Log.w(TAG, "Could not retrieve a recent location", e); return cursor; } catch (IOException e) { if (DEBUG) Log.w(TAG, "Could not get venue list for query: " + query, e); return cursor; } for (int groupIndex = 0; groupIndex < venueGroups.size(); groupIndex++) { Group<Venue> venueGroup = venueGroups.get(groupIndex); if (DEBUG) { Log.d(TAG, venueGroup.size() + " results for group: " + venueGroup.getType()); } for (int venueIndex = 0; venueIndex < venueGroup.size(); venueIndex++) { Venue venue = venueGroup.get(venueIndex); if (DEBUG) { Log.d(TAG, "Venue " + venueIndex + ": " + venue.getName() + " (" + venue.getAddress() + ")"); } cursor.addRow(new Object[] { venue.getId(), com.joelapenna.foursquared.R.drawable.venue_shortcut_icon, venue.getName(), venue.getAddress(), venue.getName(), venue.getId(), "true", VENUE_DIRECTORY, venue.getId() }); } } break; case URI_TYPE_SHORTCUT: if (DEBUG) { Log.d(TAG, "Global search for venue ID: " + query); } Venue venue; try { venue = mFoursquare.venue(query, LocationUtils .createFoursquareLocation(getBestRecentLocation())); } catch (FoursquareError e) { if (DEBUG) Log.e(TAG, "Could not get venue details for venue ID: " + query, e); return cursor; } catch (LocationException e) { if (DEBUG) Log.w(TAG, "Could not retrieve a recent location", e); return cursor; } catch (FoursquareException e) { if (DEBUG) Log.w(TAG, "Could not get venue details for venue ID: " + query, e); return cursor; } catch (IOException e) { if (DEBUG) Log.w(TAG, "Could not get venue details for venue ID: " + query, e); return cursor; } if (DEBUG) { Log.d(TAG, "Updated venue details: " + venue.getName() + " (" + venue.getAddress() + ")"); } cursor.addRow(new Object[] { venue.getId(), com.joelapenna.foursquared.R.drawable.venue_shortcut_icon, venue.getName(), venue.getAddress(), venue.getName(), venue.getId(), "true", VENUE_DIRECTORY, venue.getId() }); break; case UriMatcher.NO_MATCH: if (DEBUG) { Log.d(TAG, "No matching URI for: " + uri); } break; } return cursor; } @Override public String getType(Uri uri) { return SearchManager.SUGGEST_MIME_TYPE; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { throw new UnsupportedOperationException(); } @Override public Uri insert(Uri uri, ContentValues values) { throw new UnsupportedOperationException(); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { throw new UnsupportedOperationException(); } /** * Convenience method for getting the most recent Location * * @return the most recent Locations * @throws LocationException when no recent Location could be determined */ private Location getBestRecentLocation() throws LocationException { BestLocationListener locationListener = new BestLocationListener(); locationListener.updateLastKnownLocation((LocationManager) getContext().getSystemService( Context.LOCATION_SERVICE)); Location location = locationListener.getLastKnownLocation(); if (location != null) { return location; } throw new LocationException(); } }