Skip to content

Instantly share code, notes, and snippets.

@nissivm
Last active April 4, 2017 14:20
Show Gist options
  • Save nissivm/eb8629cf02b3740790c8037705209995 to your computer and use it in GitHub Desktop.
Save nissivm/eb8629cf02b3740790c8037705209995 to your computer and use it in GitHub Desktop.
Android - Looking for places with Yelp using Volley
<!-- In your AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="your.app.package">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
dependencies {
...
compile 'com.android.volley:volley:1.0.0'
}
package your.app.package;
import android.os.Parcel;
import android.os.Parcelable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.UUID;
@SuppressWarnings("SpellCheckingInspection")
class Business implements Parcelable
{
private JSONObject obj;
private String placeId = "";
private String placeName = "";
private String placeAddr = "";
private String placePhone = "";
private String placePriceLevel = "";
private double placeRating = 0;
private int placeReviewCount = 0;
private String placeImageUrl = "";
private String placeUrl = "";
private boolean placeClosed = true;
private double distance = 0;
private double placeLatitude = 0;
private double placeLongitude = 0;
Business(JSONObject obj)
{
this.obj = obj;
setProperties();
}
//----------------------------------------------------------------------------------------//
// Setters
//----------------------------------------------------------------------------------------//
private void setProperties()
{
UUID uuid = UUID.randomUUID();
placeId = uuid.toString();
String str = extractString("name");
if (str != null)
{
placeName = str;
}
str = extractAddress("location");
if (str != null)
{
placeAddr = str;
}
str = extractString("display_phone");
if (str != null)
{
placePhone = str;
}
str = extractString("price");
if (str != null)
{
placePriceLevel = str;
}
placeRating = extractDouble("rating");
placeReviewCount = extractInt("review_count");
str = extractString("image_url");
if (str != null)
{
placeImageUrl = str.replace("\\", "");
}
str = extractString("url");
if (str != null)
{
placeUrl = str.replace("\\", "");
}
placeClosed = extractPlaceCloseStatus();
placeLatitude = extractLatitude();
placeLongitude = extractLongitude();
}
void setDistance(double value)
{
distance = value;
}
//----------------------------------------------------------------------------------------//
// Getters
//----------------------------------------------------------------------------------------//
String getPlaceId()
{
return placeId;
}
String getPlaceName()
{
return placeName;
}
String getPlaceAddr()
{
return placeAddr;
}
String getPlacePhone()
{
return placePhone;
}
String getPlacePriceLevel()
{
return placePriceLevel;
}
double getPlaceRating()
{
return placeRating;
}
int getPlaceReviewCount()
{
return placeReviewCount;
}
String getPlaceImageUrl()
{
return placeImageUrl;
}
String getPlaceUrl()
{
return placeUrl;
}
boolean isPlaceClosed()
{
return placeClosed;
}
double getDistance()
{
return distance;
}
double getPlaceLatitude()
{
return placeLatitude;
}
double getPlaceLongitude()
{
return placeLongitude;
}
//----------------------------------------------------------------------------------------//
// Extraction functions
//----------------------------------------------------------------------------------------//
@SuppressWarnings("UnnecessaryLocalVariable")
private String extractString(String key)
{
try
{
String str = obj.getString(key);
return str;
}
catch (JSONException e)
{
//e.printStackTrace();
return null;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private String extractAddress(String key)
{
try
{
JSONObject location = obj.getJSONObject(key);
JSONArray displayAddr = location.getJSONArray("display_address");
String addr = "";
if (displayAddr.length() > 0)
{
for (int i = 0; i < displayAddr.length(); i++)
{
addr += displayAddr.getString(i);
if (i < (displayAddr.length() - 1))
{
addr += ", ";
}
}
}
return addr;
}
catch (JSONException e)
{
//e.printStackTrace();
return null;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private double extractDouble(String key)
{
try
{
double dbl = obj.getDouble(key);
return dbl;
}
catch (JSONException e)
{
//e.printStackTrace();
return 0;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private int extractInt(String key)
{
try
{
int i = obj.getInt(key);
return i;
}
catch (JSONException e)
{
//e.printStackTrace();
return 0;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private boolean extractPlaceCloseStatus()
{
try
{
boolean closed = obj.getBoolean("is_closed");
return closed;
}
catch (JSONException e)
{
//e.printStackTrace();
return true;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private double extractLatitude()
{
try
{
JSONObject coordinates = obj.getJSONObject("coordinates");
double lat = coordinates.getDouble("latitude");
return lat;
}
catch (JSONException e)
{
//e.printStackTrace();
return 0;
}
}
@SuppressWarnings("UnnecessaryLocalVariable")
private double extractLongitude()
{
try
{
JSONObject coordinates = obj.getJSONObject("coordinates");
double lng = coordinates.getDouble("longitude");
return lng;
}
catch (JSONException e)
{
//e.printStackTrace();
return 0;
}
}
//----------------------------------------------------------------------------------------//
// Parcelable
//----------------------------------------------------------------------------------------//
// Font: https://newfivefour.com/android-parcelable.html
public static final Parcelable.Creator<Business> CREATOR = new Parcelable.Creator<Business>()
{
public Business createFromParcel(Parcel in)
{
return new Business(in);
}
public Business[] newArray(int size)
{
return new Business[size];
}
};
private Business(Parcel in)
{
placeId = in.readString();
placeName = in.readString();
placeAddr = in.readString();
placePhone = in.readString();
placePriceLevel = in.readString();
placeRating = in.readDouble();
placeReviewCount = in.readInt();
placeImageUrl = in.readString();
placeUrl = in.readString();
boolean[] myBooleanArr = new boolean[1];
in.readBooleanArray(myBooleanArr);
placeClosed = myBooleanArr[0];
distance = in.readDouble();
placeLatitude = in.readDouble();
placeLongitude = in.readDouble();
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(placeId);
dest.writeString(placeName);
dest.writeString(placeAddr);
dest.writeString(placePhone);
dest.writeString(placePriceLevel);
dest.writeDouble(placeRating);
dest.writeInt(placeReviewCount);
dest.writeString(placeImageUrl);
dest.writeString(placeUrl);
dest.writeBooleanArray(new boolean[]{placeClosed});
dest.writeDouble(distance);
dest.writeDouble(placeLatitude);
dest.writeDouble(placeLongitude);
}
@Override
public int describeContents()
{
return 0;
}
}
package your.app.package;
public class MainActivity extends Activity implements LocationListener, ServerRequestInterface
{
private ServerRequest serverRequest;
private String yelpAccessToken = "";
private double userLat = 0;
private double userLong = 0;
private String[] placesNamesArray = {
"Restaurants", "Cafes", "Bakeries", "Bars", "Supermarkets", "Bookstores",
"Shopping", "Home goods", "Pets", "Museums", "Theaters", "Movie theaters",
"Churches", "Parks, Plazas & Zoos", "Bus stations", "Subway stations",
"Beauty salons", "Gym", "Pharmacies", "Hospitals"
};
// Font: https://www.yelp.com/developers/documentation/v3/all_category_list
private String[] placeCategoriesArray = {
"foodtrucks,restaurants,kiosk,dancerestaurants",
"acaibowls,bubbletea,churros,coffee,convenience,cupcakes,delicatessen,empanadas,friterie,gelato,icecream,internetcafe,milkshakebars,cakeshop,pretzels,tea,tortillas,coffeeshops",
"bakeries,bagels,donuts",
"barcrawl,bars,beergardens,jazzandblues,pianobars,poolhalls",
"butcher,ethicgrocery,farmersmarket,fishmonger,grocery,intlgrocery,organic_stores,markets,seafoodmarkets",
"bookstores,comicbooks,musicvideo,mags,usedbooks",
"childcloth,deptstores,hats,lingerie,maternity,menscloth,plus_size_fashion,shoes,sleepwear,sportswear,swimwear,vintage,womenscloth,shoppingcenters,thrift_stores,watches,wigs",
"furniture,homedecor,mattresses,gardening,outdoorfurniture,paintstores,tableware",
"emergencypethospital,groomer,vet",
"galleries,museums,planetarium",
"opera,theater",
"movietheaters",
"churches,synagogues",
"gardens,parks,playgrounds,publicplazas,zoos",
"busstations",
"metrostations",
"barbers,eyebrowservices,hair_extensions,waxing,hair,makeupartists,othersalons",
"cardioclasses,dancestudio,gyms,pilates,swimminglessons,taichi,yoga,gymnastics",
"drugstores,herbalshops,pharmacy,vitaminssupplements",
"emergencyrooms,hospitals,medcenters,urgent_care"
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serverRequest = new ServerRequest(this);
if (savedInstanceState != null)
{
yelpAccessToken = savedInstanceState.getString("yelpAccessToken");
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
outState.putString("yelpAccessToken", yelpAccessToken);
super.onSaveInstanceState(outState);
}
//----------------------------------------------------------------------------------------//
// LocationListener
//----------------------------------------------------------------------------------------//
@Override
public void onLocationChanged(Location location) // Not called in simulator
{
// Note: See my gist -> https://gist.github.com/nissivm/b3832ecaaa5d46af2e53c60626a5efee
userLat = location.getLatitude();
userLong = location.getLongitude();
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
startPlacesFetching();
}
//----------------------------------------------------------------------------------------//
// Start places fetching
//----------------------------------------------------------------------------------------//
private void startPlacesFetching()
{
if (yelpAccessToken.equals(""))
{
serverRequest.getYelpAccessToken();
}
else
{
serverRequest.fetchPlaces(userLat, userLong, yelpAccessToken, placeCategoriesArray[0]);
}
}
//----------------------------------------------------------------------------------------//
// ServerRequestInterface
//----------------------------------------------------------------------------------------//
@Override
public void yelpAccessTokenRequestResult(String result, String acessToken)
{
if (result.equals("Success"))
{
yelpAccessToken = acessToken;
serverRequest.fetchPlaces(userLat, userLong, yelpAccessToken, placeCategoriesArray[0]);
}
else
{
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, result, duration);
toast.show();
}
}
@Override
public void searchPlacesResult(String result, ArrayList<Business> businesses)
{
if (result.equals("Success"))
{
// Use businesses objcets somehow
}
else
{
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, result, duration);
toast.show();
}
}
}
package your.app.package;
import android.app.Application;
import com.android.volley.toolbox.Volley;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.RequestQueue;
// Note: https://www.yelp.com/developers/documentation/v3/get_started
public class MyApp extends Application
{
static final String YELP_APP_ID = "your-yelp-app-id";
static final String YELP_APP_SECRET = "your-yelp-app-secret";
private static final String TAG = "MyApp";
private static MyApp mInstance;
private RequestQueue mRequestQueue;
@Override
public void onCreate()
{
super.onCreate();
mInstance = this;
mRequestQueue = Volley.newRequestQueue(this);
}
//----------------------------------------------------------------------------------------//
// Get instance singleton
//----------------------------------------------------------------------------------------//
public static synchronized MyApp getInstance()
{
return mInstance;
}
//----------------------------------------------------------------------------------------//
// Volley
//----------------------------------------------------------------------------------------//
public void addJsonRequestToQueue(JsonObjectRequest jsObjRequest)
{
jsObjRequest.setTag(TAG);
mRequestQueue.add(jsObjRequest);
}
private void cancelPendingRequests()
{
mRequestQueue.cancelAll(TAG);
}
}
package your.app.package;
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
class PlacesRequest extends JsonObjectRequest
{
static String yelpAccessToken;
PlacesRequest(int method, String url, JSONObject jsonRequest,
Response.Listener<JSONObject> listener,
Response.ErrorListener errorListener)
{
super(method, url, jsonRequest, listener, errorListener);
}
PlacesRequest(String url, JSONObject jsonRequest,
Response.Listener<JSONObject> listener,
Response.ErrorListener errorListener)
{
super(url, jsonRequest, listener, errorListener);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError
{
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer " + yelpAccessToken);
return headers;
}
}
package your.app.package;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
@SuppressWarnings("SpellCheckingInspection")
class ServerRequest
{
private final String TAG = "ServerRequest";
private ServerRequestInterface interf;
private int index = 0;
private ArrayList<Business> businesses = new ArrayList<>();
ServerRequest(ServerRequestInterface i)
{
interf = i;
}
//----------------------------------------------------------------------------------------//
// Get yelp access token
//----------------------------------------------------------------------------------------//
void getYelpAccessToken()
{
String url = "https://api.yelp.com/oauth2/token?" + "grant_type=client_credentials" +
"&client_id=" + MyApp.YELP_APP_ID + "&client_secret=" + MyApp.YELP_APP_SECRET;
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, url, null,
new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject response)
{
try
{
String yelpAccessToken = response.getString("access_token");
interf.yelpAccessTokenRequestResult("Success", yelpAccessToken);
}
catch (JSONException e)
{
e.printStackTrace();
interf.yelpAccessTokenRequestResult("An error occurred, please try again.", null);
}
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
Log.e(TAG, "Error while getting Yelp Access Token: " + error.toString());
interf.yelpAccessTokenRequestResult("An error occurred, please try again.", null);
}
});
MyApp app = MyApp.getInstance();
app.addJsonRequestToQueue(jsObjRequest);
}
//----------------------------------------------------------------------------------------//
// Fetch places
//----------------------------------------------------------------------------------------//
void fetchPlaces(double userLat, double userLong, String yelpAccessToken, String placeCategory)
{
String url = "https://api.yelp.com/v3/businesses/search?" +
"latitude=" + userLat + "&longitude=" + userLong +
"&categories=" + placeCategory + "&locale=en_US" +
"&limit=" + 50 + "&sort_by=distance";
PlacesRequest.yelpAccessToken = yelpAccessToken;
PlacesRequest placesRequest = new PlacesRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject response)
{
try
{
JSONArray businessesArray = response.getJSONArray("businesses");
if (businessesArray.length() > 0)
{
if (businesses.size() > 0)
{
businesses.clear();
}
createBusinessObjects(businessesArray);
}
else
{
interf.searchPlacesResult("Search returned no results for your surroundings.", null);
}
}
catch (JSONException e)
{
e.printStackTrace();
interf.searchPlacesResult("An error occurred, please try again.", null);
}
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
interf.searchPlacesResult("An error occurred or this app has reached it's daily search quota.", null);
}
});
MyApp app = MyApp.getInstance();
app.addJsonRequestToQueue(placesRequest);
}
//----------------------------------------------------------------------------------------//
// Create Business objects
//----------------------------------------------------------------------------------------//
private void createBusinessObjects(JSONArray businessesArray)
{
try
{
JSONObject obj = businessesArray.getJSONObject(index);
Business business = new Business(obj);
if (!business.isPlaceClosed())
{
if (!business.getPlaceName().equals("") && !business.getPlaceAddr().equals("") &&
(business.getPlaceLatitude() != 0) && (business.getPlaceLongitude() != 0))
{
businesses.add(business);
}
}
if (index < (businessesArray.length() - 1))
{
index++;
createBusinessObjects(businessesArray);
}
else
{
index = 0;
if (businesses.size() > 0)
{
interf.searchPlacesResult("Success", businesses);
}
else
{
interf.searchPlacesResult("Search returned no results for your surroundings.", null);
}
}
}
catch (JSONException e)
{
e.printStackTrace();
if (index < (businessesArray.length() - 1))
{
index++;
createBusinessObjects(businessesArray);
}
else
{
index = 0;
if (businesses.size() > 0)
{
interf.searchPlacesResult("Success", businesses);
}
else
{
interf.searchPlacesResult("Search returned no results for your surroundings.", null);
}
}
}
}
}
package your.app.package;
import java.util.ArrayList;
interface ServerRequestInterface
{
void yelpAccessTokenRequestResult(String result, String accessToken);
void searchPlacesResult(String result, ArrayList<Business> businesses);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment