doInBackground in AsyncTask for Android - java

I want to know that if a doInBackground method of a AsyncTask calls a method, for example XYZ(), Is that method also executed asynchronously?
Can we make changes to the UI in XYZ() in such a situation? Will it make the UI unresponsive?
I have a method call in doInBackground which is network intensive and requires to download an image from the web. The UI becomes unresponsive as soon as the call to that method is made. Why?
protected String[] doInBackground(String... params)
{
String[] response = new String[2];
Log.v("Background", "I am in background!");
String url = params[0];
String VoiceInput = params[1];
IsCalledOnVoiceInput = VoiceInput;
Log.v(url,url);
HttpPost httppost = new HttpPost(url);
try
{
HttpParams p = new BasicHttpParams();
HttpClient httpclient = new DefaultHttpClient(p);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
responseBody = httpclient.execute(httppost,
responseHandler);
Log.v("Thread", responseBody);
//Getting background image URL
JSONObject reader = new JSONObject(responseBody);
JSONObject coords = reader.getJSONObject("coord");
loc_latitude = coords.getString("lat");
loc_longitude = coords.getString("lon");
String imageURL="";
/////////////////////////////////////////////////////////////////////////////////
try
{
imageURL = getRandomImageURL(loc_latitude,loc_longitude);
Log.v("Image URL as recieved from getRandomImageURL", imageURL);
//Trying to convert Image from the above URL, get it and theh convert it to String
URL urlOfTheImage = new URL(imageURL);
bmp = BitmapFactory.decodeStream(urlOfTheImage.openConnection().getInputStream());
//Image successfully converted to string, ready to pass as a parameter!
response[0] = "";
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(),"There seems to be a problem with the application. Please try again later.", Toast.LENGTH_LONG).show();
}
Log.v("URL of Random Image",imageURL);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
e.printStackTrace();
}
response[1] = responseBody;
return response;
}
The method getRandomImageURL and all that code in the try block is network intensive. I can also provide its code.

The code executing in the background is run in a separate thread. Anything it does, including calling other methods, happens in that thread. Since this is not the UI thread, it's not valid to make UI calls. You have to post messages to the UI thread.

Yes, whatever you call within doInBackgroud will run asynchronously. And no you shoudn't update UI from background thread for that you have CallBackDefined(onPostExecute). Or if UI update is require you can use runOnUIThread(...) API

You can make changes to the UI only from the UI thread. In general the doInBackground() is for lengthy operations that do not update the UI or access the UI toolkit. You can periodically publish changes in state that need to be reflected in the UI (eg progress bar showing status of a download operation) by calling publishProgress().

Set time out like this...
HttpPost httppost = new HttpPost(url);
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpResponse response = httpClient.execute(httppost);

Related

Invalid use of SingleClientConnManager: connection still allocated

I want to know why does this code not execute? I'm trying to send my data from my device via POST method but there is no error. The app just finishes by itself on my device by communicating "My app was stopped.:
Here is execution:
KlientNameValue kn = new KlientNameValue(getApplicationContext());
kn.new MyAsyncTask().execute(zam.klient.getNazwa(),zam.klient.getNip(),zam.klient.getAdres());
And here is code:
public class KlientNameValue {
List<NameValuePair> KlientNameValuePairs = new ArrayList<NameValuePair>();
Context context;
public KlientNameValue(Context context) {
super();
this.context=context;
}
public class MyAsyncTask extends AsyncTask<String, Void, Void> {
#Override protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
postData(params[0], params[1], params[2]);
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(context , "Zlecenie zostało wysłane",
Toast.LENGTH_LONG).show();
}
void postData(String nazwa, String nip, String adres) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("here is my default link :)");
try { // Add your data
KlientNameValuePairs = new ArrayList<NameValuePair>();
KlientNameValuePairs.add(new BasicNameValuePair("Kli_imie", nazwa));
KlientNameValuePairs.add(new BasicNameValuePair("Kli_adres", adres));
KlientNameValuePairs.add(new BasicNameValuePair( "Kli_nr_telefonu",
nip));
httppost.setEntity(new UrlEncodedFormEntity( KlientNameValuePairs));
HttpResponse response = httpclient.execute(httppost);
//httppost.setEntity(new UrlEncodedFormEntity(
// ZamowienieNameValuePairs)); // HttpResponse response1 =
} catch (IOException e) { // TODO Auto-generated catch block
e.printStackTrace(); }
}
}
}
Error:
02-15 17:45:24.695: E/AndroidRuntime(21890): at android.widget.Toast.<init>(Toast.java:94)
02-15 17:47:19.343: W/SingleClientConnManager(22288): Invalid use of SingleClientConnManager: connection still allocated.
02-15 17:47:19.343: W/SingleClientConnManager(22288): Make sure to release the connection before allocating another one.
Invalid use of SingleClientConnManager: connection still allocated.
You are executing the http request two times that is completely wrong before you consume it. So remove the second httpclient.execute(httppost); because you have already execute this http request.
and call this
httpResponse.getEntity().consumeContent();
Above method is called to indicate that the content of this entity is no longer required. All entity implementations are expected to release all allocated resources as a result of this method invocation
public static DefaultHttpClient getThreadSafeClient() {
DefaultHttpClient client = new DefaultHttpClient();
ClientConnectionManager mgr = client.getConnectionManager();
HttpParams params = client.getParams();
client = new DefaultHttpClient(
new ThreadSafeClientConnManager(params,
mgr.getSchemeRegistry()), params);
return client;
}
use this code so that your exception of free resource and allocate or being used will not come
This exception can happen when two or more threads interact with a single org.apache.http.impl.client.DefaultHttpClient
or simply give new object to each request when and where ever you are calling you get or post http client request to interact with server to fetch the data or download the large file
like
String post_url="http://www.google.com";
DefaultHttpClient client = new DefaultHttpClient();
HttpPost httpost = new HttpPost(Post_url);
httpost.setHeader("Accept", "application/json");
httpost.setHeader("Content-type", "application/json");
HttpResponse httpResponse = client.execute(httpost);
String response= EntityUtils.toString(httpResponse.getEntity());
as you like in code to retrieve the response

How to send HttpPost every 5 secs

In a Java, I want to send HttpPost every 5 secs without waiting for the response. How can I do that?
I use the following code:
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
StringEntity params = new StringEntity(json.toString() + "\n");
post.addHeader("content-type", "application/json");
post.setEntity(params);
httpClient.execute(post);
Thread.sleep(5000);
httpClient.execute(post);
but it does not work.
Even though I lose the previous connection and set up a new connection to send the second, the second execute function is always blocked.
Your question leaves a bunch of questions, but the basic point of it can be achieved by:
while(true){ //process executes infinitely. Replace with your own condition
Thread.sleep(5000); // wait five seconds
httpClient.execute(post); //execute your request
}
I tried your code and I got the exception :
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
This exception is already logged in HttpClient 4.0.1 - how to release connection?
I was able to release the connection by consuming the response with the following code:
public void sendMultipleRequests() throws ClientProtocolException, IOException, InterruptedException {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.google.com");
HttpResponse response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
Thread.sleep(5000);
response = httpClient.execute(post);
entity = response.getEntity();
EntityUtils.consume(entity);
}
Using DefaultHttpClient is synchronous which means that program is blocked waiting for the response. Instead of that you could use async-http-client library to perform asynchronous requests (you can download jar files from search.maven.org if you're not familiar with Maven). Sample code may look like:
import com.ning.http.client.*; //imports
try {
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
while(true) {
asyncHttpClient
.preparePost("http://your.url/")
.addParameter("postVariableName", "postVariableValue")
.execute(); // just execute request and ignore response
System.out.println("Request sent");
Thread.sleep(5000);
}
} catch (Exception e) {
System.out.println("oops..." + e);
}

How to connect Android app with MySQL database through PHP

I am still a little skeptical as to how to connect my Android app to a PHP script. I saw somewhere that the following code will connect the app to the server. But I am new at android so I do not know how to really use it.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://url.to.my.app.com");
HttpResponse response = httpClient.execute(httpGet);
// handle response'
I understand that this opens a connection to an online server, but what I do not understand is what kind of response is returned by the server and how to process it. Also, I want to know how to send data through POST to the server from my app.
(If you could provide some code of your own, that would be helpful too) Thanks!
This will open a connection and send a http GET request to server. Your PHP script executes on the server side for this request and returns some contents. You can use folowing code to process the response.
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String result = RestClient.convertStreamToString(instream);
}
For POST execution you need to do something like this.
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.yoursite.com/script.php");
try {
// Add your data
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("test1","test1" ));
nvps.add(new BasicNameValuePair("test2", "test2" ));
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}

Way to set connection timeout in asynchronous post method

I am using an asynchronous post method to post some data to the server. The post is working fine, but if the server is down or unresponsive then I am getting a force close in the application.
How should I implement a timeout to the post request?
This is the class which is asynchronously posting to a particular url:
//===================================================================================================================================
//sending EmailAddress and Password to server
//===================================================================================================================================
private class MyAsyncTask extends AsyncTask<String, Integer, Double>{
#Override
protected Double doInBackground(String... params) {
// TODO Auto-generated method stub
postData(params[0],params[1]);
return null;
}
protected void onPostExecute(Double result){
if(responseBody.contains("TRUE"))
{
String raw=responseBody;
raw = raw.substring(0, raw.lastIndexOf("<"));
raw = raw.substring(raw.lastIndexOf(">") + 1, raw.length());
String [] contents = raw.split(",");
//extracting user name and user id from response
String user_name=contents[1];
String student_code=contents[2];
//save user name and user id in preference
saveInPreference("user_name",user_name);
saveInPreference("student_code",student_code);
//login is successful, going to next activity
Intent intent = new Intent(LoginActivity.this, TakeTestActivity.class);
//hiding progress bar
progress.dismiss();
finish();
LoginActivity.this.startActivity(intent);
}
else
{
//hiding progress bar
progress.dismiss();
create_alert("Attention!", "Please provide valid userid and password");
}
}
protected void onProgressUpdate(Integer... progress){
}
public void postData(String emailId,String passwrd) {
**//EDIT START**
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
HttpConnectionParams.setSoTimeout(httpParams, 10000);
HttpClient httpclient = new DefaultHttpClient(httpParams);
**//EDIT END**
// Create a new HttpClient and Post Header
//HttpClient httpclient = new DefaultHttpClient();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(LoginActivity.this);
final String url_first = preferences.getString("URLFirstPart","");
HttpPost httppost = new HttpPost(url_first+"ValidateLogin");
try {
// Data that I am sending
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("EmailId", emailId));
nameValuePairs.add(new BasicNameValuePair("Password", passwrd));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
**//EDIT START**
try
{
// Execute HTTP Post Request
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
responseBody = EntityUtils.toString(response.getEntity());
}
catch (SocketTimeoutException ex)
{
// Do something specific for SocketTimeoutException.
}
**//EDIT END**
//Log.d("result", responseBody);
}
catch (Throwable t ) {
}
}
}
//===================================================================================================================================
//END sending EmailAddress and Password to server
//===================================================================================================================================
This is how I am calling the class to execute the post request:
//sending request for login
new MyAsyncTask().execute(txtUsername.getText().toString(),txtPassword.getText().toString());
What should I do to implement a connection timeout after a particular time if the server does not respond or is not available?
Edited:
How do I notify the user using an alert that the connection has timed out? Where should I put the alert and during which condition?
Thanks in advance!
You can try this, I've set 10 sec. here...
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
HttpConnectionParams.setSoTimeout(httpParams, 10000);
HttpClient client = new DefaultHttpClient(httpParams);

Trouble POSTING from Android/Java app to PHP + MYSQL

I have been trying to get my Android App to post data to a PHP file, which then writes that data to a database, however I'm having a bit of trouble with it.
I'm getting this error, however it's not force closing or anything.
Logcat Output:
08-13 20:29:42.859: I/postData(11950): HTTP/1.1 200 OK
08-13 20:29:42.859: E/log_tag(11950): Error in http connectionjava.lang.IllegalStateException: Content has been consumed
Here is the code in question that's doing all my HTTP POST stuff, the android side of things:
SubmitWord task = new SubmitWord();
task.execute(new String[] { "http://www.hanged.comli.com/main.php" });
The above code calls this asynchronous task:
private class SubmitWord extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
String response = "";
try
{
URL = urls[0];
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("victim",myId));
nameValuePairs.add(new BasicNameValuePair("rival",newname));
nameValuePairs.add(new BasicNameValuePair("word","HELLOHOMO"));
nameValuePairs.add(new BasicNameValuePair("won","0"));
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new
HttpPost(URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse execute = httpclient.execute(httppost);
HttpEntity entity = execute.getEntity();
InputStream is = entity.getContent();
Log.i("postData", execute.getStatusLine().toString());
//HttpEntity entity = response.getEntity();
is = entity.getContent();
}
catch(Exception e)
{
Log.e("log_tag", "Error in http connection"+e.toString());
}
return response;
}
#Override
protected void onPostExecute(String result)
{
mText.setText("DONE");
}
}
Here is the PHP side of things:
<?php
/// REMOVED DATABASE DETAILS
$connect = mysql_connect("$mysql_host", "$mysql_user", "$mysql_password")or die("cannot connect");
mysql_select_db("$mysql_database", $connect)or die("cannot select DB");
session_start();
$victim = $_POST['victim'];
$rival = $_POST['rival'];
$word = $_POST['word'];
$won = $_POST['won'];
mysql_query("INSERT INTO currentgames (victim, rival, wordguess, won) VALUES('$victim', '$rival', '$word', '$won'))");
I'm fairly sure it's just the Java/Android part that I've gotten wrong, but I can't figure out for the life of me what I'm doing wrong, I have tried various different methods of POSTING data and read a number of tutorials on using HTTPOST. Maybe I'm just not understanding correctly.
The culprit is you are calling getContent(); twice.
As per javadoc
Returns a content stream of the entity. Repeatable entities are expected to create a new instance of InputStream for each invocation of this method and therefore can be consumed multiple times. Entities that are not repeatable are expected to return the same InputStream instance and therefore may not be consumed more than once.

Categories