HttpClient.execute error =( [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
And Error's are:
error opening trace file:No Such file or directory(2);
java.lang.IllegalStateException: Manager is shut down. at
org.apache.http.impl.conn.SingleClientConnManager.assertStillUp(SingleClientConnManager.java:174)
org.apache.http.impl.conn.SingleClientConnManager.getConnection(bla
bla bla .java:212)
org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(---.java:190)
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:326)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
org.apache.http.impl.client.AbstractHttpClient.xecute(AbstractHttpClient.java:487)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
and more...
public class ReqClass {
public static final String TAG = ReqClass.class.getSimpleName();
//creating new ResClass object
ResClass resp = new ResClass();
//sending request
HttpResponse response;
//making the request - containst (url,header,entity);
HttpPost request;
//New HTTP Client
HttpClient httpClient = new DefaultHttpClient();
//our code in JSON or XML to Send Request
private String s;
//This variable contains the total number of keys
private int size;
// Map
Map<String,String> code = new HashMap<String, String>();
// Adding only Key Value parameters
public void addparametr (String key, String value){
code.put(key,value);
}
public String getS(){
return s;
}
//Adding Key Value and size of new map.
public void addparametr (String key, String value, int nOfValues){
}
public void Build(String lang){
//List Of keys
List<String> keys=new ArrayList<String>(code.keySet());
//k = keys; v = values;
String k="",v="";
// size = size of Map;
size=code.size();
// if we want to make our JSON Code to send Request
if (lang=="json"){
s="";
s+="{";
for (int i=0; i<size; i++){
k=keys.get(i);
v=code.get(k);
if (i==size-1) s=s+'"'+k+'"'+": "+'"'+v+'"';
else s=s+'"'+k+'"'+": "+'"'+v+'"'+',';
}
s=s+"}";
}
if (lang =="xml"){
s="";
s+="<code>";
for (int i=0; i<size; i++){
k=keys.get(i);
v=code.get(k);
s=s+'<'+k+'>'+v+"</"+k+'>';
}
s=s+"</code>";
}
}
// The Send Request Method - need link parameter and our JSON or XML code
public ResClass SendR (String url, String lang){
String valueOfSize = String.valueOf(size);
request= new HttpPost(url);
//adding a Header
request.addHeader("Header - Request Size", valueOfSize);
//adding request's body (Entity)
HttpEntity entity;
try {
entity = new StringEntity(s, "UTF-8");
request.setEntity(entity);
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BackGroundTask doItInBackGround = new BackGroundTask();
doItInBackGround.execute();
//closing our connection
httpClient.getConnectionManager().shutdown();
return resp;
}
private class BackGroundTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
try {
//execute - means sending
response = httpClient.execute(request);
//adding new response to our Response Class
resp.addNewResponse(response);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
Log.e(TAG, "Exception caught: ", e);
}
return null;
}
}
}

You are calling getConnectionManager().shutdown() just after starting AsyncTask so before executing doInBackground method connection is shutdown . so use onPostExecute for close connection as:
protected void onPostExecute(Long result) {
// call shutdown() here
httpClient.getConnectionManager().shutdown();
}

Related

the app crashes when using OkHttpClient in doInBackground [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
My application on Android LOLLIPOP runs well, but in the lower version, program crashe and displays this error:
Exception caught
java.lang.RuntimeException: An error occured while executing doInBackground()
And points to this line of code:
OkHttpClient client = new OkHttpClient();
this is my code:
private void getMoviesFromDBz(int id) {
AsyncTask<Integer, Void, Void> asyncTask = new AsyncTask<Integer, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Integer... movieIds) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(linkkk + movieIds[0])
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Movie movie = new Movie(object.getInt("id") , object.getString("per") , object.getString("movie_name"),
object.getString("movie_image"), object.getString("movie_genre") , object.getString("movie_discription") , object.getString("movie_lat"), object.getString("movie_lon") , object.getString("movie_marker") , object.getString("sort") , object.getString("price") , object.getString("email") , object.getString("tell") , object.getString("location") , object.getString("count"));
ItemOneFragment.this.movies2.add(movie);
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
adapter2.notifyDataSetChanged();
getMoviesFromDB(0);
}
};
asyncTask.execute(id);
scroll2 = 1;
}
You're trying to access the Main/UI Thread in a background Thread:
ItemOneFragment.this.movies2.add(movie);
just return the movie object and execute the above line on the onPostExecute() method, also I wouldn't recommend instantiating an OkHttpClient for each request.
You're trying to performing action the on UI Thread from background Thread. So you can userunonuithread
runOnUiThread(new Runnable() {
#Override
public void run() {
ItemOneFragment.this.movies2.add(movie);
}
});
see the changes below in your code.
#Override
protected Void doInBackground(Integer... movieIds) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(linkkk + movieIds[0])
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Movie movie = new Movie(object.getInt("id") , object.getString("per") , object.getString("movie_name"),
object.getString("movie_image"), object.getString("movie_genre") , object.getString("movie_discription") , object.getString("movie_lat"), object.getString("movie_lon") , object.getString("movie_marker") , object.getString("sort") , object.getString("price") , object.getString("email") , object.getString("tell") , object.getString("location") , object.getString("count"));
runOnUiThread(new Runnable() {
#Override
public void run() {
ItemOneFragment.this.movies2.add(movie);
}
});
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
I think this may solve your problem.
You don't need any Asynctask with Okhttp
Look up examples that use the enqueue method
// Build the client and request in the main thread
// Start an asynchronous method
client.newCall(request).enqueue(new Callback() {
#Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
JSONObject json = new JSONObject(responseBody.string());
}
}
});
If you want to use JSON objects with Okhttp, Retrofit would be a better library

Android Java retrieve JSON values and store as object in list

I would like to connect to Api link which can have multiple pages and store all the JSON values as a object in a list.
Here is a Api link example with multiple pages, note the number as last being the page you're on.
Problems that I have so far encountered and unable to solve. Return type of doInBackground as constructor class apiRootObject and how to deserialize the Json result, its logical why it doesnt work since I its extended from AsyncTask but i do not know how to work around this problem or what other road to take.
This is the code I have so far.
Calling the initial function in my Activity.java
String userSearchRequest = search_activity_data.getString("userSearchRequest");
String URL = "http://www.gw2spidy.com/api/v0.9/json/item-search/" + userSearchRequest + "/";
//Api link example with multiple pages = "http://www.gw2spidy.com/api/v0.9/json/item-search/Iron"
AsyncFetch parkingInfoFetch = new AsyncFetch(this);
parkingInfoFetch.setOnResponse(this);
parkingInfoFetch.execute(URL);
My AsyncFetch.java class which is called from aboves code
public class AsyncFetch extends AsyncTask {
public AsyncFetch(Context context) {
this.context = context;
}
private Context context;
private JSONObject jsonObject;
private onResponse onResponse;
public void setOnResponse(onResponse onResponse) {
this.onResponse = onResponse;
}
#Override
protected apiRootObject doInBackground(String... params) { //Incompatible return type
// TODO Auto-generated method stub
apiRootObject apiRootObject = null;
apiRootObject tempApiRootObject = null;
int page = 0;
try {
do {
HttpGet get = new HttpGet(params[0] + page);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
//jsonObject = new JSONObject(result);
tempApiRootObject = /*Deserialize into <RootObject>(result)*/
if (apiRootObject == null){
apiRootObject = tempApiRootObject;
}
else{
apiRootObject.results.addAll(tempApiRootObject.results);
apiRootObject.count += tempApiRootObject.count;
}
page++;
}
while(tempApiRootObject.last_page != tempApiRootObject.page);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return apiRootObject;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
this.onResponse.onResponse(result);
}
public interface onResponse {
public void onResponse(JSONObject object);
}
}
And back in the activity.java everything is being added to the list in the onResponse function.
public void onResponse(JSONObject object) {//Still expecting a JSONObject while I am changing this return type
Log.i("gw2Log", object.toString());
apiRootObject resultClass = new apiRootObject();
try {
resultClass.setCount(object.getInt("count"));
resultClass.setPage(object.getInt("page"));
resultClass.setLast_page(object.getInt("last_page"));
resultClass.setTotal(object.getInt("total"));
JSONArray list = new JSONArray(object.getString("results"));
for (int i = 0; i < resultClass.getCount(); i++) {
JSONObject resultsObject = list.getJSONObject(i);
apiResults temp = new apiResults();
temp.setData_id(resultsObject
.getInt("data_id"));
temp.setName(resultsObject
.getString("name"));
temp.setRarity(resultsObject
.getInt("rarity"));
temp.setRestriction_level(resultsObject
.getInt("restriction_level"));
temp.setImg(resultsObject
.getString("img"));
temp.setType_id(resultsObject
.getInt("type_id"));
temp.setSub_type_id(resultsObject
.getInt("sub_type_id"));
temp.setPrice_last_changed(resultsObject
.getString("price_last_changed"));
temp.setMax_offer_unit_price(resultsObject
.getInt("max_offer_unit_price"));
temp.setMin_sale_unit_price(resultsObject
.getInt("min_sale_unit_price"));
temp.setOffer_availability(resultsObject
.getInt("offer_availability"));
temp.setSale_availability(resultsObject
.getInt("sale_availability"));
temp.setSale_price_change_last_hour(resultsObject
.getInt("sale_price_change_last_hour"));
temp.setOffer_price_change_last_hour(resultsObject
.getInt("offer_price_change_last_hour"));
resultClass.addObject(temp);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < resultClass.count; i++) {
Log.i("gw2Log", resultClass.getObject(i).name);
}
}
Ofcourse there are also 2 constructor classes apiResults and apiRootObject.
EDIT:
If you take the link on the top of the question you get a lot of JSON values returned, every page can have 50 of these results if there are more a new page is created.
I want to connect to this Api link, and retrieve all values that are being returned. If there are multiple pages it needs to loop through all existing pages and add these JSON values to the exact same list.
I have asked a similiar question before in c# and here I've got it working but I now need the exact same in Android Java. For android java i was told i need to use AsyncTask in order to make a connection and do all of this in the background of the application. If there is a better or easier way, please enlighten me.
It might not be too late to use Retrofit .
gson is the easiest way to convert json into a class.
//your class
public class Foo {
public final int bar;
public final String bazz;
public foo(int bar, String bazz) {
this.bar = bar;
this.bazz = bazz;
}
}
//your json
{ "bar" : 4, "bazz" : "interesting content" }
//your gson call
Gson gson = new Gson();
Foo foo = gson.fromJson(json, Foo.class);
you can even do nested objects and it will deserialize them all.
public class FooHaver {
public final String prop1;
public final Foo foo;
}
//your json
{ "prop1" : "more content", "foo" : { "bar" : 4, "bazz" : "even more content" } }
you can also do json arrays as arrays or as a java List of any type you want
try this
#Override
protected apiRootObject doInBackground(String... params) { //Incompatible return type
// TODO Auto-generated method stub
apiRootObject apiRootObject = null;
apiRootObject tempApiRootObject = null;
List<apiRootObject> myList=new ArrayList<apiRootObject>();
int page = 0;
try {
do {
HttpGet get = new HttpGet(params[0] + page);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
jsonObject = new JSONObject(result);
//handling json exceptions
if(jsonObejct!=null && !jsonObject.isNull("page")&&..){
tempApiRootObject.page=jsonObject.getString("page");
tempApiRootObject.last_page=jsonObject.getString("last_page");
//here we put the results in the tempsApiRootObject
JSONArray ja = jsonObject.getJSONArray("results");
for (int i = 0; i < ja.length(); i++) {
JSONObject c = ja.getJSONObject(i);//this is an item
int data_id= c.getInt("data_id");
String name= c.getString("name");
//the other values
//here you add them in your arraylist of <apiResults> (*)
}
//and here we add the arraylist in (*) to tempApiRootObject
myList.add(tempApiRootObject);
/* if (apiRootObject == null){
apiRootObject = tempApiRootObject;
}
else{
apiRootObject.results.addAll(tempApiRootObject.results);
apiRootObject.count += tempApiRootObject.count;
}*/ i didn't understand this
}page++;
}
while(tempApiRootObject.last_page != tempApiRootObject.page);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myList// apiRootObject;
}
and this
public void onResponse(List<apiRootObject> myList) {
for(int i=0;i++;i<myList.size()){
apiRootObject resultClass =myList.get(i);
//do something
}
}

JAVA: How to listen to calling of event handler/How to get returned result of an event handler?

I am creating an Android chat application wherein I am using WebSockets and on top of that I want to create a custom implementation of Application protocol.
I am stuck in a situation.
Essentially, what I want is a way to know that an event handler method has been called in another class, fire up my own method in my class based on that and then get the result of that event handler method in my class.
How is that possible?
I researched a lot and found something like binding, event emitters, etc. Can someone point me to the right direction and provide some resources from where I can learn this technique?
This is what I have done so far:
public void connect(){
try {
setUpWebSocketHandler(handler);
mConnection.connect(wsuri, handler);
}
catch (WebSocketException e) {
Log.d("exception", e.toString());
}
}
public void setUpWebSocketHandler(WebSocketHandler handler)
{
handler = new WebSocketHandler(){
//first method for websockethandler
#Override
public void onOpen() {
//here i create a json format string to be sent to my server that returns something afterwards
String output = json.toString();
Log.d("OUTPUT+" , output);
Log.d("onOpen", "Status: Connected to " + wsuri);
mConnection.sendTextMessage(output);
}
//second method for websockethandler
#Override
public void onTextMessage(final String payload) {
Log.d("onTextMessage", "Response: " + payload);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(payload);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
String type = jsonObj.getString("type");
switch (type) {
case "xxx":
//authEvent
System.out.println("xxx");
break;
case "yyy":
//userOnlineEvent
System.out.println("yyy");
break;
case "zzz":
System.out.println("zzz");
break;
case "userListToken":
userList = getUserList(payload);
break;
default:
System.out.println("DefaultCase");
break;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//third method for websockethandler
#Override
public void onClose(int code, String reason) {
Log.d("onClose", "Connection lost.");
}
};
}
public String getUserList(final String payload)
{
final Thread connectthread;
connectthread = new Thread(
new Runnable()
{
public void run()
{
try {
//here i create a URL, send post request to it and i get a response with userlist
HttpClient client = new DefaultHttpClient();
HttpGet post = new HttpGet(url);
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((userList = rd.readLine()) != null) {
System.out.println(userList);
Log.d("HTTP GET RESPONSE", "Response: " + userList);
}
} catch (JSONException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
);
connectthread.start();
try
{
connectthread.join();
}
catch (Exception e)
{
Log.i("error","Error!!");
}
System.out.println("userListToken");
return userList;
}
I have another question. I got the userList using callbacks....The problem now is:
private class ProcessLogin extends AsyncTask<String, Void, String> {
private ProgressDialog pDialog;
String uname,password;
#Override
protected void onPreExecute() {
super.onPreExecute();
uname = txtUsername.getText().toString();
password = txtPassword.getText().toString();
pDialog = new ProgressDialog(LoginActivity.this);
pDialog.setTitle("Contacting Servers");
pDialog.setMessage("Logging in ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args) {
String user = null;
ifly.connect();
user = userList;
return user;
}
#Override
protected void onPostExecute(String user) {
try {
if(user != null){
//Intent i = new Intent("com.example.tabmainactivity");
Log.d("Got it", "Response: " + userList);
pDialog.dismiss();
//startService(new Intent(getApplicationContext(),iFlyChatMessage.class));
//startActivity(i);
//finish();
}else{
// username / password doesn't match
pDialog.dismiss();
Toast.makeText(getApplicationContext(),
"Incorrect username/password", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void processMessage(String userList)
{
this.userList = userList;
}
I want the userList in postExecute so that i can send this userList to another activity. How do i stop doinbackground() to wait for callback to finish. If I use thread.sleep, the whole process stops, not even connect works.
Thanks
You can declare an interface somewhere, make your event handler accept an instance of this interface, then create an anonymous class implementing this interface while passing that instance in your handler's registration with event source.
Something like below:
public class MyClass{
...
...
component.addXXXListener(new EventHandler(new MyInterface() {
#Override
public void doSomething() {
callMethod();
}
}));
...
...
public void callMethod() {
...
...
}
I hope you got the point.
I'm not sure that I understood you correctly.
You should use callback object.
Something like:
public interface MessageProcesor{
public void processMessage(String message);
}
Your activity should implement this interface.
And you should have MessageProcesor field in your "client" class.
Your code should look something like this:
private MessageProcesor callback;
public void setUpWebSocketHandler(WebSocketHandler handler)
{
handler = new WebSocketHandler(){
//first method for websockethandler
#Override
public void onOpen() {
//here i create a json format string to be sent to my server that returns something afterwards
String output = json.toString();
Log.d("OUTPUT+" , output);
Log.d("onOpen", "Status: Connected to " + wsuri);
mConnection.sendTextMessage(output);
}
//second method for websockethandler
#Override
public void onTextMessage(final String payload) {
Log.d("onTextMessage", "Response: " + payload);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(payload);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
String type = jsonObj.getString("type");
switch (type) {
case "xxx":
//authEvent
System.out.println("xxx");
break;
case "yyy":
//userOnlineEvent
System.out.println("yyy");
break;
case "zzz":
System.out.println("zzz");
break;
case "userListToken":
userList = getUserList(payload);
callback.processMessage(userList);
break;
default:
System.out.println("DefaultCase");
break;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//third method for websockethandler
#Override
public void onClose(int code, String reason) {
Log.d("onClose", "Connection lost.");
}
};
}
public String getUserList(final String payload)
{
final Thread connectthread;
connectthread = new Thread(
new Runnable()
{
public void run()
{
try {
//here i create a URL, send post request to it and i get a response with userlist
HttpClient client = new DefaultHttpClient();
HttpGet post = new HttpGet(url);
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((userList = rd.readLine()) != null) {
System.out.println(userList);
Log.d("HTTP GET RESPONSE", "Response: " + userList);
}
} catch (JSONException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
);
connectthread.start();
try
{
connectthread.join();
}
catch (Exception e)
{
Log.i("error","Error!!");
}
System.out.println("userListToken");
return userList;
}
You can pass "callback" as constructor param or via setter method.
Hope this helps.

HttpClient Replicate in Java from C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have an Android project built in Xamarin (.NET) I wish to convert to native Java. In the Xamarin app I have built an API class used to access HTTP data utilising Generics, which looks like this:
public class InventoryAPI {
HttpClientHandler handler;
Uri baseAddress;
HttpClient client;
public InventoryAPI() {
// .. Init code here
}
public async Task<Response> EnrolMultipleItemsAsync(EnrolItemModel[] _items) {
try {
var result = await PostAsync<Response>("api/inventory/enrolmultipleitems", _items);
Console.WriteLine(result.Message);
return result;
}
catch (Exception ex) {
App.Current.Logger.LogInfo("Exception at InventoryAPI - Error: EnrolItemAsync:");
App.Current.Logger.LogError(ex.Message);
throw ex;
}
}
public Response EnrolMultipleItems(EnrolItemModel[] _items) {
try {
var result = Post<Response>("api/inventory/enrolmultipleitems", _items);
return result;
}
catch (Exception ex) {
App.Current.Logger.LogInfo("Exception at InventoryAPI - Error: EnrolItem:");
App.Current.Logger.LogError(ex.Message);
throw ex;
}
}
private async Task<T> PostAsync<T>(string apiLocation, object postData) {
var response = await client.PostAsync(apiLocation, postData.ToHttpContentString());
T result = default(T);
if (response.StatusCode == HttpStatusCode.OK) {
var json = await (response.Content.ReadAsStringAsync());
result = DeserializeJson<T>(json);
}
return result;
}
private T Post<T>(string apiLocation, object postData) {
var response = client.PostAsync(apiLocation, postData.ToHttpContentString()).Result;
T result = default(T);
if (response.StatusCode == HttpStatusCode.OK) {
var json = response.Content.ReadAsStringAsync().Result;
result = DeserializeJson<T>(json);
}
return result;
}
public T DeserializeJson<T>(string json) {
var parsed = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
return parsed;
}
}
I like this style of API and it has worked well in the Xamarin app, so now I wish to port this to Java - and here's where I'm stuck!
Here's what I have so far:
public class APIDownloader extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... ts) {
String url = ts[0].toString();
return Get(url);
}
private String Get(String url) {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpEntity entity = null;
String result = "";
try {
//Execute and get the response.
HttpResponse response = httpclient.execute(httpget);
entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity);
//final JSONArray jObject = new JSONArray(EntityUtils.toString(entity));
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Catch no internet connectivity exception
e.printStackTrace();
}
return result;
}
}
And then a separate API class:
public class InventoryAPI {
public List<LocationModel> GetAllLocations() throws IOException {
String url = "https://domain.com/api/inventory/getall";
String response = null;// Get(url);
try {
response = new APIDownloader().execute(url).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Gson gson = new Gson();
LocationModel[] mcArray = gson.fromJson(response, LocationModel[].class);
return Arrays.asList(mcArray);
}
}
Whilst the Java code above does work just fine (I've only implemented the GET so far) it does seem like it's going to get out of hand very quickly, especially after I port the POST methods in the C# library to the Java package.
What would be the best approach to replicate the Xamarin API Class I have above in Java?
If you're going to go native Java then do yourself a favor and use Retrofit. That will save you a ton of code in your API layer. Regular Java Http stuff is ugly, Retrofit makes it much easier.
When you get comfortable, look at RxAndroid (RxJava) to really help with some of your Async code.

Android Http API

I am trying to write a Http API in android. I am using a AsyncTask to run the calls to my web service.I am not interested in updating the UI, instead all I want is the data to use in my application logic. This is what I have so far:
public class DataManager{
public static String result;
public DataManager ()
{
}
public String get ()
{
User user = new User ();
user.execute("http://someuri/service/users/id/21001");
return user.getResult();
}
}
public class User extends AsyncTask <String,Void,String>{
private String result;
#Override
protected String doInBackground(String... arg0)
{
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet (arg0[0]);
try
{
HttpResponse response = client.execute (get);
if (response.getStatusLine().getStatusCode () == 200)
{
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
}
catch (ClientProtocolException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
this.result = result;
}
public String getResult ()
{
return result;
}
}
I want a typical call to be:
DataManager manager = new DataManager ();
String value = manager.get ();
But when I run this I get back null. What is causing this and how can I refactor this code to get the desired behavior.
The whole idea of a thread is that it runs concurrently. Basically, here's what you're doing:
User user = new User (); // Create User object
user.execute("http://someuri/service/users/id/21001"); // Start thread
return user.getResult(); // Return thread result
However, there is no time for the thread to run between "start" and "return result".
I would suggest using some kind of callback; first, make get() return void, and remove the return statement. Then, you pass in some object which implements YourCallback, and then call onCallback(result) from within onPostExecute().
Your calling code would then look like this:
DataManager x = new DataManager();
x.get(new YourCallback() {
public void onCallback(String result) {
// ...
}
});
There is a much fuller example in this fantastic answer.

Categories

Resources