In the AsyncTask android. When calling a method in another class gets an exception which equals to null in the doInBackGround() task.
Even the hard coded inside the rest.request(url, method, json) doesn't work
protected JSONArray doInBackground(Void... arg0) {
try {
return rest.request(url, method, json); // <-- returns json array
} catch (Exception e) {
this.e = e;
}
return null; // <--- returning this null
}
Other things are like this,
private class doRequest extends AsyncTask<Void, JSONArray, JSONArray>
protected void onPostExecute(JSONArray data)
/*rest client class*/
public class AndrestClient {
// The client to use for requests
DefaultHttpClient client = new DefaultHttpClient();
public JSONArray request(String url, String method, String json) throws RESTException {
if (method.matches("GET")) {
return get(url);
} else if (method.matches("POST")) {
return post(url, json);
} else if (method.matches("PUT")) {
//return put(url, data);
} else if (method.matches("DELETE")) {
//return delete(url);
}
throw new RESTException("Error! Incorrect method provided: " + method);
}
public JSONArray get(String url) throws RESTException {
String jsonjr = "['Chanuthi','Damsith','Dunili','Isath','Minuka','Uvin','Vidath']";
JSONArray jsonAraay = null;
try {
jsonAraay = new JSONArray(jsonjr);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonAraay;
}
}
The exception I got is e=null. All the other things work properly. When I am hard coding the result inside in the doInBackGround it works properly. Also the rest client get method returns the exact thing.
It appears you're using AsyncTask improperly. Firstly, you must subclass/nest your AsyncTask as per the Android documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
In addition, you should follow the fundamental rules for calling methods of an outter class from a nested class.
There are some alternatives, like:
Create the AndrestClient object in onPreExecute() of the AsyncTask
Pass the AndrestClient object to the doInBackground as a parameter, then call its methods by doing something like this in the outter class:
doRequest.execute(rest);
Related
Here is my Code:
public class ServerCall {
Context context;
public int cartCount;
public ServerCall(Context context){
this.context=context;
}
public Integer addCartItem(RequestObject requestObject) {
new AddToCartList().execute(requestObject);
Log.d("count",String.valueOf(cartCount));
return cartCount;
}
public class AddToCartList extends AsyncTask<RequestObject, Void, JSONObject> {
#Override
protected JSONObject doInBackground(RequestObject... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(arg0[0], ServiceHandler.POST);
// List<Products> result = new ArrayList<Products>();
Log.d("Response: ", "> " + jsonStr);
JSONObject product = new JSONObject();
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
product = jsonObj.getJSONObject("rsBody");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return product;
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
try {
if (result != null) {
String status = result.getString("status");
int totalCartItem = result.getInt("totalCartItem");
/* cartHelper = new CartHelper();
cartHelper.setStatus(status);
cartHelper.setTotalCartItem(totalCartItem);*/
cartCount=totalCartItem;
Log.d("status",status);
Log.d("totalCartItem",String.valueOf(cartCount));
Toast.makeText(context, status, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
}
}
We didn't get value of global variable cartCount which I set inside AddToCartList class and try to get its value from addCartItem() function from where AddToCartList is called but we get null value.
I think that the main problem in your solution is the fact that you're trying to edit ServerCall variable from an Inner class, this would work only if cartCount is static, and I suggest you wait for your task to be finished as some people have already mentioned, using the get method new AddToCartList().execute().get()
The problem is, ServerCall and AddToCartList are not the same class, so you must first get a reference to the servercall in addtocartlit, then reference the cartCount using your reference to the servercall instance, like call.cartCount, instead of cartcount, unless its an inner class which it does not appear to be.
Secondly, you must save a reference to the addtocartlist asynctask inside addCartItem() ,then call its .get() method after starting it, this will ensure it finishes before you try to log the new value.
This question already has answers here:
AsyncTask return value
(4 answers)
Closed 9 years ago.
I am calling soap webservice and need to display what is returned. but I couldnt do it because AsyncTask is complex and I dont know how to use it properly. would you please tell me how to return data from the called function via asynctask?
here is my code
public class WebserviceTool {
private final String NAMESPACE = "http://tempuri.org/";
private final String URL = "http://192.168.0.11:9289/Service1.asmx";
private final String SOAP_ACTION = "http://tempuri.org/get_currency";
private final String METHOD_NAME = "get_currency";
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public String execute_barcode_webservice(String s1, String s2) {
//Create request
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("date",s1);
request.addProperty("cur_code",s2);
//Create envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.encodingStyle = SoapEnvelope.ENC;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
Object response;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
response = (Object) envelope.getResponse();
Log.i("my_error", response.toString());
} catch (Exception e) {
Log.i("my_error", e.getMessage().toString());
}
return "testarif";
}
public class AsyncCallWS extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
try {
execute_barcode_webservice(params[0], params[1]);
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
#Override
protected void onPostExecute(Void result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
}
this is the function execute_barcode_webservice() that does all the job and returns data. but since I call execute_barcode_webservice() view AsyncTask, I dont know how to return with it. how can I do it?
The result of the async task execution is the response object produced by execute_barcode_webservice(). However, don't think about the async task as something that will execute and return a value to you. Instead, inside the method onPostExecute() you must take the response object and process it (extract its values and display them in a list, or whatever you want to do with it). The async task is just a way to execute some code in a separate thread then go back to the main thread (the UI thread) and process the results, which is done in onPostExecute().
My suggestion: rewrite execute_barcode_webservice() to return a response object instead of a String (an object that can be null if the operation fails) and pass that object to the onPostExecute() method. You will have to change the async task to:
public class AsyncCallWS extends AsyncTask<String, Void, Object> {
#Override
protected Object doInBackground(String... params) {
Object response = null;
try {
response = execute_barcode_webservice(params[0], params[1]);
} catch (Exception e) {
// TODO: handle exception
}
return response;
}
#Override
protected void onPostExecute(Object response) {
if (response != null) {
// display results in a list or something else
}
}
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.
I have a small function in java that does a HTTP POST, and returns a JSON Object. This function return the JSON Object.
public JSONObject send_data(ArrayList<NameValuePair> params){
JSONObject response;
try {
response = new JSONObject(CustomHttpClient.executeHttpPost(URL, params).toString());
return response;
} catch(Exception e) {
// do smthng
}
}
This shows me an error that the function must return a JSONObject. how do i make it work? I cant send a JSONObject when there is an error, can I? It would be useless to send a blank jsonobject
This is because you are only returning a JSONObject if everything goes smoothly. However, if an exception gets thrown, you will enter the catch block and not return anything from the function.
You need to either
Return something in the catch block. For example:
//...
catch(Exception e) {
return null;
}
//...
Return something after the catch block. For example:
//...
catch (Exception e) {
//You should probably at least log a message here but we'll ignore that for brevity.
}
return null;
Throw an exception out of the method (if you choose this option, you will need to add throws to the declaration of send_data).
public JSONObject send_data(ArrayList<NameValuePair> params) throws Exception {
return new JSONObject(CustomHttpClient.executeHttpPost(URL, params).toString());
}
You could change it to this:
public JSONObject send_data(ArrayList<NameValuePair> params){
JSONObject response = null;
try {
response = new JSONObject(CustomHttpClient.executeHttpPost(URL, params).toString());
} catch(Exception e) {
// do smthng
}
return response;
}
There's a path through the function that doesn't return anything; the compiler doesn't like that.
You can change this to
catch(Exception e) {
// do smthng
return null; <-- added line
}
or put the return null (or some reasonable default value) after the exception block.
It's reasonble to return 'something' even in an error condition.
Look at JSend for a way to standardize your responses - http://labs.omniti.com/labs/jsend
In my opinion it's easiest to return an error json object and handle that on the client side then to solely rely on HTTP error codes since not all frameworks deal with those as well as they could.
The send_data() method should throw an exception so that the code calling send_data() has control over how it wants to handle the exception.
public JSONObject send_data(ArrayList<NameValuePair> params) throws Exception {
JSONObject response = new JSONObject(CustomHttpClient.executeHttpPost(URL, params).toString());
return response;
}
public void someOtherMethod(){
try{
JSONObject response = sendData(...);
//...
} catch (Exception e){
//do something like print an error message
System.out.println("Error sending request: " + e.getMessage());
}
}
I prefer one entry and one exit. Something like this seems reasonable to me:
public JSONObject send_data(ArrayList<NameValuePair> params)
{
JSONObject returnValue;
try
{
returnValue = new JSONObject(CustomHttpClient.executeHttpPost(URL, params).toString());
}
catch (Exception e)
{
returnValue = new JSONObject(); // empty json object .
// returnValue = null; // null if you like.
}
return returnValue;
}
How can I retrieve a file from the following method:
public void getJson(String pathToFile) {
String userUrl = DOMAIN_URL+pathToFile;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(userUrl));
JSONArray outerJsonArray;
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
try {
JSONValue jsonValue = JSONParser.parse(response.getText());
JSONArray jsonArray = jsonValue.isArray();
if (jsonArray != null) {
} else {
throw new JSONException();
}
} catch (JSONException e) {
}
} else {
}
}
});
} catch (RequestException e) {
}
}
Now it is just void. I should retriwe the jsonArray variable
You simply can't.
The request is asynchronous, so your method has to be asynchronous (non-blocking) too. You can pass something like an AsyncCallback (to reuse an existing interface) to your getJson method, and have your RequestCallback call it... back, with the JSONArray.
Technically speaking, that would be possible, but that's a design choice in GWT to not allowing blocking AJAX requests.
Embrace asynchrony!
Just change the declaration to
public JSONArray getJson(String pathToFile) {
After the line
JSONArray jsonArray = jsonValue.isArray();
you can add
return jsonArray;
Now you have to be careful. Obviously, you have some error checking conditions in case the array is null or an error occurs during reading. It is up to you to design how to handle them: if the array is null, should you throw an exception or return the null value? If there is an error reading, should you throw an exception, print an error, or return a null value? These are considerations that your external interface will dictate.