When running 2 http AsyncTasks in parallel sometimes results are exchanged - android

I have a strange problem in my application.
I have an activity that fetches 2 or 3 things in parallel using AsyncTasks
When I simply do the following
new getMessages().execute("someID");
new getNotifications().execute("someID");
and the both AsyncTasks has code as follows:
(Both of them are identical except that the URL requested by each method is different).
Notice: I modified this code a little bit just to remove any unneeded extras like extra parameters sent in the http request
// in the other Async task "notifications" is changed with "messages"
public class getNotifications extends AsyncTask<String, Void, String> {
ProgressDialog dialog;
Integer verified = 0;
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... args) {
// getRequestsCount just perfomrs http request and grabs JSON data
String result = getRequestsCount(args[0] , "notifications");
return result;
}
protected void onPostExecute(String result) {
// This is just a method that handles the result
// When I log result I found that results are exchanged.
displayResults(result);
}
}
public String getRequestsCount(String id, String type){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new
HttpPost(GlobalSettings.apiURL + "/getcount/" + type );
Log.i("will contact",GlobalSettings.apiURL + "/getcount/" + type);
HttpResponse response = httpclient.execute(httppost);
BufferedReader reader = new BufferedReader(new InputStreamReader( response.getEntity().getContent(), "UTF-8"));
String responseMessage = reader.readLine().toString().trim();
// Response is always 1 line of JSON data
Log.i("Response for "+type,responseMessage);
return responseMessage;
}
Now my problem is that sometimes results are exchanged.
i.e. getMessages recives the JSON data requested from getNotifications
and vice versa.

Related

communication between server and android app

i try to send information from android app to server to save in data base my code runs correctly but no data saved in database and i didn't get any response. i don't know where is the mistake in my code
private class postData extends AsyncTask<String, Void, String> {
// private final ProgressDialog dialog = ProgressDialog.show(getActivity(), "",
// "Saving data to server. Please wait...", true);
#Override
protected String doInBackground(String... params) {
// perform long running operation operation
// SharedPreferences settings = context.getSharedPreferences(PREFS_FILE, 0);
//String server = settings.getString("server", "");
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://phone.com/request_job");
String json = "";
String responseStr="";
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("ticket", "welcome"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
try {
httpclient.execute(httppost);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Execute HTTP Post Request
// ResponseHandler<String> responseHandler=new BasicResponseHandler();
//String responseBody = httpclient.execute(httppost, responseHandler);
// if (Boolean.parseBoolean(responseBody)) {
// dialog.cancel();
// }
HttpResponse response = httpclient.execute(httppost);
responseStr = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
// TODO Auto-generated catch block
Log.i("HTTP Failed", e.toString());
}
return responseStr;
}
protected void onPostExecute(String responseStr) {
super.onPostExecute(responseStr);
Toast.makeText(getActivity(),responseStr,Toast.LENGTH_LONG).show();
if(responseStr.equals("true")){
// Update your Button here
Toast.makeText(getActivity(),"donefinally",Toast.LENGTH_LONG).show();
}
}
}
my code in server
public function check_user(Request $request){
$ticket = new ticket;// this line responsible to set data in database
$ticket->ticket = $request->ticket;
return response()->json(['data','true']);
}
}
In your server, do
$ticket = new ticket;// this line responsible to set data in database
$ticket->ticket = $request->ticket;
$ticket->save(); //<-- this line will save
Or in one go
$ticket = Ticket::create([
'ticket' => $request->ticket
]);
...
Now, make sure you call your ticket class properly. Not sure whether it's capital T (Ticket) or lowercase (ticket).
Edit
Since it's not working, you need to debug it step by step to see where the bottleneck is. First, in your function, simply do
return response()->json($request->ticket);
//This will prove that the request makes it to the server
Once you are sure you request makes it to the server, try to manually save something like
Ticket::create([
'ticket' => 'random string'
]);
You can call this function directly from your browser to test if it works. If nothing is saved in the db, make sure you have a $fillable array in your model and that you can connect properly to the db.

AsyncTask sanity check

I've been going over various Asynctask tutorials and examples, but I'm still a little confused. If I want to issue 3 web requests and return their response
like:
//example
String[] response = new String[3];
response[0] = webrequest("http://www.google.com"); //simple HTTP GET request
response[1] = webrequest("http://www.bing.com"); //simple HTTP GET request
response[2] = webrequest("http://www.aj.com"); //simple HTTP GET request
//sample results from request
response[0] = "blah";
response[1] = "arg";
response[2] = "meh";
To do this with an AsyncTask, would I need to implement 3 different ATs? Should I be using something else?
String[] response = new String[3];
webCreate sample = new webCreate();
try{
response[0] = sample.execute("http://www.google.com").get().toString();
response[1] = sample.execute("http://www.google.com").get().toString();
response[2] = sample.execute("http://www.google.com").get().toString();
}
catch (Exception sampleMsg)
{}
public class webCreate extends AsyncTask<String, String, String> {
}
protected String doInBackground(String... params) {
// String url=params[0];
String webRequestResponse = null; //the
// web request
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
return reponse;
}
I know I could access the response data by using .get(), but then my "Async" would become "sync" lol. I feel like I should be using something other than AsyncTask, but I have no idea what that is. Please help.
Your approach is okay, from doInBackground of your AsyncTask call a function that initiates the webrequests and wait for the result with . get(). Due to the fact, that the request are then, not running on the mainUi and blocking it, I see no problem in doing so.

Write JSON response to a text view

I am authenticating an external system via a REST API. The http authentication request is of the Basic Authorization form. The response is in JSON format.
I am running this code under an AsyncTask.
url The GET url of the API.
credentials is the authentication credentials. It is a string.
response is the text view.
getmessage is a string variable.
connection = (HttpURLConnection)new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Basic" + Base64.encode(credentials.getBytes(), Base64.DEFAULT ));
// I am reading the response here,
InputStreamReader in = new InputStreamReader(connection.getInputStream());
buf = new BufferedReader(in);
getmessage = buf.readLine();
// After making the request, I am updating the response to a text view on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
response.setText(getmessage);
}
});
I am unable to write the whole JSON data to the text view. I know that buf.readline returns the response till the end of a line. Right now I am only getting a part of the JSON response, "Not Authenticated:", but I need the whole response.
How do I update the whole JSON response to the text view (response)? If I loop the data using buf.readline in a loop then where can I use it? In which thread?
If there is anything unusual in my code. Please let me know.
I would suggest you to go trough AsyncTask
private class GetDataFromUrl extends AsyncTask<URL, Integer, String> {
protected String doInBackground(URL... urls) {
connection = (HttpURLConnection)new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Basic" + Base64.encode(credentials.getBytes(), Base64.DEFAULT ));
InputStreamReader in = new InputStreamReader(connection.getInputStream());
buf = new BufferedReader(in);
StringBuilder sb = new StringBuilder();
while ((getmessage = buf.readLine()) != null) {
sb.append(getmessage);
}
getmessage = sb.toString();
return getmessage;
}
protected void onPostExecute(String result) {
// Result will be available here (this runs on main thread)
// Show result in text view here.
response.setText(result);
}
}
To understand better, as you call AsyncTask, doInBackground runs on the new thread created. Where the network call in placed and data is parsed. Now, we need to access the data on the main thread to update the TextView so override onPostExecute inside AsyncTask that is taking result as a parameter, from doInBackground. Also if you notice..
private class GetDataFromUrl extends AsyncTask<URL, Integer, String>
Here URL is the type we are passing to our AsyncTask for doInBackground
String is what we passing from doInBackground to onPostExecute
and Integer is used to show progress for another method you can override i.e onProgressUpdate .. You can read more in the documentation liked above. Hope it was helpful.
You're only reading the first line of the response with readLine(). Call that in a loop until all lines are read, and append each new line to the previous.
If i understood correcly, you are trying to read all response data line by line. Can you try the following?
#Override
protected String doInBackGround(...){
. . .
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream), 8 * 1024);
String line = "";
StringBuilder sb = new StringBuilder();
while ((line = rd.readLine()) != null) {
sb.append(line);
}
String response = sb.toString();
return response;
}
#Override
protected void onPostExecute(String response){
Textview tv = your_textview;
your_textview.settext(whatever_part_you_get_from_response);
}
Hope this helps.
Try this:
StringBuilder sb = new StringBuilder();
while ((getmessage = buf.readLine()) != null) {
sb.append(getmessage);
}
getmessage = sb.toString();
EDITED
In your code:
getmessage = buf.readLine();
in variable getmessage reads only first line of JSON. You need to read all lines and concatenate it. How to know did you read all lines or not?
Here is what documentation says about it:
public String readLine()
throws IOException
Returns:
A String containing the contents of the line, not including any
line-termination characters, or null if the end of the stream has been
reached
As you can see, you should invoke this method, save result of it into variable, and check, if variable is not null, then you have read line of JSON. If variable is null, then you have read all JSON into variable and you have completely JSON String.
StringBuilder used to avoid creating unnecessary objects, read more about it here

Android issues with AsyncTask and InputStream

I've been trying to figure this out on my own for quite a while.. by trial/error as well as research, but I just can't seem to get it figured out. I'm pretty bad with Async and network connections and stuch, so it might be something simple that I'm over looking. Anyway... I'll paste some relevant code samples and explanations.
Quick background of my problem. I'm working with the Rotten Tomatoes API for my app, and am using GSON for the parsing of their data. I was initially targeting 2.3, and this worked fine. Then I decided to have support for ICS, and of course ran into the "no network operation on the UI thread" - so I started to delve into AsyncTask.
Here is my InputStream method:
private InputStream retrieveStream(String url) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(url);
try {
HttpResponse getResponse = client.execute(getRequest);
final int statusCode = getResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(getClass().getSimpleName(),
"Error " + statusCode + " for URL " + url);
return null;
}
HttpEntity getResponseEntity = getResponse.getEntity();
return getResponseEntity.getContent();
}
catch (IOException e) {
getRequest.abort();
Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
}
return null;
}
Which was working fine in my main activity, and now is giving me issues when trying to 'convert' it into AsyncTask. I've been calling it like this:
InputStream source = retrieveStream( url parameter );
Then I tried moving that method into my AsyncTask class, and calling it like this:
private PerformMovieSearch performSearch = new PerformMovieSearch(this);
InputStream source = performSearch.retrieveStream(movieQueryUrl);
But that doesn't cut it, still get the error about performing network actions on the UI. What I need to figure out is how to call 'retrieveStream' from the AsyncTask I guess. Currently that class looks like this:
package net.neonlotus.ucritic;
[imports]
public class PerformMovieSearch extends AsyncTask<String, Void, String> {
private final Context context;
private ProgressDialog progressDialog;
public PerformMovieSearch(Context context){
this.context = context;
}
#Override
protected String doInBackground(String... urls) {
retrieveStream(urls[0]);
return null;
}
#Override
protected void onPreExecute() {
progressDialog= ProgressDialog.show(context, "Please Wait","Searching movies", true);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progressDialog.dismiss();
MyActivity.mListAdapter.notifyDataSetChanged();
}
public InputStream retrieveStream(String url) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(url);
try {
HttpResponse getResponse = client.execute(getRequest);
final int statusCode = getResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(getClass().getSimpleName(),
"Error " + statusCode + " for URL " + url);
return null;
}
HttpEntity getResponseEntity = getResponse.getEntity();
return getResponseEntity.getContent();
} catch (IOException e) {
getRequest.abort();
Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
}
return null;
}
}
The "doinbackground" is what needs to be changed... but I can't seem to find a straight way to get that working properly. I was executing using
new PerformMovieSearch(this).execute(movieQueryUrl);
I know that is a lot of stuff, potentially confusing... but if anybody knows how to essentially do the retrieveStream method asynchronously, that would be great. Like I said, Ive tried many things, did plenty of research, just could not come up with anything useful.
the point is, you didn't understand how asynctask works!
You MUST read the guide Processes and Threads: http://developer.android.com/guide/components/processes-and-threads.html
But ok, let me try help you.
On doInBackground you are correctly calling the method retrieveStream, but you are doing nothing with the stream. So, you have to process the stream and then, return it. As you said you are expecting an JSON, I'm assuming you will receive a String, so the code of your retrieveStream should like this:
public String retrieveStream(String url) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(url);
try {
HttpResponse getResponse = client.execute(getRequest);
final int statusCode = getResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(getClass().getSimpleName(),
"Error " + statusCode + " for URL " + url);
return null;
}
HttpEntity getResponseEntity = getResponse.getEntity();
String jsonString = EntityUtils.toString(getResponseEntity);
return jsonString;
} catch (IOException e) {
getRequest.abort();
Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
}
return null;
}
Look that I changed the return type to String. And maybe, you should change the name to retrieveMoviesJSON or something like this.
And you should change your AsyncTask to something like this:
class PerformMovieSearch AsyncTask<String, Void, ArrayList<Movie>>() {
#Override
protected void onPreExecute() {
progressDialog= ProgressDialog.show(context, "Please Wait","Searching movies", true);
}
#Override
protected ArrayList<Movie> doInBackground(String... params) {
String moviesJson = retrieveStream[params[0]];
JSONObject moviesJson = new JSONObject(moviesJson);
ArrayList<Movie> movies = new ArrayList<Movie>();
/*
* Do your code to process the JSON and create an ArrayList of films.
* It's just a suggestion how to store the data.
*/
return movies;
}
protected void onPostExecute(ArrayList<Movie> result) {
progressDialog.dismiss();
//create a method to set an ArrayList in your adapter and set it here.
MyActivity.mListAdapter.setMovies(result);
MyActivity.mListAdapter.notifyDataSetChanged();
}
}
And you can call as the same way you were doing.
Is it clear? Need more explanation?
[]s
Neto
What sort of behavior are you seeing that is unexpected. From scanning your code, it looks like it probably compiles and runs but I would guess that your ListAdapter never gets updated with fresh data (i.e. you're probably trying to display the results in a ListView or GridView but nothing is showing up). Is that correct? Or are you still getting the Network on Main Thread error?
You are retrieving data using your HTTP Client and then not doing anything with it. One way you could solve it is to structure your code such that:
1) Your class that extends AsyncTask has a constructor that takes a ListAdapter object
2) Your main Activity would create an instance of the AsyncTask and pass in a reference to its ListAdapter object
3) Your doInBackground method would handle all the network activity and return the result (the data you pulled from the web service) so that it gets passed down to the onPostExecute method
4) In onPostExecute, you will have the data that was returned from doInBackground, and you'll have the ListAdapter that was provided in the constructor, so parse the data, populate the ListAdapter, and invalidate it so that the list gets redrawn.
Keep in mind that AsyncTask lets you interact with the UI thread in both the onPreExecute and onPostExecute methods, so those are the only places that you can draw to the screen (i.e. populating the adapter and invalidating it so that it will redraw)

Send HttpPost with Async and get string result

I am relatively a new Android developer and I am not able to understand how to do this. I have been looking through all the forums, I made some advance but still here I am.
So, what I want to do is a common function that send a POST request to a webpage (it only sends one POST argument) and returns the result as a string.
I have the main thread here
public class AppActivity extends Activity {
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText(PostData.Result);
}
and I have my HTTPPostData asynchronous class
public class HTTPPostData extends AsyncTask<String, Long, Object> {
String Value = null;
String Result = null;
public HTTPPostData(String query) {
Value = query;
}
#Override
protected String doInBackground(String... params) {
byte[] Bresult = null;
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.mypage.com/script.php");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("cmd", Value));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
Bresult = EntityUtils.toByteArray(response.getEntity());
Result = new String(Bresult, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
}
return Result;
}
}
I want to use this function several times (inside the same Activity or share it with other Activities of the same application). I am a little bit messed up at this moment so I need your help. What I understand is that I am asking for the result before the doInBackground() is done, and I get an empty result.
Thanks in advance for your help
Regarding this:
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText(PostData.Result);
Your problem is that you're treating asynctask like it's just a regular function. It's good that you move webpage loading off the main thread, but if you depend on the result for the very next instruction, then it's not doing you much good, you're still blocking the main program waiting for the result. You need to think of AsyncTask like a 'fire and forget' operation, in which you don't know when, if ever, it will come back.
The better thing to do here would be something like:
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText("Loading...");
and then in the asynctask:
protected void onPostExecute(String result) {
txtLabel.setText(result);
}
This lets your main thread get on with doing it's business without knowing the result of the asynctask, and then as soon as the data is available the asynctask will populate the text label with the result.

Categories

Resources