This is my code
every time i touch the imageview my app waits about 5 secs and then chrashes
I have the INTERNET permission
On the server side i have a php page that reads the GET and insert it in a database
public class Home extends Activity {
ImageView lightbut;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
ImageView lightbut = (ImageView) findViewById(R.id.light);
lightbut.setClickable(true);
lightbut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("== My activity ===","OnClick is called");
// Creating HTTP client
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpGet httpPost = new HttpGet("http://192.168.0.102/HR/index.php?command=ligthsoff");
try {
HttpResponse response = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
}
});
}
A logcat would be very helpful but its probably from doing network stuff on the UI. You should move all of your network code to a background Thread such as an AsyncTask. This will easily allow you to do the network stuff in the background then update the UI if needed in functions that run on the UI.
AsyncTask Docs
Here is an answer that shows the basic structure. Basically, you call the AsyncTask from the UI such as in your onClick() then you do network operations in doInBackground() which is called when the task first starts then you can update the UI in any of its other methods.
Using the example I referenced, you would just put all of your network stuff, which looks like everything in your onClick(), inside the doInBackground() method of the example in the link. Then in your onClick() you would do something like
lightbut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TalkToServer task = new TalkToServer(); // could pass params to constructor here but might not be needed in this situation
task.execute(); // could pass in params for `doInBackground()` such as url, etc... but again maybe not needed for this situation
}
Related
This is part of my application. (You can run code below as an isolated application) On that website (url), using php language, parse some numbers from other website, and make an array and encode it to JSON array, and show.
But, with the code below (without dismiss function!) ProgressDialog appears after doInBackground.
When I add dismiss function to onPostExecute like below, it never appears. But When I set log for checking dialog window, it says that there was an dialog.
I heard that doInBackground freezes UI, but it freezes before dialog is shown.
Other similar questions have found solution, erasing .get() from mAsyncTask().execute().get(), but I don't have any get() in my code.
Boolean variable loadfinish is for waiting finishing asynctask, to show results from that website after asynctask. If I delete
while(loadFinish == false)
there, it automacally appears and disappears very well, but I can't show result immediately...
Add) I found that it takes several seconds to dialog appear after doInBackground... why?!
Add2) I've tried to move dialog codes before and after new mAsyncTask().execute(), but it doesn't work too...
public class MainActivity extends Activity {
boolean loadFinish;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = (Button) findViewById(R.id.start);
//just a button for starting asynctask
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFinish = false;
new mAsyncTask().execute();
// get and make json array to java array
while (loadFinish == false)
;
}
});
// add array to Custom_List_Data, and set custom row_adapter to listView.
// if I delete while(loadFinish == false), array with initial data is added.
}
private class mAsyncTask extends AsyncTask<String, String, String> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("asdf");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... params) {
String url = "http://songdosiyak.url.ph/MouiRate/etoos/3/main/";
String response_str = "";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
response_str = client.execute(request, responseHandler);
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
loadFinish = true;
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dialog.dismiss();
}
}
}
Sorry for my poor English language skill and thank you for reading!
As Gabe mentioned you don't need the loop, all you need is some more understanding what the async methods should do.
You introduced the result, because you want to display the result. All you have to do is to return your response_str in doInBackground. It will be then available to you as a param to onPostExecute where you can easily display it, or do whatever you need to do with it.
So to summarize:
Remove the loop
Return value response_str or whatever from doInBackground
Display value in onPostExecute
And remove loadFinish variable as its not needed at all
Hope that helps.
Because you're using an AsyncTask totally wrong. You're busy looping waiting for it to finish. NEVER do that- if you're doing that there's no point in using an AsyncTask. At any rate, the reason it won't appear is that the UI doesn't update until the UI thread returns to the event loop inside the Android Framework and runs the drawing code, which happens after onClick returns. So you won't draw until your busy loop exits, which happens after doInBackground finishes.
The solution is to remove the loop waiting for the AsyncTask to finish in your onClick. If you have logic that needs to run after it, put it in onPostExecute.
It may be worth looking into using an async library.
Using a library to help handle async callbacks can be super helpful for this as you can start the spinner, call your api, then stop the spinner in either the onSuccess function, or your success callback method in your class.
This is the one I usually use:
LoopJ's Async HTTP Callback Library
This will handle GET and POST requests with a lot of cool features such as custom timeouts, JSON format, onSuccess() and onFailure() methods, etc. There's a lot of working examples of this library too. I've used it in all my apps and haven't had any problems yet!
Hopefully this helps.
I have my Android MainActivity with its setContentView. The view is a black/blue gradient background and an ImageView. This is my onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* Activity elements
* */
ImageView rt_logo = (ImageView) findViewById(R.id.rt_logo);
/**
* Activity variables
* */
HttpGetRequest httpGetRequest = new HttpGetRequest(rt_logo);
try {
URI uri = new URI("http://www.myurl.com");
URI[] uris = {uri};
response = httpGetRequest.execute(uris).get();
[...]
}
To retrieve the code of the page, I do an AsyncTask. For debug, I use a sleep for 5 seconds.
ImageView rt_logo;
public HttpGetRequest(ImageView _rt_logo) {
rt_logo = _rt_logo;
}
#Override
protected String doInBackground(URI... uris) {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(uris[0]);
[...]
SystemClock.sleep(5000);
getString = stringBuffer.toString();
return getString;
}
My problem is that I get a white screen for 5 seconds before the black/blue gradient and the logo show, I guess after the AsyncTask.
Why can't I get it when the app launch?
Thanks.
Like Siddharth I am also a bit confused with what you are trying to do. What you are doing is not entirely wrong, which is basically to start the thread, wait 5 seconds, and then get the info from your Http request. That should not be causing the background from not appearing. But I do have a suspicion; this line:
response = httpGetRequest.execute(uris).get();
You are expecting a result. Since its a separate thread, odds are you won't have the response you think. Actually it may even be null (I wouldn't know until I see all the code). Anyways I would check that because if you are doing something that may be causing that delay with the response. It would be nice to see what the rest of onCreate does.
It is not clear what exactly you are trying to do with your sleep(). But since you have mentioned it in the doInBackground method of your 'AsyncTask' it would be executed only after the Async task has started. If you want to have a delay while you start your app, you should probably code a delay in the onCreate() method outside of the AsyncTask.
I found a way to execute AsyncTask onCreate() and still have my content.
As Andy says, MainActivity must not expect value from AsyncTask or it will wait before showing content. So in onCreate, give your activity in argument to AsyncTask and execute it.
HttpGetRequest httpGetRequest = new HttpGetRequest(MainActivity.this);
try {
URI uri = new URI("http://www.domain.com/live.html");
URI[] uris = {uri};
httpGetRequest.execute(uris);
} catch (URISyntaxException e) {
Log.e(TAG, "Wrong URI syntax : " + e.getMessage());
e.printStackTrace();
}
Then, in your AsyncTask, create an onPostExecute method. In it, finish MainActivity and call another one. If you want it to be invisible by users, disable animation on activity start.
Activity activity;
public HttpGetRequest(Activity activity) {
this.activity = activity;
}
public void onPostExecute(String response) {
Bundle bundle = new Bundle();
bundle.putString("response", response);
Intent intent = new Intent(this.activity, LiveActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.putExtras(bundle);
this.activity.startActivity(intent);
}
Send AsyncTask response to your new activity and that's it !
I've been working on an android app which regularly checks a mysql database using JSON and everything works fine with my code.
Im having trouble running this as a timer as it only runs once and then stops.
The only code i managed to get working runs the http request on the UI thread which freezes up.
Any help would be most appreciated.
Thank in advance,
#Override
protected void onCreate(Bundle savedInstanceState) {
...
checkUpdate.start();
...
}
private Thread checkUpdate = new Thread() {
public void run() {
try {
// my code here to get web request to return json string
}
String response = httpclient.execute(httppost, responseHandler);
mHandler.post(showUpdate);
}
...
}
private Runnable showUpdate = new Runnable(){
public void run(){
try{
// my code here handles json string as i need it
Toast.makeText(MainActivity.this,"New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
}
private void showja(){
Intent i = new Intent(this, JobAward.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
As #Raghunandan suggested, the standard way to perform work in the background on Android, and then modify the UI when that work is done, is using AsyncTask.
First define a new subclass of AsyncTask:
private class JsonRequestTask extends AsyncTask<HttpUriRequest, Void, String> {
protected String doInBackground(HttpUriRequest... requests) {
// this code assumes you only make one request at a time, but
// you can easily extend the code to make multiple requests per
// doInBackground() invocation:
HttpUriRequest request = requests[0];
// my code here to get web request to return json string
String response = httpclient.execute(request, responseHandler);
return response;
}
protected void onPostExecute(String jsonResponse) {
// my code here handles json string as i need it
Toast.makeText(MainActivity.this, "New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
and then you would use the task like this, instead of your Thread:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
JsonRequestTask task = new JsonRequestTask();
task.execute(httppost);
...
}
You may run the task again by simply creating a new JsonRequestTask() and calling its execute() method.
A common practice for a simple async task like this is to make it a private inner class within the Activity class that uses it (if only one Activity needs it). You may need to change the scope of some of your activity's variables so that the inner class may use them (e.g. move local variables to member variables).
I am trying to make a simple app. Where user sees one edittext .. enters some text in it.. and then press send... then the server on laptop receives that message.
Now the NetworkOnMainThread exception is giving me Headaches......the app works perfectly for 2.3.3 because there was no such thing as NetworkOnMainThread Exception that time.
Having searched a lot .. Two solutions are
Making new thread for networking OR
AsyncTask.
I tried both without any results.
Try 1: With Separate Thread:
Now what I could understand is that I had to start a separate thread. Ok. I did.
Following is my client side code.
EditText e ;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
e= (EditText) findViewById(R.id.editText1);
tv = (TextView) findViewById(R.id.textView1);
Thread startNetworking = new Thread(new NetworkThread());
startNetworking.start();
}
public void sendMessage(View v){
if(NetworkThread.sendToClient(e.getText().toString()))
tv.setText("Status : Successful");
else
tv.setText("Status : Unsuccessful");
}
sendMessage is onClick function for my send button. I have another JAVA file NetworkThread.java....
Here is a code for that :
public class NetworkThread implements Runnable{
static DatagramSocket socket;
static InetAddress add;
public void run() {
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
add = InetAddress.getByName("192.168.1.12");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean sendToClient(String message){
DatagramPacket p = new DatagramPacket(message.getBytes(),message.getBytes().length,add,4444);
try {
socket.send(p);
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
}
This is still doesn't work. I first want to exhaust this first try then I will move onto asking here about AsyncTask and what I have tried. So for time being please help me achieve this simple task of sending and receiving a string.
Unfortunately, having sendToClient() defined in the same class as NetworkThread doesn't mean that it will run on your network-specific thread. The sendToClient() method will still run on your main (UI) thread because it's being called from your onClick() method. UI callbacks, such as onClick(), are always processed on the UI thread.
I would recommend using an AsyncTask as it enables you to send arbitrary data (such as your message parameter) to the background/network thread before it executes. Continuing to use Runnable and Thread will require extra machinery to synchronize the execution of your UI and network threads, and these challenges are handled behind the scenes by AsyncTask.
I have a piece of code that sets some network IP cameras parameters by simply calling some URLs. URLs are (to simplify) in this format "http://mydomain.com:portnumber/setalarm.cgi" and I use a normal HttpGet / HttpResponse mechanism to call URL and get result status (200 if it is good, other if bad).
Now: as URL to be called are 8 or more, in sequence (I use for loop), I would like to display a progress bar (or the simple progress indicator) to let the user know that the different URL calls are being performed. When all of the 8 calls are done, I would like a new Actity to be displayed with the result (OK, or KO with the list of KO cams).
I've tried many solutions, found on this site, but none of those where successful (Threads, progressbar , dialog bar, Asynchronous task, etc.). Either I get exceptions, or the bar does not show, or the new Activity display before the completion of the process.
Could anyone help ? This is the relevant part of my code now:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
// ON button
Button myButton1 = (Button) findViewById (R.id.button1);
myButton1.setOnClickListener(new OnClickListener() {
public void onClick(final View arg0) {
intGoodCamera = 0;
intBadCamera = 0;
for (int i = 0; i<intNumCam; i++) {
System.out.println (intStartingPortNb+i);
String myurl = strIPAddress + ":" + (intStartingPortNb+i) + strSuffixSetAlarmOn;
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(myurl);
HttpResponse response = null;
try {
response = httpClient.execute(httpGet, localContext);
System.out.println (response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() == 200)
intGoodCamera++;
else {
intBadCamera++;
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println ("OK: "+intGoodCamera + " KO: "+ intBadCamera);
Intent nextIntent = new Intent(MainActivity.this, Results.class);
MainActivity.this.startActivity(nextIntent);
}
});
.....
Just Use AsyncTask..
Place starting ProgressDialog code in onPreExecute() of AsyncTask..
Place your HttpRequest in doInBackGround() of AsyncTask.
Now remove (dismiss) ProgressDailog in onPostExecute() and
Start a new Activity in onPostExecute().
Simple..
I think your problem here is that you put http requests in UI thread, which is forbidden since Android 3.0
I think you should check this link:
httpGet Request error
I would recommend reading about AsyncTask. Take a look at this tutorial (http://www.vogella.com/articles/AndroidPerformance/article.html#asynctask) for a good example of almost exactly what you are trying to do.
You cannot do operations which takes more than 5 seconds in UI thread.
For that Use Async Task
The call the next http request after the completion of the previous one (Since the task is running Async) and update the progress bar.
It is good to use a listener interface for handling the async task completion
Steps :
Call the async task to have first http request.
When the task completes, from the post execute section, write code to invoke its corresponding completion listener.
From completed listener, start the next http request and update the progress.
continue as long all the requests are made.