emotionhero/app/src/main/java/com/rubenvandeven/emotionhero/ApiRestClient.java

278 lines
9.8 KiB
Java

package com.rubenvandeven.emotionhero;
import android.content.Context;
import android.graphics.PointF;
import android.util.Log;
import com.google.gson.Gson;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestHandle;
import com.loopj.android.http.RequestParams;
import com.loopj.android.http.SyncHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HeaderElement;
import cz.msebera.android.httpclient.ParseException;
import cz.msebera.android.httpclient.entity.StringEntity;
/**
* Created by ruben on 01/09/16.
*
* A way to interact with api.emotionhero.com
*/
public class ApiRestClient {
private static final String BASE_URL = "http://api.emotionhero.com"; // TODO: https!
private static AsyncHttpClient client = new AsyncHttpClient();
// private static SyncHttpClient syncClient = new SyncHttpClient();
private String jwt;
private Player player;
public ApiRestClient(Player player) {
this.player = player;
}
public void registerIfNeeded() {
if(player.getJWT() == null) {
requestWithJWT(null, null, null, null, null);
}
}
/**
* For now call register endpoint. Given JWT should have a long enough lifetime (for now)
* @todo However, custom token endpoint should be used eventually
* @param method
* @param url
* @param postBody
* @param getParams
* @param responseHandler
*/
public void requestWithJWT(final String method, final String url, final StringEntity postBody, final RequestParams getParams, final AsyncHttpResponseHandler responseHandler) {
// sync call, so we can return a value!
client.post(BASE_URL + "/api/register", null, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
// If the response is JSONObject instead of expected JSONArray
try {
String token = response.getString("jwt");
String remoteId = response.getString("id");
Log.d("API", "Token " + token);
Log.d("API", "RemoteId" + remoteId);
getPlayer().setJWT(token);
getPlayer().setRemoteId(remoteId);
if(method != null) {
ApiRestClient.this.request( method, url, postBody, getParams, responseHandler);
}
} catch (JSONException e) {
// responseHandler.sendFailureMessage(500, null, null);
// failure!!
// retrying later probably....
Log.e("API", "Failed request");
e.printStackTrace();
}
}
});
}
public Player getPlayer() {
return player;
}
class TokenHeader implements Header {
/**
* Get the name of the Header.
*
* @return the name of the Header, never {@code null}
*/
@Override
public String getName() {
return "X-Access-Token";
}
/**
* Get the value of the Header.
*
* @return the value of the Header, may be {@code null}
*/
@Override
public String getValue() {
return "Bearer " + player.getJWT();
}
/**
* Parses the value.
*
* @return an array of {@link HeaderElement} entries, may be empty, but is never {@code null}
* @throws ParseException
*/
@Override
public HeaderElement[] getElements() throws ParseException {
return new HeaderElement[]{};
}
}
public void request(String method, String url, StringEntity postBody, RequestParams getParams, AsyncHttpResponseHandler responseHandler) {
Header[] headers = new Header[]{new TokenHeader()};
Log.d("API", "Do request to: " + url);
if(method == "post") {
client.post(player.getContext(), url, headers, postBody,"application/json", responseHandler);
} else {
client.get(player.getContext(), url, headers, getParams, responseHandler);
}
}
public void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
String jwt = player.getJWT();
if(jwt != null) {
request("get", getAbsoluteUrl(url), null, params, responseHandler);
} else {
requestWithJWT("get", getAbsoluteUrl(url), null, params, responseHandler);
}
}
public void post(String url, StringEntity postBody, AsyncHttpResponseHandler responseHandler) {
String jwt = player.getJWT();
if(jwt != null) {
request("post", getAbsoluteUrl(url), postBody, null, responseHandler);
} else {
requestWithJWT("post", getAbsoluteUrl(url), postBody, null, responseHandler);
}
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
public void syncGame(final Game game) {
if(game.remoteId != null)
return;
RequestParams params = new RequestParams();
JSONObject j = new JSONObject();
try {
j.put("lvl_id", game.scenario.id);
j.put("score", game.score);
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(tz);
j.put("time", df.format(game.time));
JSONArray jHits = new JSONArray();
j.put("hits", jHits);
for(Hit hit: game.hits.values()) {
JSONObject jHit = new JSONObject();
jHit.put("id", hit.id);
jHit.put("target_index", hit.target.index);
jHit.put("score", hit.score);
jHit.put("glasses", hit.glasses);
jHit.put("ethnicity", hit.ethnicity);
jHit.put("age", hit.age);
jHit.put("gender", hit.gender);
JSONObject jExpressions = new JSONObject();
jHit.put("expressions", jExpressions);
JSONObject jEmotions = new JSONObject();
jHit.put("emotions", jEmotions);
JSONObject jPoints = new JSONObject();
jHit.put("points", jPoints);
for(Expression e: Expression.values()) {
jExpressions.put(e.getDbName(), hit.expressions.get(e));
}
for(Emotion e: Emotion.values()) {
jEmotions.put(e.getDbName(), hit.emotions.get(e));
}
int i=0;
for(PointF p: hit.points) {
JSONObject jPoint = new JSONObject();
jPoint.put("x", p.x);
jPoint.put("y", p.y);
jPoints.put(""+i, jPoint);
i++;
}
jHits.put(jHit);
}
} catch (JSONException e) {
e.printStackTrace();
}
StringEntity postBody = null;
try {
postBody = new StringEntity(j.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
this.post("/me/games", postBody, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
Log.d("API",response.toString());
GameOpenHelper gameHelper = new GameOpenHelper(player.getContext());
// set remote ids on hits and game.
try {
game.remoteId = response.getString("id");
JSONObject hits = response.getJSONObject("hits");
gameHelper.saveRemoteId(game);
for(Hit hit: game.hits.values()) {
hit.remoteId = hits.getString(Long.toString(hit.id));
gameHelper.saveRemoteId(hit);
}
} catch (JSONException e) {
Log.e("API","Invalid data: " + response.toString());
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
handleOnFailure(statusCode, headers, responseString, throwable);
}
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject response) {
onFailure(statusCode, headers, response.toString(), throwable);
}
});
}
public static void handleOnFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
Log.e("API", "FAILURE ON REQUEST!");
Log.e("API", throwable.getMessage());
Log.e("API", "Status: "+statusCode);
Log.e("API", "Headers:");
for(Header header: headers) {
Log.e("API", "\t" + header.getName() + ": " + header.getValue());
}
Log.e("API", "Response:");
int maxLogSize = 1000;
for(int i = 0; i <= responseString.length() / maxLogSize; i++) {
int start = i * maxLogSize;
int end = (i+1) * maxLogSize;
end = end > responseString.length() ? responseString.length() : end;
Log.e("API", responseString.substring(start, end));
}
}
}