Android anonymous asyncTask return value in method - java

Now in my app i try to do http parsing from url, but i didn't carry about threads, before this time...
I have such class and method:
public class TwitterOAuthHelper {
public String httpQueryToApi(String url) {
HttpGet get = new HttpGet(url);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(params, false);
get.setParams(params);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
return response;
}
}
and now i try to move this logic into asyncTask:
String result;
public String httpQueryToApi(String url) {
new AsyncTask<String,Void,String>(){
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
result = response;
return response;
}
}.execute(url);
return result;
}
but how can i return my response result value to method?
what is the best practice of doing that?

dd below method to asynctask body (below doInBackground method):
#Override
protected void onPostExecute(String result) {
// result is your returned value from doInBackground
// now we are in main ui thread
}
If you want a callback to antoher method it should be interface
public interface ResultInterface {
public void resultFromHttp(String result);
}
then your method
public String httpQueryToApi(String url, final ResultInterface ri){
//as bove
#Override
protected void onPostExecute(String result) {
if(ri!=null)
ri.resultFromHttp(result);
}
}
implement ResultInterface in your Activity/Fragment/whatever is calling httpQueryToApi, pass this as second param (ri interface)

You can't since the Task will be executed in another thread.
However you could use a callback to get the result.
Take a look at: https://stackoverflow.com/a/19520293/4299154.

Initially your function returned a string which you then further processed. Fine.
But you can not use threading like that. You can not return result from the function, because it has not been set yet (well you can but it will return null). The correct way of doing this is
public void httpQueryToApi(String url) {
new AsyncTask<String,Void,String>(){
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
return response;
}
#Override
protected void onPostExecute(String s) {
//here s is the response string, do what ever you want
super.onPostExecute(s);
}
}.execute(url);
}
You will have to shift your further processing logic to onPostExecute, no other way :)
If you want do dig a little deeper look into Future<>

1) Create separate class for you Async (not anonymous).
2) Create interface class.
public interface AsyncResponse {
void onProcessFinish(String output);
}
3) In your Async class, you need to declare it (interface : AsyncResponse):
public class MyAsyncTask extends AsyncTask<String,Void,String>(){
public AsyncResponse listener = null;
public MyAsyncTask(AsyncResponse l) {
this.listener = l;
}
{...}
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
result = response;
return response;
}
#Override
protected void onPostExecute(String result) {
listener.onProcessFinish(result);
}
}
4) In your class (where you call AssyncClass, for example in your Activity) you need to implements interface you created earlier AsyncResponse.
public class MainActivity implements AsyncResponse{
{...}
void onProcessFinish(String output){
//this you will received result fired from async class of onPostExecute(result) method.
}
}
6) now you can call in MainActivity:
new MyAsyncTask(this).execute("your_url");

Related

How do I make a call OK HttpRequest post from an isolated class using async?

I was using this in another place as async but I wanted to refactor to make it reusable, how can I reorganize the code in order to work as a consumable class?. It doesn't work if it's not async and the ip of the backend is well defined so it's not that. Any ideas?
public class HTTPRequestManager {
public static JSONArray fetchData(){
return null;
}
public static String postData(Context context, String url, String JSONData) {
return null;
}
/* #Override
protected Integer doInBackground(String... strings) {
try {
//1.create client Object
OkHttpClient client = new OkHttpClient();
//2.Define request being sent to server
RequestBody postData = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONData);
Request request = new Request.Builder()
.url(context.getResources().getString(R.string.backend_base_url) + url)
.post(postData)
.build();
//3.Transport the request and wait for response to process next
Response response = client.newCall(request).execute();
String resultData = response.body().string();
if (resultData.equals("OK")) {
} else {
//post failed
return "FAILED";
}
return resultData;
} catch (Exception e) {
Log.d("API_CONNECTION_ERROR", "Couldn't connect to the API");
return "API_CONNECTION_ERROR";
}
}*/
}
I used to have this annonymous class embeeded in another class and it works(it's a get request) but the problem is that it's not reusable in that way:
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
URL url = null;
#Override
protected void onPreExecute() {
getActivity().setProgressBarIndeterminateVisibility(true);
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
url = new URL (getResources().getString(R.string.backend_base_url) +
"api/flrcks/user/id/0/latitude/3000/longitude/300/within/9999999999999999999999999");
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
// Download complete. Let us update UI
progressBar.setVisibility(View.GONE);
if (result == 1) {
adapter = new MyRecyclerAdapter_Nearby(getActivity(), feedsList);
mRecyclerView.setAdapter(adapter);
checkAdapterIsEmpty();
} else {
Toast.makeText(getActivity(), "Failed to fetch data!", Toast.LENGTH_SHORT).show();
t.setVisibility(View.VISIBLE);
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.getJSONArray("rows");
feedsList = new ArrayList<>();
JSONArray members;
for (int i = 0; i < posts.length(); i++) {
memberList = new ArrayList<>();
final JSONObject post = posts.optJSONObject(i);
members=post.getJSONArray("members");
final FeedItem item = new FeedItem();
//for (int i = 0; i < posts.length(); i++) {
//JSONObject post = posts.optJSONObject(i);
//FeedItem item = new FeedItem();
item.setId(post.optString("id"));
item.setTitle(post.optString("name"));
item.setDescription(post.optString("description"));
item.setPrivacy(post.optString("privacy_mode_description"));
item.setInitial_date(post.optString("initial_date"));
item.setThumbnail(post.optString("thumbnail"));
item.setColor_hex(post.optString("color_hex"));
item.setTag(post.optString("tag"));
item.setDistance(post.optInt("st_distance"));
//item.setThumbnail(post.optString("thumbnail"));
for(int k=0; k <members.length();k++)
{
MemberItem memberItem = new MemberItem();
JSONObject member = members.optJSONObject(k);
memberItem.setName(member.optString("name"));
memberItem.setUsername(member.optString("username"));
memberItem.setProfile_pic(member.optString("profile_pic"));
memberItem.setIs_moderator(member.optBoolean("is_moderator"));
memberItem.setFacebookId(member.optString("facebook_id"));
memberList.add(memberItem);
}
item.setMemberList(memberList);
feedsList.add(item);
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
What changes do I need to make to put it in an isolated file to be consumed by the whole app like for example in a file called OkHTTPRequests.class???
Create an interface
public interface OnWebResponseListener {
void onWebResponse(CommonUtilities.services service, String result);
}
create a public enum for identifying service. in my case i created a CommonUtilities java where i declared
public enum services {
LOGIN
}
Your Common File
public class CallAddr extends AsyncTask<String, Void, String> {
CommonUtilities.services service;
OnWebResponseListener onWebResponseListener;
String url;
FormBody.Builder body;
Request request;
OkHttpClient client;
final static String TAG = "CallAddr";
public CallAddr(Map<String, String> data, CommonUtilities.services service, OnWebResponseListener onWebResponseListener, String url) {
this.service = service;
this.onWebResponseListener = onWebResponseListener;
this.url = url;
body = new FormBody.Builder();
for (String key : data.keySet()) {
body.add(key, data.get(key));
}
client = new OkHttpClient();
}
#Override
protected String doInBackground(String... strings) {
String result = "";
request = new Request.Builder().url(url).post(body.build()).build();
try {
Response response = client.newCall(request).execute();
result = response.body().string();
} catch (Exception e) {
Log.e(TAG,Log.getStackTraceString(e));
}
return result;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (onWebResponseListener != null) {
onWebResponseListener.onWebResponse(service, s);
}
}
}

user information Json data appears only after login ,How to parse that Json data in android

I am working on one application ,in which i got two JSon url
1.(eg.www.xxxxxxx.com )to login application (by giving username and password) and
2.(eg.www.xxxxxx xxxx xxx.com )to get logged in user information,but we can get user information only after login,before login Second url does not show anything..so how to parse second json data from first json data in android...
here is my Login.java(First json url to login)
public class Login extends Activity {
private static final String SERVICE_URI = "http://xxxxxxxxxxxxxxxxxxxx.com/login";
private static Context mContext;
public EditText edittext_username, edittext_password;
Button button_submit,reg;
public static final String TAG = "MYTAG";
Person person;
static TextView txt_Error;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mContext = this;
edittext_password = (EditText) findViewById(R.id.textEmailAddress);
edittext_username = (EditText) findViewById(R.id.txtUsername);
button_submit = (Button) findViewById(R.id.buttonLogin);
txt_Error =(TextView)findViewById(R.id.txtError);
button_submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
new MyAsyncTask().execute();
}
});
}
public String POST(String url, Person person){
InputStream inputStream = null;
String result = "";
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
String json = "";
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("username", person.getName());
jsonObject.accumulate("password", person.getCountry());
json = jsonObject.toString();
StringEntity se = new StringEntity(json);
httpPost.setEntity(se);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse httpResponse = httpclient.execute(httpPost);
inputStream = httpResponse.getEntity().getContent();
if(httpResponse.getStatusLine().getStatusCode()==200){
Intent login = new Intent(mContext, MainActivity.class);
mContext.startActivity(login);
}else{
txt_Error.setText("Sorry!! Incorrect Username or Password");
}
if(inputStream != null)
result = convertInputStreamToString(inputStream);
else
result = "Did not work!";
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
return result;
}
private class MyAsyncTask extends AsyncTask<Void, Void, String> {
ProgressDialog mProgressDialog;
private DefaultHttpClient httpclient;
private String username, password;
private HttpPost httppost;
private ArrayList<NameValuePair> nameValuePairs;
private HttpResponse response;
private HttpEntity entity;
#Override
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(Login.this, "", "Loading...");
}
#Override
protected String doInBackground(Void... params) {
httpclient = new DefaultHttpClient();
httppost = new HttpPost("http://xxxxxxxxxxxxxxxxxxxxxxx.com/login");
person = new Person();
person.setName(edittext_username.getText().toString());
person.setCountry(edittext_password.getText().toString());
return POST(SERVICE_URI, person);
}
}
private static String convertInputStreamToString(InputStream inputStream) throws IOException{
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
return result;
}
}
There are many ways to parse a JSON string into an object representation.
I see you already use JSONObject to create the body of your POST request. You can use new JSONObject(jsonString) to create an object from the response's body, after you've converted it to a String with convertInputStreamToString.
However there are better alternatives that will map the JSON to your own object model, e.g. the Gson library.
Have a look at this answer https://stackoverflow.com/a/31743324/2914666 or any of the related questions listed on the side.

How To Convert HttpURLConnection to Volley

I have google a lot but i can find solution about my issue my old code for call web service from my activity i have pass two parameter one is link means URL and second is parameters is for data i have to send to server.
problem is i have to use volley in place of following code
call retrieveStream("www.xyz.com/abc.php","data=dfsds");
public static String retrieveStream(String link, String parameters) {
try {
link = link.replace(" ", "%20");
URL url = new URL(link);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
OutputStreamWriter request = new OutputStreamWriter(
connection.getOutputStream());
request.write(parameters);
request.flush();
request.close();
String line = "";
InputStreamReader isr = new InputStreamReader(
connection.getInputStream());
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
// Response from server after login process will be stored in
// response variable.
String response = sb.toString();
// You can perform UI operations here
isr.close();
reader.close();
return response;
} catch (IOException ignored) {
ignored.printStackTrace();
}
return "";
}`
I have implement in volley
StringRequest sr = new StringRequest(Request.Method.POST,
JSONUtils.WEB_SERVICE + "pausetest.php",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// mPostCommentResponse.requestCompleted();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// mPostCommentResponse.requestEndedWithError(error);
Toast.makeText(getActivity().getApplicationContext(),
error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("allanswer", alldata);
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
AppController.getInstance().addToRequestQueue(sr);`
FYI. This is assuming that your using application/x-www-form-urlencoded, as to a multi-part-form. I believe the Volley document/videos state somewhere that it is not meant for large data transfers.
I usually make a separate class for my various distinct Volley call, especially for restful processing or reuse as follows:
package com.your.package;
public class MyVolleyRequest1 {
public void myUniqueVolleyRequest(final String _parameter1, final String _parameter2) {
if (!isNetworkAvailable()) {
apiNetworkUnAvailableMsg("No network for this function.");
return;
}
RequestQueue queue = MyVolley.getRequestQueue();
StringRetroFIXRequest myReq = new StringRetroFIXRequest(Method.POST,
getMyContext().getString(R.string.http_url),
createMyReqSuccessListener(),
createMyReqErrorListener()) {
public Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("parameter 1", _parameter1);
params.put("parameter 2", _parameter2);
return params;
}
;
};
queue.add(myReq);
}
private Response.Listener<String> createMyReqSuccessListener() {
return new Response.Listener<String>() {
#Override
public void onResponse(String response) {
setResponseSuccess(response);
}
};
}
private Response.ErrorListener createMyReqErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
setResponseSuccess(error.toString());
}
};
}
private void setResponseSuccess(String result) {
EventBus.getDefault().post(new EventBusResultsClassResponseDone(result));
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getMyContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private void apiNetworkUnAvailableMsg(String _purpose) {
String mReturn = "Internet connection unavailable. Try " + _purpose + " at a later time.";
EventBus.getDefault().post(new VolleyReturnEvent(mReturn));
}
}
I also use EventBus, so that I can loosely couple the return value(s), especially, if I decide I want to put those results into a model (pojo), like for using MVC/MVP type processing or say specialized processing of json, etc.
Optionally I also like to use OKHttp in combination Volley, here are the dependencies for gradle in Android Studio.
compile 'de.greenrobot:eventbus:2.1.0'
compile 'com.squareup.okio:okio:1.1.0'
compile 'com.squareup.okhttp:okhttp:2.2.0'
If you are just going to do restful processing Retrofit is a cool library.
Implementing in your Activity or Fragment you then define the above class and instantiate with the parameters, if needed. My example has 2 parameters. Then you implement EventBus, define the eventbus class, and include the return events via EventBus in your app, including the generic VolleyError which is returned as a separate event for error processing.
Here's a gist of what I'd put in my activity to call and then get responses from Volley/OKHttp.
#Override
protected void onResume() {
super.onResume();
EventBus.getDefault().register(this);
requestMyVolleyResponse1();
}
#Override
protected void onPause() {
EventBus.getDefault().unregister(this);
super.onPause();
}
private void requestMyVolleyResponse1() {
MyVolleyRequest1 mVolleyRequest1 = new MyVolleyRequest1();
mVolleyRequest1.MyVolleyRequest1("Parameter 1 value","Parameter 2 value");
}
public void onEventMainThread(MyVolleyRequest1Done event) {
// Your successful response processing.
}
public void onEventMainThread(VolleyReturnEvent event) {
// Your Error Processing
;
}
The EventBus return classes that you have to define (VolleyReturnEvent, MyVolleyRequest1Done) are really simple, i.e.
public class VolleyReturnEvent {
public final String message;
public VolleyReturnEvent(String message) {
this.message = message;
}
}

How to handle different method calls to web service in the same class using AsyncTask?

I'm developing an Android app, which is supposed to connect to a web service and save data into the app's local database. I'm using AsyncTask to connect to said web service from my "Login" class, which then returns the result to the processFinish method in "Login." The problem is that I need to separate the data I bring in several methods in the web service, and as far as I have seen, the result is always handled by processFinish. This is a problem because I'll need to handle the data differently depending on the method I call.
Is there a way to tell processFinish which method in my web service I called, so it can handle the result differently? I thought about sending the method's name from the web service itself as part of the result, but it feels forced, and I was hoping to do this in a cleaner way.
Here's the code I'm using:
LoginActivity.java (shortened):
public class LoginActivity extends ActionBarActivity implements AsyncResponse {
public static DBProvider oDB;
public JSONObject jsonObj;
public JSONObject jsonUser;
WebService webService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
oDB = new DBProvider(this);
}
/*Function that validates user and password (on button press).*/
public void validateLogin(View view){
ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (!isConnected){
Toast.makeText(this, "No connection!", Toast.LENGTH_LONG).show();
}else{
/* params contains the method's name and parameters I send to the web service. */
String[][][] params = {
{
{"MyWebServiceMethod"}
},
{
{"user", "myUserName", "string"},
{"pass", "myPass", "string"}
}
};
try{
webService = new WebService();
webService.delegate = this;
webService.execute(params);
}catch(Exception ex){
Toast.makeText(this, "Error!: " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
public void processFinish(String result){
try{
// Here I handle the data in "result"
}
}catch(JSONException ex){
Toast.makeText(this, "JSONException: " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
WebService.java:
public class WebService extends AsyncTask<String[][][], Void, String> {
/**
* Variable Declaration................
*
*/
public AsyncResponse delegate = null;
String namespace = "http://example.net/";
private String url = "http://example.net/WS/MyWebService.asmx";
public String result;
String SOAP_ACTION;
SoapObject request = null, objMessages = null;
SoapSerializationEnvelope envelope;
HttpTransportSE HttpTransport;
/**
* Set Envelope
*/
protected void SetEnvelope() {
try {
// Creating SOAP envelope
envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
//You can comment that line if your web service is not .NET one.
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransport = new HttpTransportSE(url);
HttpTransport.debug = true;
} catch (Exception e) {
System.out.println("Soap Exception---->>>" + e.toString());
}
}
#Override
protected String doInBackground(String[][][]... params) {
// TODO Auto-generated method stub
try {
String[][][] data = params[0];
final String methodName = data[0][0][0];
final String[][] arguments = data[1];
SOAP_ACTION = namespace + methodName;
//Adding values to request object
request = new SoapObject(namespace, methodName);
PropertyInfo property;
for(int i=0; i<arguments.length; i++){
property = new PropertyInfo();
property.setName(arguments[i][0]);
property.setValue(arguments[i][1]);
if(arguments[i][2].equals("int")){
property.setType(int.class);
}
if(arguments[i][2].equals("string")){
property.setType(String.class);
}
request.addProperty(property);
}
SetEnvelope();
try {
//SOAP calling webservice
HttpTransport.call(SOAP_ACTION, envelope);
//Got Webservice response
result = envelope.getResponse().toString();
} catch (Exception e) {
// TODO: handle exception
result = "Catch1: " + e.toString() + ": " + e.getMessage();
}
} catch (Exception e) {
// TODO: handle exception
result = "Catch2: " + e.toString();
}
return result;
}
#Override
protected void onPostExecute(String result) {
delegate.processFinish(result);
}
/************************************/
}
AsyncResponse.java:
public interface AsyncResponse {
void processFinish(String output);
}
You can use different AsyncResponse classes. Anonymous classes make this more convenient:
// in one place
webService.delegate = new AsyncResponse() {
#Override
void processFinish(String response) {
// do something
}
};
// in another place
webService.delegate = new AsyncResponse() {
#Override
void processFinish(String response) {
// do something else
}
};

Return data from AsyncTask class

How do I get the data from my AsyncTask? My MainActivity is calling the DataCall.getJSON function that triggers the AsyncTask but I am not sure how to get the data back to the original Activity.
MainActivity with call to DataCall that should return a string and save it in state_data
String state_data = DataCall.getJSON(spinnerURL,spinnerContentType);
DataCall:
public class DataCall extends Activity {
private static final String TAG = "MyApp";
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
protected void onPostExecute(String result) {
//THIS IS WHERE I NEED TO RETURN MY DATA TO THE MAIN ACTIVITY. (I am guessing)
}
}
public void getJSON(String myUrlString, String contentType) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.mywebsite.com/" + myUrlString });
}
}
modify your AsyncTask as below:
public class GetData extends AsyncTask<String, Void, String>
{
DataDownloadListener dataDownloadListener;
public GetData()
{
//Constructor may be parametric
}
public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
this.dataDownloadListener = dataDownloadListener;
}
#Override
protected Object doInBackground(Object... param)
{
// do your task...
return null;
}
#Override
protected void onPostExecute(Object results)
{
if(results != null)
{
dataDownloadListener.dataDownloadedSuccessfully(results);
}
else
dataDownloadListener.dataDownloadFailed();
}
public static interface DataDownloadListener {
void dataDownloadedSuccessfully(Object data);
void dataDownloadFailed();
}
}
and use it in your Activity
GetData getdata = new GetData();
getdata.setDataDownloadListener(new DataDownloadListener()
{
#SuppressWarnings("unchecked")
#Override
public void dataDownloadedSuccessfully(Object data) {
// handler result
}
#Override
public void dataDownloadFailed() {
// handler failure (e.g network not available etc.)
}
});
getdata.execute("");
NOTE: For the people who are reading this.
Please consider this post for the best and perhaps right implementation.
The key for me was to create a class called URLWithParams or something because AsyncTask will allow only 1 type to be sent IN, and I needed both the URL and the params for the HTTP request.
public class URLWithParams {
public String url;
public List<NameValuePair> nameValuePairs;
public URLWithParams()
{
nameValuePairs = new ArrayList<NameValuePair>();
}
}
and then I send it to a JSONClient:
public class JSONClient extends AsyncTask<URLWithParams, Void, String> {
private final static String TAG = "JSONClient";
ProgressDialog progressDialog ;
GetJSONListener getJSONListener;
public JSONClient(GetJSONListener listener){
this.getJSONListener = listener;
}
#Override
protected String doInBackground(URLWithParams... urls) {
return connect(urls[0].url, urls[0].nameValuePairs);
}
public static String connect(String url, List<NameValuePair> pairs)
{
HttpClient httpclient = new DefaultHttpClient();
if(url == null)
{
Log.d(TAG, "want to connect, but url is null");
}
else
{
Log.d(TAG, "starting connect with url " + url);
}
if(pairs == null)
{
Log.d(TAG, "want to connect, though pairs is null");
}
else
{
Log.d(TAG, "starting connect with this many pairs: " + pairs.size());
for(NameValuePair dog : pairs)
{
Log.d(TAG, "example: " + dog.toString());
}
}
// Execute the request
HttpResponse response;
try {
// Prepare a request object
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairs));
response = httpclient.execute(httpPost);
// Examine the response status
Log.i(TAG,response.getStatusLine().toString());
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
return json;
} 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 json ) {
getJSONListener.onRemoteCallComplete(json);
}
public interface GetJSONListener {
public void onRemoteCallComplete(String jsonFromNet);
}
}
Then call it from my main class like this
public class BookCatalog implements GetJSONListener {
private final String TAG = this.getClass().getSimpleName();
private String catalog_url = "URL";
private void getCatalogFromServer() {
URLWithParams mURLWithParams = new URLWithParams();
mURLWithParams.url = catalog_url;
try {
JSONClient asyncPoster = new JSONClient(this);
asyncPoster.execute(mURLWithParams);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onRemoteCallComplete(String jsonBookCatalogList) {
Log.d(TAG, "received json catalog:");
Log.d(TAG, jsonBookCatalogList);
JSONObject bookCatalogResult;
try {
bookCatalogResult = (JSONObject) new JSONTokener(jsonBookCatalogList).nextValue();
JSONArray books = bookCatalogResult.getJSONArray("books");
if(books != null) {
ArrayList<String> newBookOrdering = new ArrayList<String>();
int num_books = books.length();
BookCatalogEntry temp;
DebugLog.d(TAG, "apparently we found " + Integer.toString(num_books) + " books.");
for(int book_id = 0; book_id < num_books; book_id++) {
JSONObject book = books.getJSONObject(book_id);
String title = book.getString("title");
int version = book.getInt("price");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Although i disagree creating a new activity for that simple task there is
startActivityForResult()
to get data from another activity.
Check this. You can store your data to the Intent's extras. But still if you have a large amount of data you better off write it to a file get the result from the other activity that is done downloading and then read the file.
Serialize it and then read it. The only way I'm aware of.
Some options:
a) Make your bean implement Serializable interface, you can then pass your bean through Intent.
b) Implement Application interface (you need to make an entry in manifest), Have setter\getter method in your Application class. You can set your bean in Application from AsyncTask and later retrieve from Activity.
Sorry for answering so late, i think by this time you might have solved this problem. when i was searching for something else, i came across your question. I'm pasting a link here which might of some help for others.

Categories