mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
Refactor API response handling for better error messaging.
This commit is contained in:
parent
8ab30d2951
commit
ada0817905
12 changed files with 413 additions and 379 deletions
|
@ -2,6 +2,11 @@
|
|||
|
||||
<string name="newsblur">NewsBlur</string>
|
||||
|
||||
<string name="error_unset_message">An unknown error occurred</string>
|
||||
<string name="error_http_connection">There was a problem connecting to NewsBlur</string>
|
||||
<string name="error_read_connection">There was a problem communicating with NewsBlur</string>
|
||||
<string name="error_offline">There was a problem connecting to the network</string>
|
||||
|
||||
<string name="login_username_hint">username</string>
|
||||
<string name="login_password_hint">password</string>
|
||||
<string name="login_registration_email_hint">email address</string>
|
||||
|
|
|
@ -85,7 +85,7 @@ public class LoginProgressFragment extends Fragment {
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(LoginResponse result) {
|
||||
if (result.authenticated) {
|
||||
if (result.isError()) {
|
||||
final Animation a = AnimationUtils.loadAnimation(getActivity(), R.anim.text_down);
|
||||
updateStatus.setText(R.string.login_logged_in);
|
||||
loggingInProgress.setVisibility(View.GONE);
|
||||
|
@ -103,11 +103,7 @@ public class LoginProgressFragment extends Fragment {
|
|||
getActivity().startActivity(startMain);
|
||||
|
||||
} else {
|
||||
if (result.errors != null && result.errors.message != null) {
|
||||
Toast.makeText(getActivity(), result.errors.message[0], Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(getActivity(), getResources().getString(R.string.login_message_error), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
Toast.makeText(getActivity(), result.getErrorMessage(), Toast.LENGTH_LONG).show();
|
||||
startActivity(new Intent(getActivity(), Login.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@ import com.newsblur.activity.AddSites;
|
|||
import com.newsblur.activity.Login;
|
||||
import com.newsblur.activity.LoginProgress;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.network.domain.LoginResponse;
|
||||
import com.newsblur.network.domain.RegisterResponse;
|
||||
|
||||
public class RegisterProgressFragment extends Fragment {
|
||||
|
||||
private APIManager apiManager;
|
||||
private String TAG = "LoginProgress";
|
||||
private String TAG = "RegisterProgress";
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
@ -87,7 +87,7 @@ public class RegisterProgressFragment extends Fragment {
|
|||
|
||||
private class RegisterTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
private LoginResponse response;
|
||||
private RegisterResponse response;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
|
@ -118,7 +118,7 @@ public class RegisterProgressFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
private String extractErrorMessage(LoginResponse response) {
|
||||
private String extractErrorMessage(RegisterResponse response) {
|
||||
String errorMessage = null;
|
||||
if(response.errors != null) {
|
||||
if(response.errors.email != null && response.errors.email.length > 0) {
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
package com.newsblur.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Scanner;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.newsblur.domain.ValueMultimap;
|
||||
import com.newsblur.util.NetworkUtils;
|
||||
import com.newsblur.util.PrefConstants;
|
||||
|
||||
public class APIClient {
|
||||
|
||||
private Context context;
|
||||
|
||||
public APIClient(final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public APIResponse get(final String urlString) {
|
||||
HttpURLConnection connection = null;
|
||||
if (!NetworkUtils.isOnline(context)) {
|
||||
APIResponse response = new APIResponse();
|
||||
response.isOffline = true;
|
||||
return response;
|
||||
}
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
Log.d(this.getClass().getName(), "API GET " + url );
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||
final String cookie = preferences.getString(PrefConstants.PREF_COOKIE, null);
|
||||
if (cookie != null) {
|
||||
connection.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
return extractResponse(url, connection);
|
||||
} catch (IOException e) {
|
||||
Log.e(this.getClass().getName(), "Error opening GET connection to " + urlString, e.getCause());
|
||||
return new APIResponse();
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public APIResponse get(final String urlString, final ContentValues values) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
for (Entry<String, Object> entry : values.valueSet()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append((String) entry.getKey());
|
||||
builder.append("=");
|
||||
builder.append(URLEncoder.encode((String) entry.getValue()));
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
return this.get(urlString + "?" + TextUtils.join("&", parameters));
|
||||
}
|
||||
|
||||
public APIResponse get(final String urlString, final ValueMultimap valueMap) {
|
||||
return this.get(urlString + "?" + valueMap.getParameterString());
|
||||
}
|
||||
|
||||
private APIResponse extractResponse(final URL url, HttpURLConnection connection) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
final Scanner scanner = new Scanner(connection.getInputStream());
|
||||
while (scanner.hasNextLine()) {
|
||||
builder.append(scanner.nextLine());
|
||||
}
|
||||
|
||||
final APIResponse response = new APIResponse();
|
||||
response.responseString = builder.toString();
|
||||
response.responseCode = connection.getResponseCode();
|
||||
response.cookie = connection.getHeaderField("Set-Cookie");
|
||||
response.hasRedirected = !TextUtils.equals(url.getHost(), connection.getURL().getHost());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public APIResponse post(final String urlString, final ContentValues values) {
|
||||
HttpURLConnection connection = null;
|
||||
if (!NetworkUtils.isOnline(context)) {
|
||||
APIResponse response = new APIResponse();
|
||||
response.isOffline = true;
|
||||
return response;
|
||||
}
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
for (Entry<String, Object> entry : values.valueSet()) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append((String) entry.getKey());
|
||||
builder.append("=");
|
||||
try {
|
||||
builder.append(URLEncoder.encode((String) entry.getValue(), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(this.getClass().getName(), e.getLocalizedMessage());
|
||||
return new APIResponse();
|
||||
}
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
final String parameterString = TextUtils.join("&", parameters);
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
Log.d(this.getClass().getName(), "API POST " + url );
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setFixedLengthStreamingMode(parameterString.getBytes().length);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||
final String cookie = preferences.getString(PrefConstants.PREF_COOKIE, null);
|
||||
if (cookie != null) {
|
||||
connection.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
|
||||
final PrintWriter printWriter = new PrintWriter(connection.getOutputStream());
|
||||
printWriter.print(parameterString);
|
||||
printWriter.close();
|
||||
|
||||
return extractResponse(url, connection);
|
||||
} catch (IOException e) {
|
||||
Log.e(this.getClass().getName(), "Error opening POST connection to " + urlString + ": " + e.getCause(), e.getCause());
|
||||
return new APIResponse();
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public APIResponse post(final String urlString, final ValueMultimap valueMap) {
|
||||
return post(urlString, valueMap, true);
|
||||
}
|
||||
|
||||
public APIResponse post(final String urlString, final ValueMultimap valueMap, boolean jsonIfy) {
|
||||
HttpURLConnection connection = null;
|
||||
if (!NetworkUtils.isOnline(context)) {
|
||||
APIResponse response = new APIResponse();
|
||||
response.isOffline = true;
|
||||
return response;
|
||||
}
|
||||
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
Log.d(this.getClass().getName(), "API POST " + url );
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
String parameterString = jsonIfy ? valueMap.getJsonString() : valueMap.getParameterString();
|
||||
connection.setFixedLengthStreamingMode(parameterString.getBytes().length);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||
final String cookie = preferences.getString(PrefConstants.PREF_COOKIE, null);
|
||||
if (cookie != null) {
|
||||
connection.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
|
||||
final PrintWriter printWriter = new PrintWriter(connection.getOutputStream());
|
||||
printWriter.print(parameterString);
|
||||
printWriter.close();
|
||||
|
||||
return extractResponse(url, connection);
|
||||
} catch (IOException e) {
|
||||
Log.e(this.getClass().getName(), "Error opening POST connection to " + urlString + ": " + e.getCause(), e.getCause());
|
||||
return new APIResponse();
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
package com.newsblur.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -8,11 +13,10 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
@ -41,12 +45,15 @@ import com.newsblur.network.domain.CategoriesResponse;
|
|||
import com.newsblur.network.domain.FeedFolderResponse;
|
||||
import com.newsblur.network.domain.FeedRefreshResponse;
|
||||
import com.newsblur.network.domain.LoginResponse;
|
||||
import com.newsblur.network.domain.Message;
|
||||
import com.newsblur.network.domain.NewsBlurResponse;
|
||||
import com.newsblur.network.domain.ProfileResponse;
|
||||
import com.newsblur.network.domain.RegisterResponse;
|
||||
import com.newsblur.network.domain.SocialFeedResponse;
|
||||
import com.newsblur.network.domain.StoriesResponse;
|
||||
import com.newsblur.serialization.BooleanTypeAdapter;
|
||||
import com.newsblur.serialization.DateStringTypeAdapter;
|
||||
import com.newsblur.util.NetworkUtils;
|
||||
import com.newsblur.util.PrefConstants;
|
||||
import com.newsblur.util.PrefsUtils;
|
||||
import com.newsblur.util.ReadFilter;
|
||||
import com.newsblur.util.StoryOrder;
|
||||
|
@ -68,46 +75,43 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public LoginResponse login(final String username, final String password) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USERNAME, username);
|
||||
values.put(APIConstants.PARAMETER_PASSWORD, password);
|
||||
final APIResponse response = client.post(APIConstants.URL_LOGIN, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
LoginResponse loginResponse = gson.fromJson(response.responseString, LoginResponse.class);
|
||||
PrefsUtils.saveLogin(context, username, response.cookie);
|
||||
return loginResponse;
|
||||
} else {
|
||||
return new LoginResponse();
|
||||
}
|
||||
}
|
||||
final APIResponse response = post(APIConstants.URL_LOGIN, values);
|
||||
LoginResponse loginResponse = ((LoginResponse) response.getResponse(gson, LoginResponse.class));
|
||||
if (!response.isError()) {
|
||||
PrefsUtils.saveLogin(context, username, response.getCookie());
|
||||
}
|
||||
return loginResponse;
|
||||
}
|
||||
|
||||
public boolean setAutoFollow(boolean autofollow) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("autofollow_friends", autofollow ? "true" : "false");
|
||||
final APIResponse response = client.post(APIConstants.URL_AUTOFOLLOW_PREF, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_AUTOFOLLOW_PREF, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public boolean addCategories(ArrayList<String> categories) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
for (String category : categories) {
|
||||
values.put(APIConstants.PARAMETER_CATEGORY, URLEncoder.encode(category));
|
||||
}
|
||||
final APIResponse response = client.post(APIConstants.URL_ADD_CATEGORIES, values, false);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_ADD_CATEGORIES, values, false);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public boolean markFeedAsRead(final String[] feedIds) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
for (String feedId : feedIds) {
|
||||
values.put(APIConstants.PARAMETER_FEEDID, feedId);
|
||||
}
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_FEED_AS_READ, values, false);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_MARK_FEED_AS_READ, values, false);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -115,11 +119,11 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean markAllAsRead() {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
values.put(APIConstants.PARAMETER_DAYS, "0");
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_ALL_AS_READ, values, false);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_MARK_ALL_AS_READ, values, false);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -127,81 +131,72 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean markSocialStoryAsRead(final String updateJson) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_MARKSOCIAL_JSON, updateJson);
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_SOCIALSTORY_AS_READ, values);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_MARK_SOCIALSTORY_AS_READ, values);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean markStoryAsStarred(final String feedId, final String storyId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
public NewsBlurResponse markStoryAsStarred(final String feedId, final String storyId) {
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
values.put(APIConstants.PARAMETER_FEEDID, feedId);
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_STORY_AS_STARRED, values, false);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
final APIResponse response = post(APIConstants.URL_MARK_STORY_AS_STARRED, values, false);
|
||||
return response.getResponse(gson, NewsBlurResponse.class);
|
||||
}
|
||||
|
||||
public boolean markStoryAsUnread( String feedId, String storyId ) {
|
||||
final APIClient client = new APIClient(context);
|
||||
public NewsBlurResponse markStoryAsUnread( String feedId, String storyId ) {
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
values.put(APIConstants.PARAMETER_FEEDID, feedId);
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_STORY_AS_UNREAD, values, false);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
final APIResponse response = post(APIConstants.URL_MARK_STORY_AS_UNREAD, values, false);
|
||||
return response.getResponse(gson, NewsBlurResponse.class);
|
||||
}
|
||||
|
||||
public CategoriesResponse getCategories() {
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.get(APIConstants.URL_CATEGORIES);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
return gson.fromJson(response.responseString, CategoriesResponse.class);
|
||||
final APIResponse response = get(APIConstants.URL_CATEGORIES);
|
||||
if (!response.isError()) {
|
||||
CategoriesResponse categoriesResponse = gson.fromJson(response.getGsonReader(), CategoriesResponse.class);
|
||||
response.close();
|
||||
return categoriesResponse;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public LoginResponse signup(final String username, final String password, final String email) {
|
||||
final APIClient client = new APIClient(context);
|
||||
public RegisterResponse signup(final String username, final String password, final String email) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USERNAME, username);
|
||||
values.put(APIConstants.PARAMETER_PASSWORD, password);
|
||||
values.put(APIConstants.PARAMETER_EMAIL, email);
|
||||
final APIResponse response = client.post(APIConstants.URL_SIGNUP, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
LoginResponse loginResponse = gson.fromJson(response.responseString, LoginResponse.class);
|
||||
PrefsUtils.saveLogin(context, username, response.cookie);
|
||||
final APIResponse response = post(APIConstants.URL_SIGNUP, values);
|
||||
if (!response.isError()) {
|
||||
RegisterResponse registerResponse = gson.fromJson(response.getGsonReader(), LoginResponse.class);
|
||||
response.close();
|
||||
PrefsUtils.saveLogin(context, username, response.getCookie());
|
||||
|
||||
CookieSyncManager.createInstance(context.getApplicationContext());
|
||||
CookieManager cookieManager = CookieManager.getInstance();
|
||||
|
||||
cookieManager.setCookie(".newsblur.com", response.cookie);
|
||||
cookieManager.setCookie(".newsblur.com", response.getCookie());
|
||||
CookieSyncManager.getInstance().sync();
|
||||
|
||||
return loginResponse;
|
||||
return registerResponse;
|
||||
} else {
|
||||
return new LoginResponse();
|
||||
return new RegisterResponse();
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileResponse updateUserProfile() {
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.get(APIConstants.URL_MY_PROFILE);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
ProfileResponse profileResponse = gson.fromJson(response.responseString, ProfileResponse.class);
|
||||
final APIResponse response = get(APIConstants.URL_MY_PROFILE);
|
||||
if (!response.isError()) {
|
||||
ProfileResponse profileResponse = gson.fromJson(response.getGsonReader(), ProfileResponse.class);
|
||||
response.close();
|
||||
PrefsUtils.saveUserDetails(context, profileResponse.user);
|
||||
return profileResponse;
|
||||
} else {
|
||||
|
@ -210,7 +205,6 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public StoriesResponse getStoriesForFeed(String feedId, String pageNumber, StoryOrder order, ReadFilter filter) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
Uri feedUri = Uri.parse(APIConstants.URL_FEED_STORIES).buildUpon().appendPath(feedId).build();
|
||||
values.put(APIConstants.PARAMETER_FEEDS, feedId);
|
||||
|
@ -218,14 +212,15 @@ public class APIManager {
|
|||
values.put(APIConstants.PARAMETER_ORDER, order.getParameterValue());
|
||||
values.put(APIConstants.PARAMETER_READ_FILTER, filter.getParameterValue());
|
||||
|
||||
final APIResponse response = client.get(feedUri.toString(), values);
|
||||
final APIResponse response = get(feedUri.toString(), values);
|
||||
Uri storyUri = FeedProvider.FEED_STORIES_URI.buildUpon().appendPath(feedId).build();
|
||||
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
if (!response.isError()) {
|
||||
if (TextUtils.equals(pageNumber, "1")) {
|
||||
contentResolver.delete(storyUri, null, null);
|
||||
}
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.responseString, StoriesResponse.class);
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.getGsonReader(), StoriesResponse.class);
|
||||
response.close();
|
||||
|
||||
Uri classifierUri = FeedProvider.CLASSIFIER_URI.buildUpon().appendPath(feedId).build();
|
||||
|
||||
|
@ -251,7 +246,6 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public StoriesResponse getStoriesForFeeds(String[] feedIds, String pageNumber, StoryOrder order, ReadFilter filter) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
for (String feedId : feedIds) {
|
||||
values.put(APIConstants.PARAMETER_FEEDS, feedId);
|
||||
|
@ -261,10 +255,11 @@ public class APIManager {
|
|||
}
|
||||
values.put(APIConstants.PARAMETER_ORDER, order.getParameterValue());
|
||||
values.put(APIConstants.PARAMETER_READ_FILTER, filter.getParameterValue());
|
||||
final APIResponse response = client.get(APIConstants.URL_RIVER_STORIES, values);
|
||||
final APIResponse response = get(APIConstants.URL_RIVER_STORIES, values);
|
||||
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.responseString, StoriesResponse.class);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.getGsonReader(), StoriesResponse.class);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
if (TextUtils.equals(pageNumber,"1")) {
|
||||
Uri storyUri = FeedProvider.ALL_STORIES_URI;
|
||||
contentResolver.delete(storyUri, null, null);
|
||||
|
@ -287,15 +282,15 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public StoriesResponse getStarredStories(String pageNumber) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
if (!TextUtils.isEmpty(pageNumber)) {
|
||||
values.put(APIConstants.PARAMETER_PAGE_NUMBER, "" + pageNumber);
|
||||
}
|
||||
final APIResponse response = client.get(APIConstants.URL_STARRED_STORIES, values);
|
||||
final APIResponse response = get(APIConstants.URL_STARRED_STORIES, values);
|
||||
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.responseString, StoriesResponse.class);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.getGsonReader(), StoriesResponse.class);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
if (TextUtils.equals(pageNumber,"1")) {
|
||||
contentResolver.delete(FeedProvider.STARRED_STORIES_URI, null, null);
|
||||
}
|
||||
|
@ -313,7 +308,6 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public SocialFeedResponse getSharedStoriesForFeeds(String[] feedIds, String pageNumber) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
for (String feedId : feedIds) {
|
||||
values.put(APIConstants.PARAMETER_FEEDS, feedId);
|
||||
|
@ -322,10 +316,11 @@ public class APIManager {
|
|||
values.put(APIConstants.PARAMETER_PAGE_NUMBER, "" + pageNumber);
|
||||
}
|
||||
|
||||
final APIResponse response = client.get(APIConstants.URL_SHARED_RIVER_STORIES, values);
|
||||
final APIResponse response = get(APIConstants.URL_SHARED_RIVER_STORIES, values);
|
||||
|
||||
SocialFeedResponse storiesResponse = gson.fromJson(response.responseString, SocialFeedResponse.class);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
SocialFeedResponse storiesResponse = gson.fromJson(response.getGsonReader(), SocialFeedResponse.class);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
|
||||
// If we've successfully retrieved the latest stories for all shared feeds (the first page), delete all previous shared feeds
|
||||
if (TextUtils.equals(pageNumber,"1")) {
|
||||
|
@ -362,7 +357,6 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public SocialFeedResponse getStoriesForSocialFeed(String userId, String username, String pageNumber) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USER_ID, userId);
|
||||
values.put(APIConstants.PARAMETER_USERNAME, username);
|
||||
|
@ -370,9 +364,10 @@ public class APIManager {
|
|||
values.put(APIConstants.PARAMETER_PAGE_NUMBER, "" + pageNumber);
|
||||
}
|
||||
Uri feedUri = Uri.parse(APIConstants.URL_SOCIALFEED_STORIES).buildUpon().appendPath(userId).appendPath(username).build();
|
||||
final APIResponse response = client.get(feedUri.toString(), values);
|
||||
SocialFeedResponse socialFeedResponse = gson.fromJson(response.responseString, SocialFeedResponse.class);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = get(feedUri.toString(), values);
|
||||
SocialFeedResponse socialFeedResponse = gson.fromJson(response.getGsonReader(), SocialFeedResponse.class);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
|
||||
Uri storySocialUri = FeedProvider.SOCIALFEED_STORIES_URI.buildUpon().appendPath(userId).build();
|
||||
if (TextUtils.equals(pageNumber, "1")) {
|
||||
|
@ -436,11 +431,11 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean followUser(final String userId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USERID, userId);
|
||||
final APIResponse response = client.post(APIConstants.URL_FOLLOW, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_FOLLOW, values);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -448,11 +443,11 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean unfollowUser(final String userId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USERID, userId);
|
||||
final APIResponse response = client.post(APIConstants.URL_UNFOLLOW, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_UNFOLLOW, values);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -460,7 +455,6 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public Boolean shareStory(final String storyId, final String feedId, final String comment, final String sourceUserId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
if (!TextUtils.isEmpty(comment)) {
|
||||
values.put(APIConstants.PARAMETER_SHARE_COMMENT, comment);
|
||||
|
@ -471,8 +465,9 @@ public class APIManager {
|
|||
values.put(APIConstants.PARAMETER_FEEDID, feedId);
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
|
||||
final APIResponse response = client.post(APIConstants.URL_SHARE_STORY, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_SHARE_STORY, values);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -489,17 +484,18 @@ public class APIManager {
|
|||
*/
|
||||
public boolean getFolderFeedMapping(boolean doUpdateCounts) {
|
||||
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues params = new ContentValues();
|
||||
params.put( APIConstants.PARAMETER_UPDATE_COUNTS, (doUpdateCounts ? "true" : "false") );
|
||||
final APIResponse response = client.get(APIConstants.URL_FEEDS, params);
|
||||
final APIResponse response = get(APIConstants.URL_FEEDS, params);
|
||||
|
||||
final FeedFolderResponse feedUpdate = new FeedFolderResponse(response.responseString, gson);
|
||||
// note: this response is complex enough, we have to do a custom parse in the FFR
|
||||
final FeedFolderResponse feedUpdate = new FeedFolderResponse(response.getGsonReader(), gson);
|
||||
response.close();
|
||||
|
||||
// there is a rare issue with feeds that have no folder. capture them for debug.
|
||||
List<String> debugFeedIds = new ArrayList<String>();
|
||||
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
if (!response.isError()) {
|
||||
|
||||
// if the response says we aren't logged in, clear the DB and prompt for login. We test this
|
||||
// here, since this the first sync call we make on launch if we believe we are cookied.
|
||||
|
@ -567,18 +563,6 @@ public class APIManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
private HashMap<String, Feed> getExistingFeeds() {
|
||||
Cursor feedCursor = contentResolver.query(FeedProvider.FEEDS_URI, null, null, null, null);
|
||||
feedCursor.moveToFirst();
|
||||
HashMap<String, Feed> existingFeeds = new HashMap<String, Feed>();
|
||||
while (!feedCursor.isAfterLast()) {
|
||||
existingFeeds.put(Feed.fromCursor(feedCursor).feedId, Feed.fromCursor(feedCursor));
|
||||
feedCursor.moveToNext();
|
||||
}
|
||||
feedCursor.close();
|
||||
return existingFeeds;
|
||||
}
|
||||
|
||||
public boolean trainClassifier(String feedId, String key, int type, int action) {
|
||||
String typeText = null;
|
||||
String actionText = null;
|
||||
|
@ -625,18 +609,18 @@ public class APIManager {
|
|||
}
|
||||
values.put(APIConstants.PARAMETER_FEEDID, feedId);
|
||||
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.post(APIConstants.URL_CLASSIFIER_SAVE, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_CLASSIFIER_SAVE, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public ProfileResponse getUser(String userId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_USER_ID, userId);
|
||||
final APIResponse response = client.get(APIConstants.URL_USER_PROFILE, values);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
ProfileResponse profileResponse = gson.fromJson(response.responseString, ProfileResponse.class);
|
||||
final APIResponse response = get(APIConstants.URL_USER_PROFILE, values);
|
||||
if (!response.isError()) {
|
||||
ProfileResponse profileResponse = gson.fromJson(response.getGsonReader(), ProfileResponse.class);
|
||||
response.close();
|
||||
return profileResponse;
|
||||
} else {
|
||||
return null;
|
||||
|
@ -644,10 +628,10 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public void refreshFeedCounts() {
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.get(APIConstants.URL_FEED_COUNTS);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final FeedRefreshResponse feedCountUpdate = gson.fromJson(response.responseString, FeedRefreshResponse.class);
|
||||
final APIResponse response = get(APIConstants.URL_FEED_COUNTS);
|
||||
if (!response.isError()) {
|
||||
final FeedRefreshResponse feedCountUpdate = gson.fromJson(response.getGsonReader(), FeedRefreshResponse.class);
|
||||
response.close();
|
||||
for (String feedId : feedCountUpdate.feedCounts.keySet()) {
|
||||
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
|
||||
if (feedCountUpdate.feedCounts.get(feedId) != null) {
|
||||
|
@ -666,40 +650,40 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean favouriteComment(String storyId, String commentId, String feedId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
values.put(APIConstants.PARAMETER_STORY_FEEDID, feedId);
|
||||
values.put(APIConstants.PARAMETER_COMMENT_USERID, commentId);
|
||||
final APIResponse response = client.post(APIConstants.URL_LIKE_COMMENT, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_LIKE_COMMENT, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public Boolean unFavouriteComment(String storyId, String commentId, String feedId) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
values.put(APIConstants.PARAMETER_STORY_FEEDID, feedId);
|
||||
values.put(APIConstants.PARAMETER_COMMENT_USERID, commentId);
|
||||
final APIResponse response = client.post(APIConstants.URL_UNLIKE_COMMENT, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_UNLIKE_COMMENT, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public boolean replyToComment(String storyId, String storyFeedId, String commentUserId, String reply) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_STORYID, storyId);
|
||||
values.put(APIConstants.PARAMETER_STORY_FEEDID, storyFeedId);
|
||||
values.put(APIConstants.PARAMETER_COMMENT_USERID, commentUserId);
|
||||
values.put(APIConstants.PARAMETER_REPLY_TEXT, reply);
|
||||
final APIResponse response = client.post(APIConstants.URL_REPLY_TO, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_REPLY_TO, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public boolean markMultipleStoriesAsRead(ContentValues values) {
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.post(APIConstants.URL_MARK_FEED_STORIES_AS_READ, values);
|
||||
if (!response.isOffline && response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final APIResponse response = post(APIConstants.URL_MARK_FEED_STORIES_AS_READ, values);
|
||||
response.close();
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -707,65 +691,142 @@ public class APIManager {
|
|||
}
|
||||
|
||||
public boolean addFeed(String feedUrl, String folderName) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_URL, feedUrl);
|
||||
if (!TextUtils.isEmpty(folderName)) {
|
||||
values.put(APIConstants.PARAMETER_FOLDER, folderName);
|
||||
}
|
||||
final APIResponse response = client.post(APIConstants.URL_ADD_FEED, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_ADD_FEED, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
public FeedResult[] searchForFeed(String searchTerm) throws ServerErrorException {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_FEED_SEARCH_TERM, searchTerm);
|
||||
final APIResponse response = client.get(APIConstants.URL_FEED_AUTOCOMPLETE, values);
|
||||
final APIResponse response = get(APIConstants.URL_FEED_AUTOCOMPLETE, values);
|
||||
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
return fromJson(response.responseString, FeedResult[].class);
|
||||
if (!response.isError()) {
|
||||
FeedResult[] feedResult = gson.fromJson(response.getGsonReader(), FeedResult[].class);
|
||||
response.close();
|
||||
return feedResult;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean deleteFeed(long feedId, String folderName) {
|
||||
final APIClient client = new APIClient(context);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_FEEDID, Long.toString(feedId));
|
||||
if (!TextUtils.isEmpty(folderName)) {
|
||||
values.put(APIConstants.PARAMETER_IN_FOLDER, folderName);
|
||||
}
|
||||
final APIResponse response = client.post(APIConstants.URL_DELETE_FEED, values);
|
||||
return (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected);
|
||||
final APIResponse response = post(APIConstants.URL_DELETE_FEED, values);
|
||||
response.close();
|
||||
return (!response.isError());
|
||||
}
|
||||
|
||||
private <T> T fromJson(String json, Class<T> classOfT) throws ServerErrorException {
|
||||
if(isServerMessage(json)) {
|
||||
Message errorMessage = gson.fromJson(json, Message.class);
|
||||
throw new ServerErrorException(errorMessage.message);
|
||||
/* HTTP METHODS */
|
||||
|
||||
private APIResponse get(final String urlString) {
|
||||
HttpURLConnection connection = null;
|
||||
if (!NetworkUtils.isOnline(context)) {
|
||||
return new APIResponse(context);
|
||||
}
|
||||
return gson.fromJson(json, classOfT);
|
||||
}
|
||||
|
||||
private boolean isServerMessage(String json) {
|
||||
// TODO find a better way to identify these failed responses
|
||||
boolean isServerMessage = false;
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonElement jsonElement = parser.parse(json);
|
||||
if(jsonElement.isJsonObject()) {
|
||||
JsonObject asJsonObject = jsonElement.getAsJsonObject();
|
||||
if(asJsonObject.has("code")) {
|
||||
JsonElement codeItem = asJsonObject.get("code");
|
||||
int code = codeItem.getAsInt();
|
||||
if(code == -1)
|
||||
isServerMessage = true;
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
Log.d(this.getClass().getName(), "API GET " + url );
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||
final String cookie = preferences.getString(PrefConstants.PREF_COOKIE, null);
|
||||
if (cookie != null) {
|
||||
connection.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
}
|
||||
return isServerMessage;
|
||||
return new APIResponse(context, url, connection);
|
||||
} catch (IOException e) {
|
||||
Log.e(this.getClass().getName(), "Error opening GET connection to " + urlString, e.getCause());
|
||||
return new APIResponse(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private APIResponse get(final String urlString, final ContentValues values) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
for (Entry<String, Object> entry : values.valueSet()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append((String) entry.getKey());
|
||||
builder.append("=");
|
||||
builder.append(URLEncoder.encode((String) entry.getValue()));
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
return this.get(urlString + "?" + TextUtils.join("&", parameters));
|
||||
}
|
||||
|
||||
private APIResponse get(final String urlString, final ValueMultimap valueMap) {
|
||||
return this.get(urlString + "?" + valueMap.getParameterString());
|
||||
}
|
||||
|
||||
private APIResponse post(String urlString, String postBodyString) {
|
||||
HttpURLConnection connection = null;
|
||||
if (!NetworkUtils.isOnline(context)) {
|
||||
return new APIResponse(context);
|
||||
}
|
||||
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
Log.d(this.getClass().getName(), "API POST " + url );
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setFixedLengthStreamingMode(postBodyString.getBytes().length);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
final SharedPreferences preferences = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||
final String cookie = preferences.getString(PrefConstants.PREF_COOKIE, null);
|
||||
if (cookie != null) {
|
||||
connection.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
|
||||
final PrintWriter printWriter = new PrintWriter(connection.getOutputStream());
|
||||
printWriter.print(postBodyString);
|
||||
printWriter.close();
|
||||
|
||||
return new APIResponse(context, url, connection);
|
||||
} catch (IOException e) {
|
||||
Log.e(this.getClass().getName(), "Error opening POST connection to " + urlString + ": " + e.getCause(), e.getCause());
|
||||
return new APIResponse(context);
|
||||
}
|
||||
}
|
||||
|
||||
private APIResponse post(final String urlString, final ContentValues values) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
for (Entry<String, Object> entry : values.valueSet()) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append((String) entry.getKey());
|
||||
builder.append("=");
|
||||
try {
|
||||
builder.append(URLEncoder.encode((String) entry.getValue(), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(this.getClass().getName(), e.getLocalizedMessage());
|
||||
return new APIResponse(context);
|
||||
}
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
final String parameterString = TextUtils.join("&", parameters);
|
||||
|
||||
return this.post(urlString, parameterString);
|
||||
}
|
||||
|
||||
private APIResponse post(final String urlString, final ValueMultimap valueMap) {
|
||||
return post(urlString, valueMap, true);
|
||||
}
|
||||
|
||||
private APIResponse post(final String urlString, final ValueMultimap valueMap, boolean jsonIfy) {
|
||||
String parameterString = jsonIfy ? valueMap.getJsonString() : valueMap.getParameterString();
|
||||
return this.post(urlString, parameterString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to call contentResolver.bulkInsert using a list rather than an array.
|
||||
*/
|
||||
|
|
|
@ -1,11 +1,137 @@
|
|||
package com.newsblur.network;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.network.domain.NewsBlurResponse;
|
||||
|
||||
/**
|
||||
* A JSON-encoded response from the API servers. This class encodes the possible outcomes of
|
||||
* an attempted API call, including total failure, online failures, and successful responses.
|
||||
* In the latter case, the GSON reader used to look for errors is left open so that the expected
|
||||
* response can be read. Instances of this class should be closed after use.
|
||||
*/
|
||||
public class APIResponse {
|
||||
|
||||
public String responseString = "";
|
||||
public int responseCode = -1;
|
||||
public boolean hasRedirected;
|
||||
public boolean isOffline;
|
||||
public String cookie;
|
||||
private Context context;
|
||||
private HttpURLConnection connection;
|
||||
private boolean isError;
|
||||
private String errorMessage;
|
||||
private String cookie;
|
||||
private JsonReader gsonReader;
|
||||
|
||||
/**
|
||||
* Construct an online response. Will test the response for errors and extract all the
|
||||
* info we might need.
|
||||
*/
|
||||
public APIResponse(Context context, URL originalUrl, HttpURLConnection connection) {
|
||||
|
||||
this.context = context;
|
||||
this.connection = connection;
|
||||
|
||||
this.errorMessage = context.getResources().getString(R.string.error_unset_message);
|
||||
|
||||
try {
|
||||
if (connection.getResponseCode() != HttpStatus.SC_OK) {
|
||||
Log.e(this.getClass().getName(), "API returned error code " + connection.getResponseCode() + " calling " + originalUrl);
|
||||
this.isError = true;
|
||||
this.errorMessage = context.getResources().getString(R.string.error_http_connection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(originalUrl.getHost(), connection.getURL().getHost())) {
|
||||
// TODO: the existing code rejects redirects as errors. Is this correct?
|
||||
Log.e(this.getClass().getName(), "API redirected calling " + originalUrl);
|
||||
this.isError = true;
|
||||
this.errorMessage = context.getResources().getString(R.string.error_http_connection);
|
||||
return;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(this.getClass().getName(), "Error (" + ioe.getMessage() + ") calling " + originalUrl, ioe);
|
||||
this.isError = true;
|
||||
this.errorMessage = context.getResources().getString(R.string.error_read_connection);
|
||||
return;
|
||||
}
|
||||
|
||||
this.cookie = connection.getHeaderField("Set-Cookie");
|
||||
|
||||
// make a GSON streaming reader for the response
|
||||
try {
|
||||
this.gsonReader = new JsonReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
Log.e(this.getClass().getName(), e.getClass().getName() + " (" + e.getMessage() + ") calling " + originalUrl, e);
|
||||
this.isError = true;
|
||||
this.errorMessage = context.getResources().getString(R.string.error_read_connection);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and empty/offline response. Signals that the call was not made.
|
||||
*/
|
||||
public APIResponse(Context context) {
|
||||
this.context = context;
|
||||
this.isError = true;
|
||||
this.errorMessage = context.getResources().getString(R.string.error_offline);
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return this.isError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GSON reader that will have been left open for use if the API call was successful.
|
||||
*/
|
||||
public JsonReader getGsonReader() {
|
||||
return this.gsonReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response object from this call. A specific subclass of NewsBlurResponse
|
||||
* may be used for calls that return data, or the parent class may be used if no
|
||||
* return data are expected.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends NewsBlurResponse> T getResponse(Gson gson, Class<T> classOfT) {
|
||||
if (this.isError) {
|
||||
// if we encountered an error, make a generic response type and populate
|
||||
// it's message field
|
||||
NewsBlurResponse response = new NewsBlurResponse();
|
||||
response.message = this.errorMessage;
|
||||
this.close();
|
||||
return ((T) response);
|
||||
} else {
|
||||
// otherwise, parse the response as the expected class and defer error detection
|
||||
// to the NewsBlurResponse parent class
|
||||
T response = gson.fromJson(this.gsonReader, classOfT);
|
||||
this.close();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public String getCookie() {
|
||||
return this.cookie;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (this.connection != null) this.connection.disconnect();
|
||||
if (this.gsonReader != null) this.gsonReader.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(this.getClass().getName(), "Error closing API connection.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.newsblur.domain.Feed;
|
||||
import com.newsblur.domain.SocialFeed;
|
||||
import com.newsblur.util.AppConstants;
|
||||
|
@ -35,7 +36,7 @@ public class FeedFolderResponse {
|
|||
|
||||
public boolean isAuthenticated;
|
||||
|
||||
public FeedFolderResponse(String json, Gson gson) {
|
||||
public FeedFolderResponse(JsonReader json, Gson gson) {
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject asJsonObject = parser.parse(json).getAsJsonObject();
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
package com.newsblur.network.domain;
|
||||
|
||||
public class LoginResponse {
|
||||
public class LoginResponse extends NewsBlurResponse {
|
||||
|
||||
// {"code": -1, "authenticated": false, "errors": {"__all__": ["That username is not registered. Create an account with it instead."]}, "result": "ok"}
|
||||
// {"code": -1, "authenticated": false, "errors": {"username": ["Please enter a username."]}, "result": "ok"}
|
||||
|
||||
public boolean authenticated;
|
||||
public int code;
|
||||
public LoginErrors errors;
|
||||
public String result;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.newsblur.network.domain;
|
||||
|
||||
/**
|
||||
* A generic response to an API call that only encapsuates success versus failure.
|
||||
*/
|
||||
public class NewsBlurResponse {
|
||||
|
||||
public boolean authenticated;
|
||||
public int code;
|
||||
public String message;
|
||||
public String[] errors;
|
||||
|
||||
public boolean isError() {
|
||||
if (message != null) return true;
|
||||
if ((errors != null) && (errors.length > 0) && (errors[0] != null)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
if (message != null) return message;
|
||||
if ((errors != null) && (errors.length > 0) && (errors[0] != null)) return errors[0];
|
||||
return Integer.toString(code);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.newsblur.network.domain;
|
||||
|
||||
public class RegisterResponse {
|
||||
|
||||
public boolean authenticated;
|
||||
public int code;
|
||||
public LoginErrors errors;
|
||||
public String result;
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@ import com.newsblur.R;
|
|||
import com.newsblur.database.DatabaseConstants;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.domain.ValueMultimap;
|
||||
import com.newsblur.network.APIClient;
|
||||
import com.newsblur.network.APIConstants;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.network.domain.SocialFeedResponse;
|
||||
|
@ -69,7 +68,6 @@ public class SyncService extends IntentService {
|
|||
public static final int EXTRA_TASK_MULTISOCIALFEED_UPDATE = 40;
|
||||
public static final int EXTRA_TASK_STARRED_STORIES_UPDATE = 42;
|
||||
|
||||
public APIClient apiClient;
|
||||
private APIManager apiManager;
|
||||
private ContentResolver contentResolver;
|
||||
public static final String SYNCSERVICE_TASK = "syncservice_task";
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.newsblur.database.FeedProvider;
|
|||
import com.newsblur.domain.Story;
|
||||
import com.newsblur.domain.ValueMultimap;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.network.domain.NewsBlurResponse;
|
||||
import com.newsblur.service.SyncService;
|
||||
|
||||
public class FeedUtils {
|
||||
|
@ -35,17 +36,17 @@ public class FeedUtils {
|
|||
if (story != null) {
|
||||
final String feedId = story.feedId;
|
||||
final String storyId = story.id;
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
new AsyncTask<Void, Void, NewsBlurResponse>() {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... arg) {
|
||||
protected NewsBlurResponse doInBackground(Void... arg) {
|
||||
return apiManager.markStoryAsStarred(feedId, storyId);
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result) {
|
||||
protected void onPostExecute(NewsBlurResponse result) {
|
||||
if (!result.isError()) {
|
||||
Toast.makeText(context, R.string.toast_story_saved, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(context, R.string.toast_story_save_error, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(context, result.getErrorMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
@ -56,17 +57,17 @@ public class FeedUtils {
|
|||
|
||||
public static void markStoryUnread( final Story story, final Context context, final APIManager apiManager) {
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
new AsyncTask<Void, Void, NewsBlurResponse>() {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... arg) {
|
||||
protected NewsBlurResponse doInBackground(Void... arg) {
|
||||
return apiManager.markStoryAsUnread(story.feedId, story.id);
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result) {
|
||||
protected void onPostExecute(NewsBlurResponse result) {
|
||||
if (!result.isError()) {
|
||||
Toast.makeText(context, R.string.toast_story_unread, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(context, R.string.toast_story_unread_error, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(context, result.getErrorMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
|
Loading…
Add table
Reference in a new issue