i wrote those threads:
How to manage multiple Async Tasks efficiently in Android
Running multiple AsyncTasks at the same time -- not possible?
but didnt find answer for my question, maybe someone can help..
I have android app which makes Login POST and getting json response,
if the Json is OK i need to POST another data to get another response.
i have extends Async Class which doing the post to the URL:
public class AsyncHttpPost extends AsyncTask<String, String, String> {
private HashMap<String, String> mData = null;
public AsyncHttpPost(HashMap<String, String> data) {
mData = data;
}
#Override
protected String doInBackground(String... params) {
byte[] result = null;
String str = "";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(params[0]);// in this case, params[0] is URL
try {
ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
Iterator<String> it = mData.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
nameValuePair.add(new BasicNameValuePair(key, mData.get(key)));
}
post.setEntity(new UrlEncodedFormEntity(nameValuePair, "UTF-8"));
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
result = EntityUtils.toByteArray(response.getEntity());
str = new String(result, "UTF-8");
}
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (Exception e) {
return null;
}
return str;
}
#Override
protected void onPostExecute(String result) {
try {
JSONArray Loginjson = new JSONArray(result);
strStt = Loginjson.getJSONObject(0).getJSONObject("fields").getString("status");
if (strStt.equals("ERR")) {
ErrorMsg("Authentication failed");
} else if (strStt.equals("OK")) {
ErrorMsg("Login OK!!!");
ClientPage();
} else {
ErrorMsg("Connection Error");
}
} catch (JSONException e) {
ErrorMsg("Connection Error");
}
}
}
Now - i need to get another POST if the status is Error. do i need to make another Async class? with the same all procedures ? the issue is only the onPostExecute part is different.. actually the "doInBackground" will be always the same..
any idea how can i easily do multiple posts in the same activity?
Firstly, since your doInBackground() code will always stay the same, I recommend you move it into a general utility class.
Beyond that, you can go one of two ways:
Create a new AsyncTask for each type of request that can call your utility class, and have its own onPostExecute()
Create one AsyncTask that has a flag in it, which can be checked in the onPostExecute() method to see what code needs to be executed there. You will have to pass the flag in in the constructor or as a parameter in execute.
You can use a parameter at AsyncHttpPost constructor/execute or global variable to indicate if it is first or second POST (by other words - a flag). Then just create and execute another instance of AsyncHttpPost in onPostExecute (only if parameter/variable is set as "first POST").
Related
I have an app that should send a the phone number and retrieve a value from the database, now I change the query and my code should retrieve values of multiple columns, So where changes should be in my code.
public class JSONTransmitter extends AsyncTask<JSONObject, Void, String>
{
HttpResponse response;
String url = "http://192.168.1.97:89/Derdeery/bankOsman.php";
private AsyncCallback asyncCallback;
public JSONTransmitter(Context context) {
// attach the callback to any context
asyncCallback = (AsyncCallback) context;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
asyncCallback.onResponse(result);
}
protected String doInBackground(JSONObject... data)
{
JSONObject json = data[0];
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 100000);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
JSONObject jsonResponse = null;
HttpPost post = new HttpPost(url);
String resFromServer = "";
try {
StringEntity se = new StringEntity("json=" + json.toString());
post.addHeader("content-type", "application/x-www-form-urlencoded");
post.setEntity(se);
HttpResponse response;
response = client.execute(post);
resFromServer = org.apache.http.util.EntityUtils.toString(response.getEntity());
Log.i("Response from server", resFromServer);
} catch (Exception e) {
e.printStackTrace();
}
return resFromServer;
}
public static interface AsyncCallback {
void onResponse(String res);
}
}
Here is something to consider:
First, in your php code (server-side), query your data perhaps separately. So for instance, you can get those that match column A and then query for those that match column B.
Generate Json for each (A and B accordingly)
Then create a single JSON object that contains the two sets of data like this:
{
"DataFromColumnA" : {},
"DataFromColumnB" : {}
}
Once you have made your HTTP request in your android code, you can get the specific data by getting "DataFromColumnA" json Object and B respectively.
I hope this helps you get your problem solved!
I am working on android app and facing a problem. The problem is that onPostExecute does not execute everytime event doInBackground execute successfully and return true. My code is given below. Please help me I am in big trouble.
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
msgtouser.setText("Wait we are fetching HOT DEALS...");
}
#Override
protected Boolean doInBackground(String... urls) {
Boolean retValue = false;
try {
HttpResponse response = null;
String CSRFTOKEN = "";
// Create a new HttpClient and Post Header
DefaultHttpClient httpClient = new DefaultHttpClient();
// Access POST route using CSRFTOKEN
HttpPost httppost = new HttpPost(urls[0]);
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("_token", CSRFTOKEN));
nameValuePairs.add(new BasicNameValuePair("uid", urls[1]));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
response = httpClient.execute(httppost);
} catch (Exception e) {
ccode.ErrorReporting(e);
}
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("hotdeal");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
HotDeals objHD = new HotDeals();
objHD.setId(object.getInt("offid"));
objHD.setName(object.getString("line1"));
objHD.setLocation(object.getString("line3"));
objHD.setDistance(object.getString("dist"));
objHD.setOffer(object.getString("line2"));
objHD.setImage(object.getString("ban"));
dealsList.add(objHD);
}
retValue = true;
}
} catch (Exception e) {
ccode.ErrorReporting(e);
}
return retValue;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
dialog.cancel();
// adapter.notifyDataSetChanged();
if (result == false && AppConstants.ISDEBUG) {
Toast.makeText(getActivity().getApplicationContext(), "Hot Deals : Network Error", Toast.LENGTH_LONG)
.show();
} else {
if (dealsList.isEmpty()) {
msgtouser.setText("Sorry, there are no HOT DEALS for the location selected by you");
} else {
msgtouser.setVisibility(View.GONE);
ListView listview = (ListView) rootView.findViewById(R.id.listhd);
adapter = new HotDealsAdapter(HotDealsFragment.this.getActivity(), R.layout.hotdeals_row,
dealsList);
listview.setAdapter(adapter);
}
}
}
}
you don't need to call super.onPostExecute() (not sure if it could be causing problems, but isn't needed) If this isn't the problem then below...
I "think" I know what the problem is... and we've ran into it before... IF this is happening when you rotate the phone (or any other hardware change)...
Then the problem is that the return value of the doInBackground() doesn't get actually passed to the onPostExecute() and you will get a null passed in. (if the hardware change happened during the doInBackground())
However, that doesn't appear to be 'exactly' what you are having from your description. 'onPostExecute()' not running at all is odd. You should put a logcat statement as the very first thing in the method and see if that gets logged.
Because 'false' is the default value of boolean so it could be what you are describing where you don't have the 'else' part ever run, but you should be getting the toast then...
So log in two places (1) just before the return of doInBackground and (2) at the very beginning of the onPostExecute() and see if the values 'agree'
I'm trying to see how works an Asynctask class in android. In particular i want reveal in real time the status of the class for see when it is running and when it has finished. For do this, i have created a class that extend the main activity and another class that is the asynctaks class.
This is my main class:
public class PhotoManagement extends Activity{
private String numberOfSelectedPhotos;
private Bitmap currentImage;
private String initConfiguration = "http://www.something.com";
private String response;
private ArrayList<String> formatPhotoList = new ArrayList<String>(); //create a list that will contains the available format of the photos downloaded from the server
private ArrayList<String> pricePhotoList = new ArrayList<String>(); //create a list that will contains the available price for each format of the photos
DownloadWebPageTask webPage = new DownloadWebPageTask();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume(){
super.onResume();
webPage.execute(initConfiguration);
if(webPage.getStatus() == AsyncTask.Status.PENDING){
Log.i("STATUS","PENDING");
}
if(webPage.getStatus() == AsyncTask.Status.RUNNING){
Log.i("","RUNNING");
}
if(webPage.getStatus() == AsyncTask.Status.FINISHED){
Log.i("","FINISHED");
}
}
}
As you can see i want only see the passages of the status with a simple log.
And here there is the asynctask class.
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient(); //create a new http client
HttpGet httpGet = new HttpGet(url); //create a new http request passing a valid url
try {
HttpResponse execute = client.execute(httpGet); //try to execute the http get request
InputStream content = execute.getEntity().getContent(); //prepare the input stream to read the bytes of the request
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s; //until is present a line to read, the response variable store the value of the lines
}
} catch (Exception e) {
Log.i("MyApp", "Download Exception : " + e.toString()); //Print the error if something goes wrong
}
}
return response; //return the response
}
#Override
protected void onPostExecute(String result) {
result = doInBackground(initConfiguration); //take the result from the DownloadWebPageTask class
result = result.replace("null", "");
Log.i("RESULT",""+result);
//find the price and format value from the result using XmlPullParser
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new StringReader ( result ) );
int attributeNumber = xpp.getAttributeCount();
int eventType = xpp.getEventType();
String currentTag = null;
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG) {
currentTag = xpp.getName();
if (currentTag.equals("product")){
xpp.getAttributeValue(null, "name");
formatPhotoList.add(xpp.getAttributeValue(null, "name"));
Log.i("FORMAT PHOTO",""+xpp.getAttributeValue(null, "name"));
}
}
eventType = xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
Log.i("","ERROR XML PULL PARSER");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i("","ERROR IOEXCEPTION");
}
}
}
}
As you can see i have implemented also the method onPostExecute that should be called when the asynctask method has finished to execute the instructions right?
So at this point i don't understand why my log RUNNING and my log FINISHED never appear on the log cat.
What i'm doing wrong?
I'm tried to follow this topic Android, AsyncTask, check status? but in my case it isn't working.
Thanks
Problem :
You are creating object like
DownloadWebPageTask webPage = new DownloadWebPageTask();
But you are calling asynctask on different object,
new DownloadWebPageTask().execute(initConfiguration);
Solution :
It should be like
webPage.execute(initConfiguration);
#Override
protected void onResume(){
super.onResume();
new DownloadWebPageTask().execute(initConfiguration);
here do like this
#Override
protected void onResume(){
super.onResume();
webPage.execute(initConfiguration);
You didn't implement webPage.execute(), add it
Most probably the task hasn't finished or even started yet. As you probably know the AsyncTask is doing it's (background) work on a different thread, so your onResume is running in parallel with it. You can either use the task's get() method to wait for it to finish and get the result of the doInBackground() method and then query for it's status or notify your activity from the task's onPostExecute() method to let it know (and log) that it has finished. I don't recommend you the first option because it will actually block the UI thread and will make your usage of AsyncTask pointless.
I am currently using android-async-http library to send a post/get requests. I didn't have any problem before but now i realize that it gives me timeout error if i send this request without image data. (There is no error if i send exact same request by putting image data as well.)
RequestParams params = new RequestParams();
params.add("mail", mail.getText().toString());
params.add("password", pass.getText().toString());
try {
if (!TextUtils.isEmpty(imagePath))
params.put("image", new File(imagePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
AsyncHttpClient client = new AsyncHttpClient();
client.setTimeout(60000);
client.post("some_url", params, myResponseHandler);
What is the reason of this?
Thanks in advance.
After comparing requests and responses, i found out that the case was content-type. With image it was posting multipart, and without it something else.
So i got into RequestParams class in library, and made these changes. Now it works fine. For further troubles i am posting changes that i've made.
I put a flag to determine this request should post as multipart or not:
private boolean shouldUseMultiPart = false;
I created a constructor to set this parameter:
public RequestParams(boolean shouldUseMultiPart) {
this.shouldUseMultiPart = shouldUseMultiPart;
init();
}
And then on getEntity() method i applied these lines:
/**
* Returns an HttpEntity containing all request parameters
*/
public HttpEntity getEntity() {
HttpEntity entity = null;
if (!fileParams.isEmpty()) {
...
} else {
if (shouldUseMultiPart) {
SimpleMultipartEntity multipartEntity = new SimpleMultipartEntity();
// Add string params
for (ConcurrentHashMap.Entry<String, String> entry : urlParams
.entrySet()) {
multipartEntity.addPart(entry.getKey(), entry.getValue());
}
// Add dupe params
for (ConcurrentHashMap.Entry<String, ArrayList<String>> entry : urlParamsWithArray
.entrySet()) {
ArrayList<String> values = entry.getValue();
for (String value : values) {
multipartEntity.addPart(entry.getKey(), value);
}
}
entity = multipartEntity;
} else {
try {
entity = new UrlEncodedFormEntity(getParamsList(), ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return entity;
}
Here is my issue:
I have a list of values which I retrieve from server.
These values fill ListView in the UI.
I cannot continue loading the View and showing it to user until the list is full.
Since Android forces me to make http calls in separate thread, my question is how do I create 1 class that does the httprequests and in the calling class I wait until I get response from the HttpRequest and only then I proceed loading the View?
Right now I have this class that does the requests:
public class WapConnector extends AsyncTask<String, String, String>{
private static final String TAG = "WapConnector";
private String html = "";
private Handler mHandler;
private String server = "http://....whatever";
private String callUrl = "/api/";
private String params = "login?u=Admin&pw=234234&format=json";
private int _callstate = 1;
#Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
String fullUrl = "";
Log.i(TAG,fullUrl);
if(params.length() > 0){
fullUrl = server + callUrl + params + "&alf_ticket=" + Globals.getInstance().getTicket() + "&udid=" + Globals.getInstance().udid() + "&phoneNumber=" + Globals.getInstance().phoneNumber();
}
else{
fullUrl = server + callUrl + "?udid=" + Globals.getInstance().udid() + "&alf_ticket=" + Globals.getInstance().getTicket() + "&phoneNumber=" + Globals.getInstance().phoneNumber();
}
Log.i(TAG,fullUrl);
response = httpclient.execute(new HttpGet(fullUrl));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
Log.i(TAG,responseString);
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
//TODO Handle problems..
} catch (IOException e) {
//TODO Handle problems..
e.printStackTrace();
}
return responseString;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i(TAG + "onPostExecute",result);
activity.getClass().handleResponse();
//main load
JSONObject jobj;
JSONObject jvalue;
try {
jobj = new JSONObject(result);
if(_callstate == 1){
jvalue = jobj.getJSONObject("data");
String ticket = jvalue.getString("ticket");
Log.i("loginwap",ticket);
Globals.getInstance().setTicket(ticket);
_callstate = 2;
}
else{
jvalue = jobj.getJSONObject("countries");
JSONArray countries = jvalue.getJSONArray("countries");
}
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And this is how I make calls from Parent classes:
WapConnector wap = new WapConnector();
wap.setCallUrl("/anyurl/");
wap.callstate(3);
wap.setParams("");
wap.execute("");
Now my issue is that since the request runs in thread, once I call wap.execute(), my Activity continues to load, but I want it to wait until I get response, parse the response and only then continue to load.
thanks everyone for replies.!!!
Pass in a context to your class from the activity you are calling it from. Overload the onPreExecute() to show a ProgressDialog and then overload onPostExecute() to hide the ProgressDialog. This gives you blocking while letting the user you are loading.
There is a kinda hacky way to get more control. If you want to keep the AsyncTask as a separate class but allow it to update UI elements in another Activity, define a Handler in that Activity and then pass it in the constructor of the the AsyncTask. You can then send a message in the onPostExecute() method of your AsyncTask to the handler to tell it to update the UI. You will need to make sure the handler is properly handling the message your AsyncTask is sending back. Could be a little cleaner, but it works and will allow you to reuse an asyncTask that makes a network call across activities.