16

I'll keep this one as simple as I can.

I have a method in my control layer that uses a class CallServiceTask that extends AsyncTask. When calling new CallServiceTask().execute(parameters)
How do I retrieve the data returned from doInBackground? All the tutorials I've found use the class that extends AsyncTask directly from their Activity.
My problem is a little bit more complex than that.
All I want is to take the Object[] returned by doInBackground and set it to the private data members of my RestClient class.

CallServiceTask looks like this :

    private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{

    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];

        return executeRequest(req, url);
    }
}

And my RestClient class looks like this:

public class RestClient
{

private ArrayList <NameValuePair> params;
private ArrayList <NameValuePair> headers;

private JSONObject jsonData;

private Object[] rtnData;

private String url;

private boolean connError;

public int getResponseCode() {
    return responseCode;
}

/**
 * 
 * @return  the result of whether the login was successful by looking at the response parameter of the JSON object. 
 */
public Boolean DidLoginSucceed()
{
    // Will Crash on socket error
        return ((JSONObject) rtnData[0]).optBoolean("response");
}

public String GetToken()
{
    return jsonData.optString("token");
}

public RestClient(String url)
{
    this.url = url;
    params = new ArrayList<NameValuePair>();
    headers = new ArrayList<NameValuePair>();
    rtnData = new Object[]{ new JSONObject() , Boolean.TRUE  };
}

public void AddParam(String name, String value)
{
    params.add(new BasicNameValuePair(name, value));
}

public void AddHeader(String name, String value)
{
    headers.add(new BasicNameValuePair(name, value));
}

/**
 * This method will execute, call the service and instantiate the JSON Object through executeRequest().
 * 
 * @param method    an enum defining which method you wish to execute.
 * @throws Exception
 */
public void ExecuteCall(RequestMethod method) throws Exception
{
    Object[] parameters = new Object[]{ new HttpGet() , new String("") };
    switch(method) {
        case GET:
        {
            //add parameters
            String combinedParams = "";
            if(!params.isEmpty()){
                combinedParams += "?";
                for(NameValuePair p : params)
                {
                    String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue());
                    if(combinedParams.length() > 1)
                    {
                        combinedParams  +=  "&" + paramString;
                    }
                    else
                    {
                        combinedParams += paramString;
                    }
                }
            }

            HttpGet request = new HttpGet(url + combinedParams);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }
            parameters[0] = request;
            parameters[1] = url;

            new CallServiceTask().execute(parameters);

            jsonData = ((JSONObject) rtnData[0]).optJSONObject("data");
            connError = (Boolean) rtnData[1];
            break;

        }
        case POST:
        {
            HttpPost request = new HttpPost(url);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            if(!params.isEmpty()){
                request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            }
            new CallServiceTask().execute(request, url);
            break;
        }
    }
}

private Object[] executeRequest(HttpUriRequest request, String url)
{
    HttpClient client = new DefaultHttpClient();
    client = getNewHttpClient();

    HttpResponse httpResponse;

    try {
        httpResponse = client.execute(request);
        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            String response = convertStreamToString(instream);
            try {
                rtnData[0] = new JSONObject(response);
                rtnData[1] = false;

            } catch (JSONException e1) {
                rtnData[1] = true;
                e1.printStackTrace();
            }

            // Closing the input stream will trigger connection release
            instream.close();
        }

    } catch (ClientProtocolException e)  {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    }
    return rtnData;
}


private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}

/**
 * Custom HTTP Client accepting all SSL Certified Web Services.
 * 
 * @return n HttpClient object.
 */
public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
S1LENT WARRIOR
  • 11,704
  • 4
  • 46
  • 60
CodePrimate
  • 6,646
  • 13
  • 48
  • 86

6 Answers6

26

The only way to do this is using a CallBack. You can do something like this:

new CallServiceTask(this).execute(request, url);

Then in your CallServiceTask add a local class variable and call a method from that class in your onPostExecute:

private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{
    RestClient caller;

    CallServiceTask(RestClient caller) {
        this.caller = caller;
    }


    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];
        return executeRequest(req, url);
    }

    protected onPostExecute(Object result) {
        caller.onBackgroundTaskCompleted(result);
    }
}

Then simply use the Object as you like in the onBackgroundTaskCompleted() method in your RestClient class.

A more elegant and extendible solution would be to use interfaces. For an example implementation see this library. I've just started it but it has an example of what you want.

Saad Farooq
  • 13,172
  • 10
  • 68
  • 94
16

as @saad-farooq mentioned you can use interface for that. So you can use the Handler.Callback or define your own:

public interface ClientIF {

    public void onResponseReceived(Object result);

}

then you need to implement it in your CallServiceTask

public abstract class CallServiceTask extends AsyncTask<Object, Void, Object[]> 
    implements ClientIF
{
    Activity activity;

    CallServiceTask(Activity activity) {
        this.activity = activity;
    }

    public abstract void onResponseReceived(Object result); 

    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];
        return executeRequest(req, url);
    }

    protected onPostExecute(Object result) {
        onResponseReceived(result);
    }
}

note that the costructor is changed so you can call from every Activity class. Then make the instance of this class in your RestClient

public class RestClient
{
CallServiceTask service = new CallServiceTask() {
    @Override
    public void onResponseReceived(Object result) {
    // TODO Auto-generated method stub

    }
};

}
laplasz
  • 3,359
  • 1
  • 29
  • 40
9

You can use get() to retrieve your value/object back from AsyncTask.

new CallServiceTask().execute(parameters).get();

This will return you computed result that you are returning. But this will block your UI till your background process is completed.

Another option is to create an Interface or BroadcastReceiver that you return you the value as soon as your doInBackground() is completed. I had created a demo for the same using Interface and BroadcastReceiver you can check if from my github

Also, by using second approach your UI will not be blocked!

Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
  • 3
    But get() will also cause my application to stop and wait untill the method actually returns and since the entire point of using AsyncTask was to make the call to the web service asynchronous. – CodePrimate Feb 14 '12 at 09:01
  • 1
    I don't follow. I have my LoginController which is used by my Activity when the user presses the Log in button. LoginController then instantiates the RestClient and calls RestCLient.ExecuteCall. ExecuteCall adds the parameters to the url and then calls rtnData = new CallServiceTask().execute(parameters).get(); How will this not make the Activity sit around and wait for get() to return? – CodePrimate Feb 14 '12 at 09:18
  • Other thing you can do is use the computed result in `onPostExecute()` method to do any UI stuff. – Lalit Poptani Feb 14 '12 at 09:33
  • I may be asking like an idiot here, but how on earth does my AsyncTask know about the UI that lies 3 layers above it ? – CodePrimate Feb 14 '12 at 09:51
1
public class getOperators extends AsyncTask<Void, Void, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        items = new ArrayList();
        dialog = new ProgressDialog(PrepaidOperatorsListActivity.this);
        dialog.setMessage("Please Wait...");
        dialog.setCancelable(false);
        dialog.show();
    }



    @Override
    protected String doInBackground(Void... params) {
        BufferedReader reader;
        StringBuffer buffer;
        String res = null;

        try {
            URL url = new URL("");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setReadTimeout(40000);
            con.setConnectTimeout(40000);
            con.setRequestMethod("GET");
            con.setRequestProperty("Content-Type", "application/json");
            int status = con.getResponseCode();
            InputStream inputStream;
            if (status == HttpURLConnection.HTTP_OK) {
                inputStream = con.getInputStream();
            } else {
                inputStream = con.getErrorStream();
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));
            buffer = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            res = buffer.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        System.out.println("JSON RESP:" + s);
        String response = s;
        try {

            JSONObject ecomerrce = new JSONObject(response);
            JSONArray jsonArray = ecomerrce.getJSONArray("prepaid_operators");

            for (int j = 0; j < jsonArray.length(); j++) {
                JSONObject jsonObject = jsonArray.getJSONObject(j);

                PrepaidOperatorsPojo prepaidOperatorsPojo = new PrepaidOperatorsPojo(jsonObject.getString("operator_name"), jsonObject.getString("operator_code"), jsonObject.getString("operator_display_comission"), jsonObject.getString("operator_calculate_comission"));
                items.add(prepaidOperatorsPojo);

            }
            if (items.size() > 0) {
                dialog.dismiss();
                prepaidOperatorListAdapter = new PrepaidOperatorListAdapter(PrepaidOperatorsListActivity.this, items);
                rvPrepaidOperatorList.setAdapter(prepaidOperatorListAdapter);

            } else {
                dialog.dismiss();
                Toast.makeText(PrepaidOperatorsListActivity.this, "No Data to display", Toast.LENGTH_SHORT).show();
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
1
private void walletStatements() {
        JSONObject post_search = new JSONObject();
        try {

            post_search.put("username", getUserName);


        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (post_search.length() > 0) {
            try {
               new Getwalletstatements().execute(String.valueOf(post_search));

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }


    class Getwalletstatements extends AsyncTask<String, String, String> {
        String JsonResponse = null;
        ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            dialog = new ProgressDialog(ReportsActivity.this);
            dialog.setMessage("Please Wait...");
            dialog.setCancelable(false);
            dialog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            String JsonDATA = params[0];
            HttpURLConnection urlConnection = null;
            BufferedReader reader = null;
            URL url = null;

            try {
                url = new URL(Constant.url+"GetReports_v9.php");
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setDoOutput(true);                // is output buffer writter
                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Content-Type", "application/json");
                urlConnection.setRequestProperty("Accept", "application/json");//set headers and method
                Writer writer = new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8"));
                writer.write(JsonDATA);// json data
                writer.close();

                InputStream inputStream = urlConnection.getInputStream();//input stream
                StringBuffer buffer = new StringBuffer();
                if (inputStream == null) {                    // Nothing to do.
                    return null;
                }
                reader = new BufferedReader(new InputStreamReader(inputStream));
                String inputLine;

                while ((inputLine = reader.readLine()) != null)
                    buffer.append(inputLine + "\n");

                if (buffer.length() == 0) {                    // Stream was empty. No point in parsing.
                    return null;
                }

                JsonResponse = buffer.toString();


                return JsonResponse;

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (final IOException e) {

                    }
                }
            }


            return null;
        }

        @Override
        protected void onPostExecute(String s) {

            if (JsonResponse != null) {
                try {
                    NetworkIN.iv= Constant.iv;
                    NetworkIN.change=Constant.key;
                    NetworkIN mCrypt=new NetworkIN();
                    String decrypted = new String( mCrypt.decrypt(JsonResponse.trim()) );

                    if(decrypted!=null){
                        JSONObject ordersHistory = new JSONObject(decrypted);
                        msg = ordersHistory.getString("msg");

                        JSONArray jsonArray = ordersHistory.getJSONArray("PPDetails");

                        ordersCount = jsonArray.length();
                        //for (int j = 0; j < jsonArray.length(); j++)
                        for (int j = jsonArray.length() - 1; j >= 0; j--)
                        {
                            JSONObject jsonObject = jsonArray.getJSONObject(j);


                            String message,total_in,inType ;

                            total_in =jsonObject.getString("total_in");
                            inType =jsonObject.getString("in_type");
                            message="Congratulations your wallet is credited by Rs."+total_in+" because of "+inType;
                            ReportsPojo reportsPojo = new ReportsPojo(jsonObject.getString("reg_id"),
                                    jsonObject.getString("username"),
                                    jsonObject.getString("transfer_from"),
                                    jsonObject.getString("transfer_to"),
                                    jsonObject.getString("total_in"),
                                    jsonObject.getString("tds"),
                                    jsonObject.getString("in_amount") ,
                                    jsonObject.getString("out_amount"),
                                    jsonObject.getString("in_type"),
                                    jsonObject.getString("created_on"),
                                    message);

                            reportsItems.add(reportsPojo);
                        }
                    }else{

                    }


                } catch (JSONException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if (msg.equals("Success")) {

                    reportsAdapter = new ReportsAdapter(ReportsActivity.this, reportsItems);
                    reportsListview.setAdapter(reportsAdapter);

                } else {
                    Toast.makeText(ReportsActivity.this, "Sorry "+msg, Toast.LENGTH_LONG).show();

                }
                dialog.dismiss();
            } else {
                dialog.dismiss();
            }
        }
0
public class MyAsyncTask extends AsyncTask<String, Void, String> {  

    @Override    
    protected void onPreExecute() {
        //showProgressDialog
        dialog = new ProgressDialog(this);
        dialog.setMessage("Loading........");
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.show();
    }

    @Override    
    protected String doInBackground(String... strings) {
      HttpURLConnection httpURLConnection;
      BufferedReader reader;
      int responseCode ;

        try {
            URL url = new URL(YOUR_URL);
            URLConnection urlConnection = url.openConnection();
            httpURLConnection = (HttpURLConnection) urlConnection;
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setDoOutput(true);

            responseCode = httpURLConnection.getResponseCode();
            InputStream inputStream = httpURLConnection.getInputStream();
            if (inputStream != null) {
                if (responseCode == 200) {
                    reader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuilder buffer = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line);
                    }
                    return buffer.toString();
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override    
    protected void onPostExecute(String result) {
        progressDialog.dismiss();
        // Fetch Your Data Add Your Code Here
    }
}
Keyur Potdar
  • 7,158
  • 6
  • 25
  • 40