Android web api call without asynctask - android

I need to make an api call on click of button. So i do it following way.
btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
HttpResponse apiResponse = mySingleTonehttpClient.execute(new HttpGet(Url));
HttpEntity resEntity = apiResponse.getEntity();
InputStream instream = resEntity.getContent();
String result = convertInputStreamToString(instream);
}
}
This code is working fine if i set targetSDKVersion = 8 in Manifest file. But giving me Network mainthread error for targetSDKVersion = 11. Can anyone suggest me what should i do?
Thanks,
Jay

The reason for this is that you're not supposed to do things that can possible take a long time in the UI Thread. Because doing that will result in the UI being blocked, and you're application will be lagging.
That's why you should either use a Worker Thread or an AsyncTask to do Network IO. You can read more information about how to use them and how they can interact with the UI Thread on the Android Developer guide.

You should not do networks call on main/UI thread of Application. you may start new worker thread that will run in separate thread rather than on UI thread.

Related

Android application doing too much work on main thread

I call function processImage() on a button click and could't get the exact output needed.
processImage() function,
private void processImage() {
TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
if (textRecognizer.isOperational()) {
Log.d("IMAGE-PROCESS", "started");
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
final SparseArray<TextBlock> items = textRecognizer.detect(frame);
runOnUiThread(new Runnable(){
public void run() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
TextBlock textBlock = items.valueAt(i);
stringBuilder.append(textBlock.getValue());
stringBuilder.append("\n");
}
try {
Log.d("IMAGE-PROCESS", "finished");
Log.d("OUTPUT", stringBuilder.toString());
textView.setText(stringBuilder.toString());
} catch (final Exception ex) {
Log.i("EXC","Exception in thread");
}
}
});
} else {
Log.d("IMAGE-PROCESS", "not operational");
}
}
It logs
I/Choreographer: Skipped 86 frames! The application may be doing too much work on its main thread.
Do I need to change anything in my function?
Help me to fix this
You need to make sure that the processImage method runs on a background (non-ui) thread. It is probably running on the UI thread now, and you get the warning because it is blocking the UI thread.
There are a number of ways to do work on a background thread, from simply spawning a new thread to creating a service - you will need to research this, and decide on the best method for your particular situation. Just remember that when your background processing is complete, you need to transfer the data to the UI thread, and update the UI from the UI thread, as attempting an update from another thread will cause a crash.
My only specific advice is to not use an AsyncTask. They sound great in theory, but unless you really know how they work, they can get you into a lot of trouble. And if you really know how they work, you're fully capable of doing something more reliable.
Where is the posted code located?
Usually, even if the hard work is done on the UI thread, the screen will freeze/stutter, but eventually, the desired output is produced. I'd guess 86 skipped frames is ~1.25 s of freezing.
If your processImage() method is inside a Runnable, Callable<>, or the like, then one could understand the use of Activity.runOnUiThread(), but..
Since you are getting this message, and you did not mention this imporant detail, I'll assume that your code runs on the UI thread.
Image processing is an expensive task, and should be carried out on a background thread.
To do an kind of background work, you should use some of the ready-made classes (e.g. AsyncTask, Service, etc.), or create ones on your own (with the help of Executors or the like).
Find out how to do that here

Android TextView text updation on receiving data from Inputstream

I am coding a client-server app to test communication between two Android Bluetooth devices. On my client, I am reading data from the inputstream object.
When I checked by printing on the logcat, the data is being read successfully. However when I try to set the data to a TextView, it is not displaying.
In the following code, packetsReceivedTV is the TextView object. I am getting correct output when I print 'result' on logcat, but the text is not setting in the TextView. Is it because I am setting the text in a while (listening) loop?
while(listening){
bytesRead =instream.read(buffer);
if(bytesRead!=-1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
packetsReceivedTV.setText("Received : "+dataRead);
packetsReceivedTV.invalidate();
}
}
Even a call to invalidate() is not working.
NOTE: Occasionally when I kill the server process on one device, then the TextView on the client device updates correctly. But this does not happen always. Please help!
It's not clear which thread your code is called on, but you need to make sure these two operations are happening on different threads:
The stream polling needs to be done on a background thread. If you are not doing this, then you are not seeing text because the thread blocking on read() keeps the main thread from updating the UI elements.
The setText() method call must happen on the main (UI) thread. If you are not doing this, the text will also not display--and on some devices you will even see crashes.
I'll assume this code live in an activity (since you are trying to update UI elements). While this is not the best practice, a simple example that demonstrates the concept follows:
Thread pollingThread = new Thread() {
#Override
public void run() {
…
//This code needs to be running on a background thread
while(listening){
bytesRead = instream.read(buffer);
if(bytesRead != -1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
runOnUiThread(new Runnable() {
#Override
public void run() {
//This code needs to be posted back to the main thread.
packetsReceivedTV.setText("Received : "+dataRead);
}
});
}
}
}
};
//Start the listener thread
pollingThread.start();
This is really just meant to illustrate the basic point that the polling code must be in the background and the view code must be on the main thread.
Even a call to invalidate() is not working.
TextView calls this internally when its contents change, so you calling it is redundant.

android cancel previous http get request

I want to create an autoCompleteTextview with the suggestion from the web-service. On text change I call the web service with the text entered.
public String searchpalace_Searchtext(String serchtext)
{
String resultString = "";
try {
String searchtext = URLEncoder.encode(String.valueOf(serchtext), "UTF-8");
HttpClient Clientloc = new DefaultHttpClient();
String URL = baseUrl + "places?name=" + searchtext;
HttpGet httpget = new HttpGet(URL);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
resultString = Clientloc.execute(httpget, responseHandler);
}
catch (Exception e) {
resultString = "";
}
return resultString;
}
This function is called from the asyncTask when reach character is entered or deleted. Now when the text is entered fast the I want to cancel the pending request when the new request is arrived. How can I cancel the previous request?
You can go through each queued task and call the cancel() method. Check if the task was cancelled using isCancelled(). Do not trigger async tasks for every change in the text box. You can introduce a small delay to avoid unnecessary creation of AsyncTask objects.
You can use Android volley network tool kid for cancel the HttpRequest,
If HttpClient.execute() can be interrupted, AsyncTask.cancel(true) will do it if you pass (true). The docs don't say if it's interruptable or not, experiment.
If it doesn't then you may need to investigate the toolkit suggested in another answer.
Anyway you can check isCancelled() and not apply the result. Probably not a huge overhead once the connection has been started.
Note that, depending on Android version, sometimes multiple AsyncTasks can run in parallel (donut - honecomb) and sometimes they only run one at a time and queue up (honeycomb onwards). You can change the thread executor to allow them to run in parallel, see the AsyncTask class docs, but this will affect the rest of your app too.
Also note you're not allowed to re-use an AsyncTask once it's been run.

exception being thrown when performing http GET request from android [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Android HttpClient : NetworkOnMainThreadException
I have a php script on a server that recieves get requests, and mails out the content.
So lets say we have http://url.com/testmail.php?message=somemessage
the contents of "message" will be sent in an email.
I want my app to be able to call this script, and insert it's own mesage in the request. It will mostly be used for user feedback. I know it would be better to use POST, and if there is some android function that can natively handle mail, please enlighten me as I am new.
This is the code I have at the moment inside my main activities "onCreate", and it is generating exceptions:
HttpClient httpClient = new DefaultHttpClient();
String url = "http://someurl/testmail.php?message=eventualjavavariable";
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
ByteArrayOutputStream out = new ByteArrayOutputStream();
entity.writeTo(out);
out.close();
String responseStr = out.toString();
// do something with response
} else {
// handle bad response
}
} catch (ClientProtocolException e) {
// handle exception
} catch (IOException e) {
// handle exception
}
I also have added this line in my Android Manifest file:
<uses-permission android:name="android.permission.INTERNET"/>
What am I doing wrong?
This is my LogCat:
10-09 15:12:33.185: E/AndroidRuntime(5561): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.fragments/com.example.android.fragments.MainActivity}: android.os.NetworkOnMainThreadException
10-09 15:12:33.185: E/AndroidRuntime(5561): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
10-09 15:12:33.185: E/AndroidRuntime(5561): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
10-09 15:12:33.185: E/AndroidRuntime(5561): at android.app.ActivityThread.access$600(ActivityThread.java:130)
10-09 15:12:33.185: E/AndroidRuntime(5561): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
The application is crashing due to network activity on the main UI thread, which itself is not a very good practice, as the application can stop responding and might get killed by the OS. You should always try to do your background processing in some separate thread, and not on the main UI thread.
You need to make the HttpConnection on a background thread, maybe by using an AsyncTask.
As the name of the exception indicates, you are not allowed to perform a networking operation on the main thread. See the reference documentation.
A NetworkOnMainThreadException is thrown when an application attempts to perform a networking operation on its main thread. This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.
Some examples of other operations that ICS and HoneyComb won't allow you to perform on the UI thread are:
Opening a Socket connection (i.e. new Socket()).
HTTP requests (i.e. HTTPClient and HTTPUrlConnection).
Attempting to connect to a remote MySQL database.
Downloading a file (i.e. Downloader.downloadFile()).
If you are attempting to perform any of these operations on the UI thread, you must wrap them in a worker thread. The easiest way to do this is to use of an AsyncTask, which allows you to perform asynchronous work on your user interface. An AsyncTask will perform the blocking operations in a worker thread and will publish the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

Android HttpClient : NetworkOnMainThreadException

I have some code below:
protected void testConnection(String url) {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
ResponseHandler<String> responsehandler = new BasicResponseHandler();
try {
String connection = httpclient.execute(httpget, responsehandler);
Toast.makeText(getBaseContext(), R.string.connection_succeed, Toast.LENGTH_SHORT).show();
view_result.setText(connection);
} catch(IOException e) {
Toast.makeText(getBaseContext(), R.string.connection_failed, Toast.LENGTH_SHORT).show();
}
httpclient.getConnectionManager().shutdown();
}
and add a permission in Menifest:
<uses-permission android:name="android.permission.INTERNET"/>
But it goes an exception:
NetworkOnMainThreadException,
How can i do?
On ICS and later you cannot do network operations on the UI thread anymore. Instead you are forced to create a new thread and do your networking stuff there.
Possible tools are Android's AsyncTask and the normal Java Thread.
A good tutorial can be found here: Android Threads, Handlers and AsyncTask - Tutorial
Starting from API 11, you can not manipulate network (time-consuming) operations on main thread. Use AsyncTask or Thread to perform such operations.
You cant perform network operations in event thread, since android Api Level 11.
Instead you should do network operation in another thread than event thread, and use Handler or Asynctask to do so.
I you run your code in android 2.x and its lower version, i think this code will run perfectly. But if you run this in 3.x and it's upper version then you get an Exception. The problem is the you need to call the web service from your worker thread(AsyncTask<>) . You can not call the web service from the main thread.

Categories

Resources