Android app background thread behavior - android

I have a basic app that uses a background thread to post values to our server. The code is below. When I run the code, in debugging or normally, the following line throws a NullException (though when debugging, the value of the backgroundThread variable is set). Every subsequent run through works fine. I'm new to Android development and am unsure what is causing this discrepancy. I've included the activity function and the server post function.
backgroundThread.start();
This line is what throws the NullException. Any ideas on what is causing the problem? Thanks for any help you can provide.
--UPDATE
#jonas452 & #Rudi
I changed the code to use asynctask and am struggling with the return value. postResult is always null, and breakpoints in the postTo function never run it seems. Probably a dumb error but I'm not sure what is amiss.
--UPDATE
I worked out the issue. The AsyncTask was setup correctly, but because it's asynchronous, postResult was not immediately available. I moved my check into the onPostExecute function of the AsyncTask and everything works fine.
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
try {
//retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
final String scanContent = scanningResult.getContents();
String scanFormat = scanningResult.getFormatName();
scan_format.setText("FORMAT: " + scanFormat);
scan_content.setText("CONTENT: " + scanContent);
error.setText(null);
output.setText(null);
neonetpost post = new neonetpost();
post.execute(scanContent);
/*
Thread backgroundThread = new Thread(new Runnable() {
#Override
public void run() {
postResult = postTo(scanContent);
}
});
backgroundThread.start();
*/
if(postResult.indexOf("ERROR: ")>-1)
error.setText(postResult);
else
output.setText(postResult);
}
else{
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
error.setText("ERROR: " + e.getMessage());
}
}
public class neonetpost extends AsyncTask<String,String,String>
{
#Override
protected void onPreExecute() {
}
protected void onPostExecute(String result) {
}
protected String doInBackground(String... params) {
return postTo(params[0], params[1]);
}
public String postTo(String operation) {
return postTo(operation, "E:1");
}
public String postTo(String operation, String employee)
{
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://domain.com/page.php");
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("operation", operation));
nameValuePairs.add(new BasicNameValuePair("employee", employee));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
// According to the JAVA API, InputStream constructor do nothing.
//So we can't initialize InputStream although it is not an interface
InputStream inputStream = response.getEntity().getContent();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder stringBuilder = new StringBuilder();
String bufferedStrChunk = null;
while((bufferedStrChunk = bufferedReader.readLine()) != null){
stringBuilder.append(bufferedStrChunk);
}
postResult = stringBuilder.toString();
} catch (Exception e) {
// TODO Auto-generated catch block
postResult = "ERROR: " + e.getMessage();
}
return postResult;
}
}

Don't use Java Threads, use the AsyncTask class.
Here is a good tutorial:
http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html

the line that gives you NPE is if(postResult.indexOf("ERROR: ")>-1). You made the assumption that calling
backgroundThread.start();
made the UI Thread wait, till backgroundThread finished its execution and assign a value to postResult, but Thread are executed asynchronously. and backgroundThread.start();
makes the system spawn a new thread. When this is executed is up to the scheduler

Related

HttpURLConnection crashes application

I want to receive and send data with a web server but the code does not work
What do I do for this code to work?
Note this code inside onCreate
try {
URL url = new URL("http://myweb.com/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream Stream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(Stream);
BufferedReader b = new BufferedReader(reader);
StringBuilder s = new StringBuilder();
String str ="";
while ((str = b.readLine())!=null) {
s.append(str);
}
String data = s.toString();
TextView myText = (TextView) findViewById(R.id.Text);
myText.setText(data);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Make sure that you do network-related tasks on a separate thread in Android. Also, check that you have the INTERNET permission set.
If you want to then update the UI from another thread, you have to use
runOnUiThread (new Runnable () {
public void run() {
//update ui in here
}
}
All your code runs in Main thread which should be always used for setting up the UI and to listen for UI events such as on click listeners.
Network calls are not allowed on this thread as they might take long time. Use AsyncTask API of android which is designed for running code in separate thread.
Create a class like one below for all GET request tasks.
public class DownloadTask extends AsyncTask<String, Void, Integer> {
private String TAG = "InDownloadTask";
private DownloadCallback callback;
private String data;
public DownloadTask(DownloadCallback cb){
callback = cb;
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
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);
}
data = response.toString();
result = 1;
} else {
result = 0;
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
callback.onFinishDownload(data, integer);
}
}
Create a callback interface that we use for the above class.
public interface DownloadCallback {
public void onFinishDownload(String data, Integer result);
}
Now from your activity onCreate
String url = "http://myweb.com/";
new DownloadTask(new DownloadCallback() {
public void onFinishDownload(String data, Integer result) {
if(result == 1)
myText.setText(data);
else
myText.setText("Error");
}
}).execute(url);
If you have many network related operations, use a Network library such as Volley which will take care of this.

how can i run Webservice code in Thread?

I wanna get some data from server with this code :
public class Webservice {
public static String readUrl(String url, ArrayList<NameValuePair> params) {
try {
HttpClient client = new DefaultHttpClient();
HttpPost method = new HttpPost(url);
if (params != null) {
method.setEntity(new UrlEncodedFormEntity(params));
}
HttpResponse response = client.execute(method);
InputStream inputStream = response.getEntity().getContent();
String result = convertInputStreamToString(inputStream);
return result;
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static String convertInputStreamToString(InputStream inputStream) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
but there is some delay and pause in the application , so i wanna run this code in the Thread , but when i tried to do it , i got some error , for example i couldn't return the result or ...
Take a look at AsyncTask:
Network operations can involve unpredictable delays. To prevent this
from causing a poor user experience, always perform network operations
on a separate thread from the UI. The AsyncTask class provides one of
the simplest ways to fire off a new task from the UI thread. For more
discussion of this topic, see the blog post Multithreading For
Performance.
In the following snippet, the myClickHandler() method invokes new
DownloadWebpageTask().execute(stringUrl). The DownloadWebpageTask
class is a subclass of AsyncTask.
public class HttpExampleActivity extends Activity {
private static final String DEBUG_TAG = "HttpExample";
private EditText urlText;
private TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
urlText = (EditText) findViewById(R.id.myUrl);
textView = (TextView) findViewById(R.id.myText);
}
// When user clicks button, calls AsyncTask.
// Before attempting to fetch the URL, makes sure that there is a network connection.
public void myClickHandler(View view) {
// Gets the URL from the UI's text field.
String stringUrl = urlText.getText().toString();
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new DownloadWebpageTask().execute(stringUrl);
} else {
textView.setText("No network connection available.");
}
}
// Uses AsyncTask to create a task away from the main UI thread. This task takes a
// URL string and uses it to create an HttpUrlConnection. Once the connection
// has been established, the AsyncTask downloads the contents of the webpage as
// an InputStream. Finally, the InputStream is converted into a string, which is
// displayed in the UI by the AsyncTask's onPostExecute method.
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
... }

Progress Bar not showing while waiting for Future to complete

I'm writing some code to discover the different ways of handling asynchronisity in Android, and I've already done AsyncTask, now I've had some luck with futures in the past, but this time it's bugging me a bit...
The code itself works fine, except for the fact that the (spinning) progressbar only shows up after the download operation has completed... despite the fact that I tell the code to display it before...
here's the code:
public void startDownload(final String url) {
bar.setVisibility(View.VISIBLE); // progress bar should appear here
ExecutorService pool = Executors.newCachedThreadPool();
Gson gson = new Gson();
Future<String> promise = pool.submit(new Callable<String>() {
#Override
public String call() throws Exception {
String response = "";
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 (IOException ioe) {
ioe.printStackTrace();
}
return response;
}
});
while(promise.isDone() == false) {
// wait
}
bar.setVisibility(View.GONE); // and disappear here
try {
GitHubStatus status = gson.fromJson(promise.get(), GitHubStatus.class);
statusText.setText(status.getStatus());
bodyText.setText(status.getBody());
dateText.setText(status.getCreationDate());
} catch (ExecutionException ee) {
ee.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
// instead it briefly appears here, and then disappears again
}
For those who don't know; futures execute themselves, and thus you don't need to call a "run"or "start" method to start it
I've tried to put a Log.v("DEBUG: ", "Loading..."); in the loop that waits for it to finish, and it does print the message just fine, many times at that
I've tried without the loop, that doesn't work either, and I've even tried with a ProgressDialog that doesn't work either...
I understand that I can't update the UI thread while the UI thread is busy, but I only set the visibility before and after any of the work in the UI thread is being done, so what's wrong here? Why isn't it working?
Try following:
public void startDownload(final String url) {
bar.setVisibility(View.VISIBLE); // progress bar should appear here
ExecutorService pool = Executors.newCachedThreadPool();
Gson gson = new Gson();
Future<String> promise = pool.submit(new Callable<String>() {
#Override
public String call() throws Exception {
String response = "";
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 (IOException ioe) {
ioe.printStackTrace();
}
runOnUiThread(new Runnable()
{
public void run()
{
bar.setVisibility(View.GONE); // and disappear here
try {
GitHubStatus status = gson.fromJson(promise.get(), GitHubStatus.class);
statusText.setText(status.getStatus());
bodyText.setText(status.getBody());
dateText.setText(status.getCreationDate());
} catch (ExecutionException ee) {
ee.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
});
return response;
}
});
}
Because of
while(promise.isDone() == false) {
// wait
}
You are blocking UIThread.
FutureTask can be used to run asynchronous tasks. However, it's get() method and isDone() method will block when called.
Thus, when you try to show a ProgressBar on the UI thread that has just been blocked by FutureTask, it won't show, till probably after the FutureTask is done.
In your case, your start the ProgressBar before initiating the FutureTask call, which is correct, but once FutureTask starts, running of the ProgressBar is blocked.
To solve this, you can run a FutureTask inside an AsyncTask:
Use the onPreExecute() method of the AsyncTask to show the ProgressBar`.
Use the onProgressUpdate() method of the AsyncTask to update the progress on the ProgressBar.
Use the onPostExecute() method of the AsyncTask to hide the ProgressBar; in a worst case scenario, you can call runOnUiThread() inside the FutureTask's Callable/Runnable, to hide the ProgressBar.

AsyncTask usage on Android

I use AsnycTask to connect URL and parse the return xml:
class Connecting extends AsyncTask<String, String, String> {
private String URLPath = "";
private HttpURLConnection Connection;
private InputStream InputStream;
private boolean Return1 = false;
private int Return2 = -1;
public Connecting (String fn, String u) {
FileName = fn;
URLPath = u;
Connection = null;
InputStream = null;
Return1 = false;
Return2 = -1;
execute();
}
public boolean getReturn1() {
return Return1;
}
public int getReturn2() {
return Return2;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... aurl) {
try {
URL url = new URL(URLPath);
Connection = (HttpURLConnection)url.openConnection();
Connection.setConnectTimeout(10000);
Connection.setReadTimeout(10000);
Connection.setDoInput(true);
Connection.setUseCaches(false);
Connection.connect();
InputStream = Connection.getInputStream();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String unused) {
super.onPostExecute(unused);
try {
InputStreamReader fsr = new InputStreamReader(InputStream);
BufferedReader br = new BufferedReader(fsr);
String line = "";
while((line = br.readLine()) != null) {
//parse Reture1 and Return2
}
}
catch(Exception e) {
e.printStackTrace();
}
Connection = null;
}
}
And I use below code to call it:
Connecting con = new Connecting(Name, URL);
System.out.println("Return1 " + con.getReturn1());
System.out.println("Return2 " + con.getReturn2());
It will get false and -1, which the init value.
And connect URL after print message.
I want to get the value which has connect success and parse from the xml.
How can I do it?
AsyncTask is a class that helps to run in background. You can use it if you want to access to remote server using for example HTTP connection.
In doBackground method you have to the the "heavy" task, the one that requires time and could block the UI. When you finish at the end of doBackground you have to return the value that is the result of the task.
Then in the onPostExecute you use this result to update for example the UI.
In your case it seems to me you aren't using correctly the AsyncTask. First of all you return null in doBackground and dont set return1 and return2 as you should.
And in onPostExecute you read the response while yuo should do it in doBackground.
There's another method you can override called onPreExecute that is called before doBackground method.
In my blog i've an example how to use AsyncBackground in this case and it could help you. If you like give a look here
The AsyncTask runs (as the name says) asynchronously to the main-thread.
If you want to happen something after the task is done, you have to put that code in the onPostExecute() method.
So you may put the System.out there.

Android: TRying to show text saying sending when HttpClient sends message to server

I have a simple program that aks questions then call a php file saying if the answer was a yes or a no.
Right now it works but there is a slight pause when the information is being send. I would like some kind message or indicator to come up showing the computer is busy.
Now when I chnage the text of a textvue, before I send the data, the textView does not change, I allso tried to call it's update methed
code
case R.id.butYes:
mSend .setText("Sending your vote to server");
mSend.invalidate();
TalkToServer( mYes[mPes-1] );
UpdateScreen();
mSend .setText("");
break;
String TalkToServer( String addr)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(addr);
HttpResponse response;
String responseBody=new String("");
try {
response = httpclient.execute(httppost);
responseBody = EntityUtils.toString(response.getEntity());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseBody;
}
use AsyncTask to avoid hanging of UI when sending data to server just change your code as:
case R.id.butYes:
new SendTextOperation().execute("");
break;
private class SendTextOperation extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
//Update UI here
mSend.setText("Sending your vote to server");
mSend.invalidate();
}
#Override
protected String doInBackground(String... params) {
// Talk to server here to avoid Ui hanging
TalkToServer( mYes[mPes-1] );
return null;
}
#Override
protected void onPostExecute(String result) {
// Update screen here after talk to server end
UpdateScreen();
mSend .setText("");
}
}

Categories

Resources