Getting response out of AsyncHttpClient - java

Im using this lib: http://loopj.com/android-async-http/ to make all my requests && The biggest thing currently making my code messy is that I havent been able to successfully get my Async Http Request Responses out of onSuccess() so that the data is available to the rest of the class freely. Up till this point I have been parsing all my request responses inside the curlys of my responsehandlers onSuccess(){}
I came across this post on Stack:How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
but have yet to get it to work with this lib.
import com.loopj.android.http.*;
public class TwitterRestClient {
private static final String BASE_URL = "http://api.twitter.com/1/";
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}
public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
}
import org.json.*;
import com.loopj.android.http.*;
class TwitterRestClientUsage {
public void getPublicTimeline() throws JSONException {
TwitterRestClient.get("statuses/public_timeline.json", null, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray timeline) {
// Pull out the first event on the public timeline
JSONObject firstEvent = timeline.get(0);
String tweetText = firstEvent.getString("text");
// Do something with the response
System.out.println(tweetText);
}
});
}
}

I do not know if this helps, but I have had to face the same problem (I am quite the novice at java and android). Used an interface. http://www.gdgankara.org/2013/03/25/android-asynchronous-http-client-a-callback-based-http-client-library-for-android-and-android-smart-image-view/

Try this:
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
String response = new String(responseHandler);
Log.i("RESPONSE", response);
}

Related

php : reading json arraylist and saving data in mysql?

I want to read arraylist from android into php in order to store in database, but I'm not able to find exact code for it. Can anybody guide me in the direction to solve this problem ?
Here is my java code for creating the arraylist
private void loadCart()
{
productList.clear();
Cursor cursor = dbHelper.getCarProducts();
cursor.moveToFirst();
do {
CartProduct cartProduct = new CartProduct();
cartProduct.setProductName("Name: "+cursor.getString(cursor.getColumnIndex("_Name")));
cartProduct.setProductCost("Cost: "+cursor.getString(cursor.getColumnIndex("_Cost")));
cartProduct.setProductPrice("Price: "+cursor.getString(cursor.getColumnIndex("_Price")));
cartProduct.setProductQuantity("Quantity: "+cursor.getString(cursor.getColumnIndex("_Quantity")));
productList.add(cartProduct);
}while(cursor.moveToNext());
}
I'm using retrofit2 in order to send the arraylist to the server, but as I have seen in other question here I'm not able to get the url for the file_get_contents ?
Here you go...
Step 1: Add retrofit dependency in your gradle.app
compile 'com.squareup.retrofit:retrofit:1.9.0'
Step 2: Make an RestClient class like below.
public class RestClient {
private static final String BASE_URL = DataConstants.TEST_URL; //Place your web service URL here
private ApiInterface apiService;
public RestClient()
{
RequestInterceptor requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(requestInterceptor)
.setEndpoint(BASE_URL)
.build();
apiService = restAdapter.create(ApiInterface.class);
}
public ApiInterface getApiService()
{
return apiService;
}
}
Step 3: Make an Interface for POST URL.
public interface ApiInterface {
#POST("/sendData")
void sendData(#Body JsonObject jsonObject,
Callback<DataModel> dataModelCallback);
}
Step 4: Make an POJO class like below.
public class DataModel{
private String success;
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
}
Step 5: Make an call of webservice from your activity like below.
private void callWebService(String user_id) {
try {//TODO SEND
final Utility utility = new Utility(this);
utility.showProgressDialog();
JsonObject myJsonData = new JsonObject();
myJsonData.addProperty("user_id", user_id);
Gson gsonData = new GsonBuilder().create();
JsonArray dataArray = new JsonArray();
dataArray = gsonData.toJsonTree(productList).getAsJsonArray(); //Here you want to add your array list i.e productList
myJsonData.add("assign_to", jaAssignee);
new RestClient().getApiService().sendData(myJsonData, new Callback<DataModel>() {
#Override
public void success(DataModel dataModel, Response response) {
utility.hideProgressDialog();
try {
String success = dataModel.getSuccess();
if (success.equalsIgnoreCase("Success")) {
//Do what you want to do
}
} catch (Exception e) {
}
}
#Override
public void failure(RetrofitError error) {
utility.hideProgressDialog();
}
});
} catch (Exception e) {
}
}
Hope this will help you!
Send all your data in one go. Create JsonArray and add each object by creating JsonObject. After its done upload all the data in one go. You'll just have to decode that array in php.
Advantage of using this is, you can manage the response in retrofit very well (being it asynchronous)
you can parse json value in php by
<?php
header('Content-type: application/json');
$jsonString = file_get_contents('php://input');
$jsonArray = json_decode($jsonString,true);
print_r($jsonArray);/* print array */
?>
After almost searching for 3+ weeks and n+ hours of frustration, i've finally found an working solution to my problem and sharing it with people so they could benefit from it (as i was blocked from another a/c due to asking too many questions and down votes ) , in order to send your array list to your server we need to use another library and the best fit according to my need is async-http library by loop j and these are the steps to import and use the library in your program :-
1.)import the library into your project by writing this statement in your bulid.gradle(app module):-
compile 'com.loopj.android:android-async-http:1.4.9'
2.)Create the following variables in order to use them in your program:-
AsyncHttpClient (a client to send data to your server)
RequestPrarms (Data sent to your server for parsing and further operations )
String url(Link to your server where actually operations occurs)
3.) Now we use these variables and run the program :-
p
arams.put("OrderSummary", <your array list>);
httpClient.post(APIURL.API_URL,params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
//your operations on success
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Toast.makeText(getApplicationContext(),error.toString(),Toast.LENGTH_LONG).show();
}
});
i hope this clears your doubts somewhat i'm still creating my php side in order to insert data in the database

How can I Customize Volley Library to make post request as java object to get response as java Object

I am using framework in which I simply pass a java object. Framework methods and classes converts this object to json string and makes a post request. Also I am getting response as java object.
This same thing I wish to implement using volley library
I just want to pass Java request object and in response also want java object
Please suggest me a way how could I do that.
Thanks...
I have something that might help you starting.
Just create your BaseRequest where you pass what you are expecting as Response. Son library takes care of converting your Json to you Java Object type.
BaseRequest
public class BaseRequest<T> extends Request<T> {
private final Class<T> resultClass;
private final Response.Listener<T> listener;
Gson gson = new Gson();
private final int REQUEST_TIMEOUT_LIMIT_SECONDS = 10; // Value in seconds
public BaseRequest(int method, String url, Class<T> resultClass, Response.Listener<T> listenerSuccess, Response.ErrorListener listenerError) {
super(method, url, listenerError);
this.resultClass = resultClass;
this.listener = listenerSuccess;
this.setRetryPolicy(new DefaultRetryPolicy(REQUEST_TIMEOUT_LIMIT_SECONDS * 1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, resultClass),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
}
The method parseNetworkResponse will take care of converting your Json to Java Object type.
Now you can create a class for each Request, for example Login:
public class LoginRequest<T> extends BaseRequest<T> {
private final Gson gson = new Gson();
private final String email;
private final String password;
public LoginRequest(String email, String password, Class<T> clazz,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Request.Method.POST, "url here...", clazz, listener, errorListener);
this.email = email;
this.password = password;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("param1", email);
params.put("param2", password);
return params;
}
}
Finally create the call for your request (inside your activity, fragment, wherever you need):
LoginRequest request = new LoginRequest<>("aaaa#email.com", "myDummyPassword", LoginResponseModel.class, new Response.Listener<LoginResponseModel>() {
#Override
public void onResponse(LoginResponseModel loginResponseModel) {
//Success
}
}, new BaseError(getApplicationContext()) {
#Override
public void onError(ErrorResponse response) {
//Erros
}
});
This way you will receive the objects you want, parsed from Gson.

Using Post in Retrofit

Can you anyone help me giving good example on how to use retrofit for posting large data from my local DB to mysql server.
Currently I am using async-http API and strangely there is always memory error coming up. I am looking for better API that wont give memory error while uploading huge text of data.
This is my setup:
List<TextDetails> unTextList = dbvalue.getTextData();
for (TextDetails td : unTextList)
{
String textID = td.getSerialNumber();
String textSMS = td.getText();
String textAddress = td.getFulladdress();
String textDate = td.getFulldate();
String textException = td.getExceptiontext();
textDetailsBackUpDataOnline(textID , textSMS, textAddress, textDate, textException);
}
private void textDetailsBackUpDataOnline(final String textID ,
String textSMS, String textAddress, String textDate, String textException)
{
final String uploadWebsite = url_backup_text_details;
RequestParams requestParams = new RequestParams();
requestParams.put("textSMS", textSMS);
requestParams.put("textAddress", textAddress);
requestParams.put("textDate", textDate);
requestParams.put("textException", textException);
Text_HttpClient.post(uploadWebsite, requestParams, new AsyncHttpResponseHandler()
{
#Override
public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] responseBody)
{
Log.e("textID", "= how many times");
}
#Override
public void onFailure(int statusCode, org.apache.http.Header[] headers, byte[] errorResponse, Throwable e)
{
e.printStackTrace(System.out);
}
});
}
Text_HttpClient class has the following:
public class Text_HttpClient
{
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler)
{
client.get(url, params, responseHandler);
}
public static void post(String url, RequestParams requestParams, AsyncHttpResponseHandler responseHandler)
{
client.post(url, requestParams, responseHandler);
}
}
1) Write service interface:
public interface ArticleGetListService {
#FormUrlEncoded // Request will have "application/x-www-form-urlencoded" MIME type
#POST("/api/Article/ArticleGetList")
public void getArticleList(#Field("LanguageCode") String languageCode,
#Field("CategoryId") String categoryId,
#Field("Token") String token,
Callback<ArticleViewPojo> response); //POJO: The json retrieved from the server is added to this class.
}
Here my Rest service requires 3 Parameters, change it as your need.
2) Write POJO for converting JSON returned from Rest Api into java class object so you can use data.
Just copy your JSON into this site, choose JSON source type, annotation as Gson. It will generate POJO for your JSON automatically.
3)On your Main Activity
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(baseUrl)
.build();
ArticleGetListService articleGetListService = restAdapter.create(ArticleGetListService.class);
Callback<ArticleViewPojo> callback = new Callback<ArticleViewPojo>() {
#Override
public void success(ArticleViewPojo model, Response response) {
//use model which is data returned to you
}
#Override
public void failure(RetrofitError error) {
//handle error
}
};
//START REST CALL
articleGetListService.getArticleList(languageCode, categoryId, token, callback);
//above parameters are those written in service interface at 1
//Whole Url is baseUrl+ArticleGetListService in above example

Requests and response from netty server hangs

I have the following code to create a netty web server based on http server created in the netty's example. My buisness logic is the following.
public class HttpServerHandler extends SimpleChannelInboundHandler<Object> {
private final static Logger LOG = LogManager
.getLogger(HttpServerHandler.class);
private WorkflowService workflowService;
private HttpRequest request;
private final StringBuffer buff = new StringBuffer();
private API avalancheApi;
public HttpServerHandler(WorkflowService workflowService) {
this.workflowService = workflowService;
this.avalancheApi = new API(this.workflowService);
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
LOG.debug("channelActive");
LOG.debug(ctx.toString());
};
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void channelRead0(ChannelHandlerContext ctx, Object msg)
throws IOException {
avalancheApi.setContext(ctx);
if (msg instanceof HttpRequest) {
HttpRequest request = this.request = (HttpRequest) msg;
if (HttpHeaders.is100ContinueExpected(request)) {
send100Continue(ctx);
}
String command = getCommand(request);
LOG.debug(command);
Map<String, List<String>> parameters = getParameters(request);
LOG.debug(parameters);
switch (command) {
case "/login":
ctx = avalancheApi.login(parameters);
break;
case "/test":
ctx = avalancheApi.test();
break;
default:
break;
}
}
if (msg instanceof LastHttpContent) {
LOG.debug("msg is of LastHttpContent");
}
if (!HttpHeaders.isKeepAlive(request)) {
// If keep-alive is off, close the connection once the content is
// fully written.
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(
ChannelFutureListener.CLOSE);
}
}
public class API {
private static final Logger LOG = LogManager.getLogger(API.class);
private ChannelHandlerContext ctx;
private HttpResponse response;
private WorkflowService workflowService;
public API(WorkflowService workflowService) {
this.workflowService = workflowService;
this.ctx = null;
}
public void setContext(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
public ChannelHandlerContext login(Map<String, List<String>> parameters) {
boolean success;
String username = getUsername(parameters);
String password = getPassword(parameters);
User user = null;
user = workflowService.login(username, password);
success = validateLogin(user);
this.response = writeLoginResponse(success);
this.ctx.write(this.response);
writeLoginContext(success, response);
return this.ctx;
}
private void writeLoginContext(boolean success, HttpResponse response) {
JsonObject jsonResponseMessage = new JsonObject();
jsonResponseMessage.addProperty("result", success);
LOG.debug(jsonResponseMessage.toString());
this.ctx.write(Unpooled.copiedBuffer(jsonResponseMessage.toString(),
CharsetUtil.UTF_8));
this.response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
jsonResponseMessage.toString().length());
}
private HttpResponse writeLoginResponse(boolean success) {
if (success)
return createSuccessfullLoginResponse();
else
return createLoginFailureResponse();
}
private HttpResponse createLoginFailureResponse() {
return Response.loginFailureResponse();
}
private HttpResponse createSuccessfullLoginResponse() {
return Response.loginSuccessResponse();
}
}
Response class is only creating the response and the content_type which is of application/json. Content Length is set in the API class. Using python client with requests, results in the request made in http://localhost/login?username=name&password=pass works only once. The second time everything works, but it doesn't finish processing the request and send the response object. Api calls get executed normally, and I also get the message of LastHttpContext message getting print. The problem sometimes happens with browser too. Am I missing something? Maybe the content data and the content length doesn't match? Could it be that when making requests from python client, the content of the previous context isn't flushed and the content_length value of the header and content length of the context doesn't match?
Just wild guess
this.response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
jsonResponseMessage.toString().length());
Instead, shouldn't you be doing jsonResponseMessage.toString().getBytes().length ?? Sometimes, one character is not just one byte.
My guess is that you have overwritten the context in your API class, and as a result, are writing the response to the wrong context. Is your HttpServerHandler marked with #Shareable?

Best way to model Android REST connection

I am making an Android app that connects to a web service via REST API and I have a dilemma with the design of the internal architecture.
Now I have class Client.java whose purpouse is make connect with the server (ConnectionMethod is Enum that contains GET|POST values):
public class Client {
private AsyncHttpClient client = new AsyncHttpClient(); //I use com.loopj.AsyncHttpClient to connect
private ConnectionMethod method;
private RequestParams params = new RequestParams();
private AsyncHttpResponseHandler responseHandler = new JsonHttpResponseHandler(){
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
//Actions when connection success
}
#Override
public void onFailure(int statusCode, Header[] headers, JSONObject response, Throwable error) {
//Actions when connection fails
}
};
public Client (RequestParams params, ConnectionMethod method) {
this.params = params;
this.method = method;
}
public void addParameters (Map<String, String> parameters) {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
this.params.put(entry.getKey(), entry.getValue());
}
}
public ServerResponse connect () {
RequestHandle handle;
if (this.method==ConnectionMethod.POST) {
handle = postRequest();
}
else {
handle = getRequest();
}
//How can I treat here different type of responses homogeneously?
}
private RequestHandle getRequest () {
return client.get(Constants.getEndpoint(), this.params, this.responseHandler);
}
private RequestHandle postRequest () {
return client.post(Constants.getEndpoint(), this.params, this.responseHandler);
}
}
A sample method that requests info from the server is this:
public static void login (String login, String password) {
//This classes should be static or dynamic?
Map<String, String> map = new HashMap<String, String>();
map.put("login", login);
map.put("password", password);
map.put("method", "site_login");
Client c = new Client();
c.addParameters(map);
c.getRequest();
}
All server responses are JSON: {status:0, result:array/int/string} when response is correct and {status:-1, message:string} when response is incorrect.
Additionaly I want to make classes to model components from JSON result (User.java, Message.java...) and intermediate methods between UI and API to implement the logic of the app and classes.
What is the best way to design an homogeneous connection system that manages automatically correct/fail response and independent of model (user, message...)?
There is a bunch of frameworks which can make this whole process much easier.
For example Retrofit is very simple framework for mapping java classes to REST calls. It comes with gson which will automatically deserialize response from json to plain java objects.
It also allows use callbacks as well as rxJava Observables. It allows to handle errors as well.
You can check sample app: https://github.com/JakeWharton/u2020
You are describing tools that already exist. My favorite happens to be Retrofit but there are others out there. Retrofit can handle the success and fail responses and even map JSON directly to a POJO.
My API client
public class ApiClient {
private static ApiInterface sApiInterface;
public static ApiInterface getApiClient(Context context) {
//build the rest adapter
if (sApiInterface == null) {
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("example.com")
.build();
sApiInterface = restAdapter.create(ApiInterface.class);
}
return sApiInterface;
}
public interface ApiInterface {
#GET("/program/{id}")
void getProgram(#Path("id") int id, RetrofitCallback<Program> callback);
}
My RetrofitCallback
public class RetrofitCallback<S> implements Callback<S> {
private static final String TAG = RetrofitCallback.class.getSimpleName();
#Override
public void success(S s, Response response) {
}
#Override
public void failure(RetrofitError error) {
Log.e(TAG, "Failed to make http request for: " + error.getUrl());
Response errorResponse = error.getResponse();
if (errorResponse != null) {
Log.e(TAG, errorResponse.getReason());
if (errorResponse.getStatus() == 500) {
Log.e(TAG, "Handle Server Errors Here");
}
}
}
}
My model
public class Program {
#Expose
private doublea.models.Airtime Airtime;
#Expose
private String id;
#Expose
private String title;
#SerializedName("short_name")
#Expose
private String shortName;
#SerializedName("full_description")
#Expose
private String fullDescription;
#SerializedName("short_description")
#Expose
private String shortDescription;
#Expose
private doublea.models.Image Image;
#SerializedName("image")
#Expose
private String imageName;
#Expose
private List<Host> hosts = new ArrayList<Host>();
#Expose
private List<Category> categories = new ArrayList<Category>();
#Expose
private List<Airtime> airtimes = new ArrayList<Airtime>();
/** Getters and Setters */
public Program() {
}
How it is used.
private void executeProgramApiCall(int programId) {
ApiClient.getApiClient(this).getProgram(programId, new RetrofitCallback<Program>() {
#Override
public void success(Program program, Response response) {
super.success(program, response);
addDataToAdapter(program);
}
});
}

Categories