package ca.grocerygo.android.utils; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.content.CursorLoader; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.widget.DrawerLayout; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; import ca.grocerygo.android.*; import ca.grocerygo.android.database.*; import ca.grocerygo.android.database.contentprovider.GroceryotgProvider; import ca.grocerygo.android.fragment.AboutDialogFragment; import ca.grocerygo.android.settings.SettingsActivity; import ca.grocerygo.android.settings.SettingsManager; import com.actionbarsherlock.app.SherlockFragmentActivity; import java.util.ArrayList; import java.util.List; import java.util.Set; public class GroceryGoUtils { public static final String BROADCAST_ACTION_RELOAD_GROCERY_LIST = "com.grocerygo.android.intent_action_reload_grocery_list"; public static final String BROADCAST_ACTION_FILTER_GROCERY_LIST = "com.grocerygo.android.intent_action_filter_grocery_list"; public static final String BROADCAST_ACTION_RELOAD_LOCATION = "com.grocerygo.android.intent_action_reload_location"; public static final String LOCATION_IS_LOATION_AVA = "isLocationAvailable"; public static final String LOCATION_IS_LOATION_TOGGLE_PROMTED = "isLocationTogglePrompted"; public static Cursor getStoreLocations(Context context) { String[] projection = {StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_NAME, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LATITUDE, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LONGITUDE}; Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_STO_JOIN_STOREPARENT, projection, null, null, null); return c; } public static Cursor getStoreIDs(Context context) { String[] projection = {StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ID, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_FLYER, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_PARENT}; Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_STO, projection, null, null, null); return c; } public static Cursor getStoreParentNamesCursor(Context context) { String[] projection = {StoreParentTable.COLUMN_STORE_PARENT_ID, StoreParentTable.COLUMN_STORE_PARENT_NAME}; Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_STOPARENT, projection, null, null, null); return c; } public static Cursor getGroceriesFromCartFromStores(Context context) { String[] projection = {CartTable.COLUMN_CART_GROCERY_ID, CartTable.COLUMN_CART_GROCERY_NAME, StoreTable.COLUMN_STORE_ID, StoreTable.COLUMN_STORE_LATITUDE, StoreTable.COLUMN_STORE_LONGITUDE}; Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_CART_JOIN_STORE, projection, null, null, null); return c; } public static int getMaxGroceryId(Context context) { String[] projection = {"Max(" + GroceryTable.COLUMN_GROCERY_ID + ")"}; Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_GRO, projection, null, null, null); c.moveToFirst(); return c.getInt(0); } public static SparseArray<String> getCategorySets(Context context) { SparseArray<String> categories = new SparseArray<String>(); Cursor c = context.getContentResolver().query(GroceryotgProvider.CONTENT_URI_CAT, null, null, null, null); c.moveToFirst(); while (!c.isAfterLast()) { categories.put( c.getInt(c.getColumnIndexOrThrow(CategoryTable.COLUMN_CATEGORY_ID)), c.getString(c.getColumnIndexOrThrow(CategoryTable.COLUMN_CATEGORY_NAME))); c.moveToNext(); } return categories; } public static SparseArray<String> getStoreParentNameSets(Context context) { SparseArray<String> storeNames = new SparseArray<String>(); Cursor storeCursor = GroceryGoUtils.getStoreParentNamesCursor(context); if (storeCursor != null) { storeCursor.moveToFirst(); while (!storeCursor.isAfterLast()) { storeNames.put(storeCursor.getInt(storeCursor.getColumnIndex(StoreParentTable.COLUMN_STORE_PARENT_ID)), storeCursor.getString(storeCursor.getColumnIndex(StoreParentTable.COLUMN_STORE_PARENT_NAME))); storeCursor.moveToNext(); } } return storeNames; } public static CursorLoader getAllStores(Context context) { List<String> selectionArgs = new ArrayList<String>(); String[] projection = {StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_NAME, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ADDR, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LATITUDE, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LONGITUDE}; String selection = ""; final String[] selectionArgsArr = new String[selectionArgs.size()]; selectionArgs.toArray(selectionArgsArr); return new CursorLoader(context, GroceryotgProvider.CONTENT_URI_STO_JOIN_STOREPARENT, projection, selection, selectionArgsArr, null); } public static CursorLoader getFilteredStores(Context context) { List<String> selectionArgs = new ArrayList<String>(); String[] projection = {StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_ID, StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_NAME, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_ADDR, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LATITUDE, StoreTable.TABLE_STORE + "." + StoreTable.COLUMN_STORE_LONGITUDE}; String selection = ""; SparseBooleanArray selectedStores = SettingsManager.getStoreFilter(context); if (selectedStores != null && selectedStores.size() > 0) { // Go through selected stores and add them to query String storeSelection = ""; for (int storeNum = 0; storeNum < selectedStores.size(); storeNum++) { if (selectedStores.valueAt(storeNum) == true) { if (storeSelection.isEmpty()) { storeSelection += StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_ID + " = ?"; } else { storeSelection += " OR " + StoreParentTable.TABLE_STORE_PARENT + "." + StoreParentTable.COLUMN_STORE_PARENT_ID + " = ?"; } selectionArgs.add(((Integer) selectedStores.keyAt(storeNum)).toString()); } } if (!storeSelection.isEmpty()) { selection += storeSelection; } } final String[] selectionArgsArr = new String[selectionArgs.size()]; selectionArgs.toArray(selectionArgsArr); return new CursorLoader(context, GroceryotgProvider.CONTENT_URI_STO_JOIN_STOREPARENT, projection, selection, selectionArgsArr, null); } public static Location getLastKnownLocation(Context context) { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); List<String> providers = lm.getProviders(true); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor settingsEditor = settings.edit(); // Loop over the array backwards (more accurate) // if you get an accurate location, then break out the loop Location loc = null; for (int i = providers.size() - 1; i >= 0; i--) { loc = lm.getLastKnownLocation(providers.get(i)); if (loc != null) break; } // Since the user disabled GPS, we assume they are in downtown Toronto if (loc == null) { settingsEditor.putBoolean(LOCATION_IS_LOATION_AVA, false); loc = new Location("Mock Location"); loc.setLatitude(43.6481); loc.setLongitude(-79.4042); } else{ settingsEditor.putBoolean(LOCATION_IS_LOATION_AVA, true); } settingsEditor.commit(); return loc; } public static int getClosestStore(ArrayList<Integer> storeIds, SparseArray<Float> distanceMap) { /* * storeIds: list of store_ids * distanceMap: <store_id, distance> * * Returns the store_id of the store with the minimal distance from the user's last known location */ float closestDistance = -1; int closestStore = 0; if (storeIds != null && distanceMap != null) { for (int j = 0; j < storeIds.size(); j++) { float nextDistance = distanceMap.get(storeIds.get(j)); if (closestDistance < 0 || nextDistance < closestDistance) { closestDistance = nextDistance; closestStore = storeIds.get(j); } } } return closestStore; } public static SparseArray<Float> buildDistanceMap(Context context) { Cursor storeLocations = GroceryGoUtils.getAllStores(context).loadInBackground(); SparseArray<Float> map = new SparseArray<Float>(); int storeID; double storeLat; double storeLng; Location storeLoc; float distance; Location loc = GroceryGoUtils.getLastKnownLocation(context); storeLocations.moveToFirst(); while (!storeLocations.isAfterLast()) { storeID = storeLocations.getInt(storeLocations.getColumnIndex(StoreTable.COLUMN_STORE_ID)); if (map.get(storeID) != null) { storeLocations.moveToNext(); continue; } storeLat = storeLocations.getDouble(storeLocations.getColumnIndex(StoreTable.COLUMN_STORE_LATITUDE)); storeLng = storeLocations.getDouble(storeLocations.getColumnIndex(StoreTable.COLUMN_STORE_LONGITUDE)); storeLoc = new Location("Store Location"); storeLoc.setLatitude(storeLat); storeLoc.setLongitude(storeLng); // calculate the distance in meters between the current user location and the store's location distance = loc.distanceTo(storeLoc); map.put(storeID, distance); storeLocations.moveToNext(); } return map; } /** * Method copies the intent extras from the received intent to the intent * that will be dispatched. * * @param aReceived * @param aDispatch */ public static void copyIntentData(Intent aReceived, Intent aDispatch) { Set<String> lKeys = aReceived.getExtras().keySet(); for (String lKey : lKeys) { aDispatch.putExtra(lKey, aReceived.getStringExtra(lKey)); } } public static class NavigationDrawerBundle { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; public NavigationDrawerBundle(DrawerLayout drawerLayout, ListView drawerList, ActionBarDrawerToggle drawerToggle) { this.mDrawerLayout = drawerLayout; this.mDrawerList = drawerList; this.mDrawerToggle = drawerToggle; } /** * @return the drawerLayout */ public DrawerLayout getDrawerLayout() { return mDrawerLayout; } /** * @return the drawerList */ public ListView getDrawerList() { return mDrawerList; } /** * @return the drawerToggle */ public ActionBarDrawerToggle getDrawerToggle() { return mDrawerToggle; } } public static void configActionBar(Activity activity) { ((SherlockFragmentActivity) activity).getSupportActionBar().setDisplayHomeAsUpEnabled(true); ((SherlockFragmentActivity) activity).getSupportActionBar().setHomeButtonEnabled(true); } public static GroceryGoUtils.NavigationDrawerBundle configNavigationDrawer(final Activity activity, boolean isTopView, final int titleResId) { DrawerLayout drawerLayout; ListView drawerList; ActionBarDrawerToggle drawerToggle = null; configActionBar(activity); NavigationDrawerListViewModel[] rowModels = new NavigationDrawerListViewModel[]{ new NavigationDrawerListViewModel(R.string.navdrawer_heading_places, -1, true), new NavigationDrawerListViewModel(R.string.navdrawer_item_cat, R.drawable.ic_menu_home, false), new NavigationDrawerListViewModel(R.string.navdrawer_item_cart, R.drawable.ic_menu_cart, false), new NavigationDrawerListViewModel(R.string.navdrawer_item_map, R.drawable.ic_menu_map, false), new NavigationDrawerListViewModel(R.string.navdrawer_heading_tools, -1, true), new NavigationDrawerListViewModel(R.string.navdrawer_item_settings, R.drawable.ic_menu_settings, false), new NavigationDrawerListViewModel(R.string.navdrawer_item_about, R.drawable.ic_menu_about, false) }; drawerLayout = (DrawerLayout) activity.findViewById(R.id.navigation_drawer_layout); drawerToggle = new ActionBarDrawerToggle(activity, drawerLayout, R.drawable.ic_drawer, R.string.navdrawer_open, R.string.navdrawer_closed) { public void onDrawerClosed(View view) { if (!SettingsManager.getNavigationDrawerSeen(activity)) SettingsManager.setNavigationDrawerSeen(activity, true); ((SherlockFragmentActivity) activity).getSupportActionBar().setTitle(activity.getString(titleResId)); ((SherlockFragmentActivity) activity).supportInvalidateOptionsMenu(); } public void onDrawerOpened(View drawerView) { if (!SettingsManager.getNavigationDrawerSeen(activity)) SettingsManager.setNavigationDrawerSeen(activity, true); ((SherlockFragmentActivity) activity).getSupportActionBar().setTitle(activity.getString(R.string.app_name)); ((SherlockFragmentActivity) activity).supportInvalidateOptionsMenu(); } }; if (!isTopView) { drawerToggle.setDrawerIndicatorEnabled(false); } drawerLayout.setDrawerListener(drawerToggle); drawerList = (ListView) activity.findViewById(R.id.navigation_drawer_view); drawerList.setAdapter(new GroceryGoUtils.NavigationDrawerAdapter(activity, rowModels)); drawerList.setOnItemClickListener(new NavigationDrawerItemClickListener(activity, drawerLayout, drawerList)); if (isTopView) { // Handle first-time viewing of navigaton drawer if (!SettingsManager.getNavigationDrawerSeen(activity)) { drawerLayout.openDrawer(drawerList); } } GroceryGoUtils.NavigationDrawerBundle bundle = new GroceryGoUtils.NavigationDrawerBundle(drawerLayout, drawerList, drawerToggle); return bundle; } private static class NavigationDrawerListViewModel { public int mTitleResId; public int mIconResId; public boolean mIsHeader; public NavigationDrawerListViewModel(int titleResId, int iconResId, boolean isHeader) { this.mIconResId = iconResId; this.mTitleResId = titleResId; this.mIsHeader = isHeader; } } private static class NavigationDrawerAdapter extends BaseAdapter { Context mContext; NavigationDrawerListViewModel[] mRowModels; int mCount; LayoutInflater mInflater; public NavigationDrawerAdapter(Context context, NavigationDrawerListViewModel[] rowModels) { this.mContext = context; this.mRowModels = rowModels; this.mCount = mRowModels.length; } @Override public int getCount() { return this.mCount; } @Override public NavigationDrawerListViewModel getItem(int position) { return mRowModels[position]; } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return getItem(position).mIsHeader ? 0 : 1; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView titleView; ImageView iconView; mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View itemView; if (getItem(position).mIconResId > 0) { itemView = mInflater.inflate(R.layout.navdrawer_item, parent, false); iconView = (ImageView) itemView.findViewById(R.id.navdrawer_item_icon); iconView.setImageResource(getItem(position).mIconResId); } else { itemView = mInflater.inflate(R.layout.navdrawer_header, parent, false); } titleView = (TextView) itemView.findViewById(R.id.navdrawer_item_title); titleView.setText(getItem(position).mTitleResId); return itemView; } @Override public int getViewTypeCount() { return 2; } @Override public boolean isEnabled(int position) { return !getItem(position).mIsHeader; } } private static class NavigationDrawerItemClickListener implements ListView.OnItemClickListener { Context mContext; private DrawerLayout mDrawerLayout; private ListView mDrawerList; NavigationDrawerItemClickListener(Context context, DrawerLayout drawerLayout, ListView drawerList) { this.mContext = context; this.mDrawerLayout = drawerLayout; this.mDrawerList = drawerList; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mDrawerLayout.isDrawerOpen(mDrawerList)) mDrawerLayout.closeDrawer(mDrawerList); switch (position) { case 1: launchHomeActivity(mContext); break; case 2: launchShopCartActivity(mContext); break; case 3: launchMapActivity(mContext); break; case 5: launchSettingsActivity(mContext); break; case 6: launchAboutDialog(mContext); break; } } } public static void launchHomeActivity(Context context) { Intent intent = new Intent(context, CategoryTopFragmentActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(intent); } public static void launchGroceryPagerActivity(Context context, int position) { Intent intent = new Intent(context, GroceryPagerFragmentActivity.class); //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Add an extra to tell the pager to return to the first page Bundle extras = new Bundle(); extras.putInt(GroceryPagerFragmentActivity.EXTRA_LAUNCH_PAGE, position); intent.putExtras(extras); context.startActivity(intent); } public static void launchMapActivity(Context context) { Intent intent = new Intent(context, MapFragmentActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(intent); } public static void launchShopCartActivity(Context context) { Intent intent = new Intent(context, ShopCartOverviewFragmentActivity.class); context.startActivity(intent); } public static void launchSettingsActivity(Context context) { Intent intent = new Intent(context, SettingsActivity.class); context.startActivity(intent); } public static void launchAboutDialog(Context context) { AboutDialogFragment dialog = new AboutDialogFragment(); dialog.show(((SherlockFragmentActivity) context).getSupportFragmentManager(), "about_dialog"); } public static void restartGroceryLoaders(Context context) { Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION_RELOAD_GROCERY_LIST); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } public static void reloadGroceryLocation(Context context) { Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION_RELOAD_LOCATION); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } public static int getVersionCode(Context mContext) { int versionCode = 0; try { versionCode = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return versionCode; } }