//*****************************************************************************
// This file is part of CheckIn4Me. Copyright � 2010 David Ivins
//
// CheckIn4Me 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, either version 3 of the License, or
// (at your option) any later version.
//
// CheckIn4Me 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 CheckIn4Me. If not, see <http://www.gnu.org/licenses/>.
//*****************************************************************************
package com.davidivins.checkin4me.gowalla;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import com.davidivins.checkin4me.comparators.LocaleDistanceComparator;
import com.davidivins.checkin4me.core.Locale;
import com.davidivins.checkin4me.interfaces.APIInterface;
import com.davidivins.checkin4me.oauth.OAuth2Request;
import com.davidivins.checkin4me.oauth.OAuthResponse;
import com.davidivins.checkin4me.util.HTTPRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.*;
/**
* GowallaAPI
*
* @author david ivins
*/
public class GowallaAPI implements APIInterface
{
private static final String TAG = GowallaAPI.class.getSimpleName();
private int service_id;
private Properties config;
private List<Locale> latest_locations;
private boolean latest_checkin_status;
/**
* GowallaAPI
*
* @param config
* @param service_id
*/
public GowallaAPI(Properties config, int service_id)
{
Log.i(TAG, "service_id = " + service_id);
this.config = config;
this.service_id = service_id;
latest_locations = new ArrayList<Locale>();
latest_checkin_status = false;
}
/**
* getLocationsThread
*
* @param longitude
* @param latitude
* @param persistent_storage
* @return LocationThread
*/
public Runnable getLocationsThread(String query,String longitude, String latitude, SharedPreferences persistent_storage)
{
return new LocationsThread(query, longitude, latitude, persistent_storage);
}
/**
* getLatestLocations
*
* @return List<Locale>
*/
public List<Locale> getLatestLocations()
{
Collections.sort(latest_locations, new LocaleDistanceComparator());
return latest_locations;
}
/**
* getCheckInThread
*
* @param location
* @param persistent_storage
* @return CheckInThread
*/
public Runnable getCheckInThread(Locale location, String message, SharedPreferences persistent_storage)
{
latest_checkin_status = false;
return new CheckInThread(location, message, persistent_storage);
}
/**
* getLatestCheckInStatuse
*
* @return boolean
*/
public boolean getLatestCheckInStatus()
{
return latest_checkin_status;
}
/**
* LocationsThread
*
* @author david
*/
class LocationsThread implements Runnable
{
private String query;
private String longitude;
private String latitude;
private SharedPreferences persistent_storage;
/**
* LocationsThread
*
* @param query
* @param longitude
* @param latitude
* @param persistent_storage
*/
LocationsThread(String query, String longitude, String latitude, SharedPreferences persistent_storage)
{
this.query = query;
this.longitude = longitude;
this.latitude = latitude;
this.persistent_storage = persistent_storage;
}
/**
* run
*/
public void run()
{
Log.i(TAG, "Retrieving Gowalla Locations");
// build new http request
HTTPRequest request = new HTTPRequest(
config.getProperty("api_http_method"), config.getProperty("api_host"),
config.getProperty("api_locations_endpoint"));
// set request headers
request.addHeader("X-Gowalla-API-Key", config.getProperty("oauth_client_id"));
request.addHeader("Accept", "application/" + config.getProperty("api_format"));
// set query parameters
if (query != null)
request.addQueryParameterAndEncode("q", query);
request.addQueryParameter("lat", latitude);
request.addQueryParameter("lng", longitude);
request.addQueryParameter("radius", "50");
// execute http request
OAuthResponse response = (OAuthResponse)request.execute();
// save locations
if (response.getSuccessStatus())
setLocationsFromJson(response.getResponseString());
}
/**
* setLocationsFromJson
*
* @param json_string
* @throws JSONException
*/
synchronized private void setLocationsFromJson(String json_string)
{
// clear locations
latest_locations.clear();
// get user's current location as doubles
double user_longitude = Double.valueOf(persistent_storage.getString("current_longitude", "0.0"));
double user_latitude = Double.valueOf(persistent_storage.getString("current_latitude", "0.0"));
try
{
JSONObject json = new JSONObject(json_string);
JSONArray spots = json.getJSONArray("spots");
for (int i = 0; i < spots.length(); i++)
{
JSONObject spot = spots.getJSONObject(i);
String name = spot.getString("name");
String description = spot.getString("description");
String checkins_url = spot.getString("checkins_url");
String longitude = spot.getString("lng");
String latitude = spot.getString("lat");
JSONObject addr = spot.getJSONObject("address");
String city = addr.getString("locality");
String state = addr.getString("region");
String address = "";
String zip = "";
String[] temp = checkins_url.split("\\?");
String[] spot_id_key_value = temp[1].split("\\=");
String spot_id = spot_id_key_value[1];
Locale location = new Locale(name, description, longitude, latitude,
address, city, state, zip);
location.calculateAndSetDistanceFromUser(user_longitude, user_latitude);
location.mapServiceIdToLocationId(service_id, spot_id);
latest_locations.add(location);
}
}
catch (JSONException e)
{
Log.e(TAG, "JSON Exception: " + e.getMessage());
Log.e(TAG, "Could not parse json response: " + json_string);
}
}
}
/**
* LocationThread
*
* @author david
*/
class CheckInThread implements Runnable
{
private Locale location;
private String message;
private SharedPreferences persistent_storage;
private boolean token_refresh_attempted;
/**
* CheckInThread
*
* @param location
* @param persistent_storage
*/
CheckInThread(Locale location, String message, SharedPreferences persistent_storage)
{
this.location = location;
this.message = message;
this.persistent_storage = persistent_storage;
this.token_refresh_attempted = false;
}
/**
* run
*/
public void run()
{
Log.i(TAG, "Checking in with Gowalla");
boolean checkin_status = false;
// build new http request
HTTPRequest request = new HTTPRequest(
config.getProperty("oauth_http_method"), config.getProperty("api_secure_host"),
config.getProperty("api_checkin_endpoint"));
// set request headers
request.addHeader("X-Gowalla-API-Key", config.getProperty("oauth_client_id"));
request.addHeader("Accept", "application/" + config.getProperty("api_format"));
Map<Integer, String> service_id_location_id_xref = location.getServiceIdToLocationIdMap();
String spot_id = service_id_location_id_xref.get(service_id);
// set query parameters
request.addQueryParameter("oauth_token", persistent_storage.getString("gowalla_access_token", "-1"));
request.addQueryParameter("spot_id", spot_id);
request.addQueryParameter("comment", "");
request.addQueryParameter("lat", persistent_storage.getString("current_latitude", "-1"));
request.addQueryParameter("lng", persistent_storage.getString("current_longitude", "-1"));
// if post to twitter is enabled, post it
if (persistent_storage.getBoolean("gowalla_post_to_twitter_default", false))
request.addQueryParameter("post_to_twitter", "1");
else
request.addQueryParameter("post_to_twitter", "0");
// if post to facebook is enabled, post it
if (persistent_storage.getBoolean("gowalla_post_to_facebook_default", false))
request.addQueryParameter("post_to_facebook", "1");
else
request.addQueryParameter("post_to_facebook", "0");
if (!message.equals(""))
request.addQueryParameterAndEncode("comment", message);
// execute http request
OAuthResponse response = (OAuthResponse)request.execute();
// save locations
if (response.getSuccessStatus())
checkin_status = setStatusFromJson(response.getResponseString());
if (token_refresh_attempted == false && checkin_status == false)
{
token_refresh_attempted = true;
if (attemptToRefreshToken())
run();
else
Log.i(TAG, "Token refresh failed.");
}
}
/**
* setStatusFromJson
*
* @param json_string
* @throws JSONException
*/
synchronized private boolean setStatusFromJson(String json_string)
{
Log.i(TAG, "json_string = " + json_string);
// clear latest status
latest_checkin_status = false;
try
{
JSONObject json = new JSONObject(json_string);
@SuppressWarnings("unused")
String created_at = json.getString("created_at");
// if we found a created_at time/date and didn't throw an exception, check-in succeeded
latest_checkin_status = true;
}
catch (JSONException e)
{
Log.i(TAG, "JSON Exception: " + e.getMessage());
Log.i(TAG, "Could not parse json response: " + json_string);
}
return latest_checkin_status;
}
/**
* attemptToRefreshToken
*/
private boolean attemptToRefreshToken()
{
Log.i(TAG, "Attempting to refresh Gowalla OAuth token");
OAuthResponse response = new OAuthResponse();
Log.i(TAG, "refresh_token in persistent_storage = " + persistent_storage.getString("gowalla_refresh_token", "-1"));
if (persistent_storage.getString("gowalla_refresh_token", "-1") != "-1")
{
OAuth2Request request = new OAuth2Request(
config.getProperty("oauth_http_method"), config.getProperty("oauth_host"),
config.getProperty("oauth_access_token_endpoint"));
request.addQueryParameter("grant_type", "refresh_token");
request.addQueryParameter("client_id", config.getProperty("oauth_client_id"));
request.addQueryParameter("client_secret", config.getProperty("oauth_client_secret"));
request.addQueryParameter("refresh_token", persistent_storage.getString("gowalla_refresh_token", "-1"));
response = (OAuthResponse)request.execute();
}
else
{
Log.e(TAG, "Attempting to complete handshake without a code");
}
return setTokenFromJson(response.getResponseString());
}
/**
* setTokenFromJson
*/
private boolean setTokenFromJson(String json_string)
{
Log.i(TAG, "json_string = " + json_string);
Editor persistent_storage_editor = persistent_storage.edit();
boolean status = false;
try
{
JSONObject json = new JSONObject(json_string);
String access_token = json.getString("access_token");
String refresh_token = json.getString("refresh_token");
Log.i(TAG, "New Access Token = " + access_token);
Log.i(TAG, "New Refresh Token = " + refresh_token);
persistent_storage_editor.putString("gowalla_access_token", access_token);
persistent_storage_editor.putString("gowalla_refresh_token", refresh_token);
persistent_storage_editor.commit();
status = true;
}
catch (JSONException e)
{
Log.i(TAG, "JSON Exception: " + e.getMessage());
Log.i(TAG, "Could not parse json response: " + json_string);
}
return status;
}
}
}