I am trying to trigger a HTTP post request on each button click to get some data from a webservice in android. I have created an async task to send the http request. My code is as follows :
Activity
public void sendHttpRequest(View view){
//gets called on button click
new MyHttpRequestTask(this).execute();
}
MyHttpRequestTask
public class MyHttpRequestTaskextends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void result) {
//Show received data
super.onPostExecute(result);
}
#Override
protected Void doInBackground(Void... arg0) {
//Send http request
return null;
}
}
I am having two problems, one is that the onPostExecute method is not being fired and the other is, if I press the button second time or multiple times, the task is not being executed. But somehow I think that onPostExecute method not being called is the reason for the task not being executed on second time. So, what am I doing wrong? How can I get rid of these issues? Thanks
Here is the full doInBackground method
#Override
protected Void doInBackground(Void... arg0) {
Looper.prepare();
GpsHelper gpsHelper = new GpsHelper();
LocationHelper locationHelper = new LocationHelper(mContext);
gpsHelper.turnGPSOn();
String location = locationHelper.getMyCurrentLocation();
...
String rawHtml = HttpHelper.sendPostRequest(postUrl, postParams);
HtmlHelper.processRawHtml(rawHtml);
Looper.loop();
return null;
}
It gets the current location using GPS, then the current address and posts them to a webservice, then the response from webservice is parsed and processed. Is the problem due to the GPS ?
Here you should call your method like
public MyHttpRequestTask myHttpRequestTask;
public void sendHttpRequest(View view){
//gets called on button click
//Status.PENDING -- got the status when your asynch task not run yet with same instance
//Status.RUNNING -- whether it running
if(myHttpRequestTask.getStatus() == Status.FINISHED || myHttpRequestTask.getStatus() == Status.PENDING){
myHttpRequestTask = new MyHttpRequestTask(this).execute();
}
}
if your asynch task is in running task then no need to start it again and it would not be start.
it would be feasible if you create a new object when your status of asynchtask is either finish or pending. and please put the log or system out in your post method so you can easily identify it whether it will be called. please check again.
Please do this in your code,
public void sendHttpRequest(View view){
//gets called on button click
new MyHttpRequestTask().execute();
}
public class MyHttpRequestTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
//Send http request
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//please put your code here.
}
}
try this code, and if any issues then please mention here.
After couple of days of head banging and debugging, I finally figured it out.
The onPostExecute was not being executed because of the GPS codes. Apparently, starting gps started few threads which were not terminated and hence onPostExecute was not being executed.
Related
I get a username from a login screen. I want to make a call to a web service to validate user. The problem is that I am getting the error:
android.os.NetworkOnMainThreadException
I know why I'm getting it. I'm making a network call on the main thread.
The problem is that I don't want to use AsyncTask. I don't want the user to be able to sign in BEFORE I get a response from the web service.
How do I get around this?
You can start an AsyncTask when the user opens the first Activity, with a "Waiting" fragment. When the AsyncTask finished, you can switch to the "Login" fragment.
You can use AsyncTask as shown below to sign in only when you get a response from the web service.
class SignInAsyncTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Display a progress bar saying signing in or something
}
#Override
protected String doInBackground(Void... params) {
// Call your web service
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Sign in if the credentials are okay, otherwise show some error message to the user
}
}
If you really don't want to use AsyncTask you could start a new Thread and put your logic here.
new Thread(new Runnable() {
public void run() {
// Sign in validation
}
}).start();
I am trying to get along with AsyncTask..
what my problem was that i was building a table of textviews dynamically, based on the output of a procedure.. But then i figured that by using asynctask i can do it in a more efficient way..So, what i did is as follows:
private class DisplayReport extends AsyncTask<Void, Void, Boolean>{
protected void onPreExecute(){
//Message -- "Please wait while the Report Loads..."
}
#Override
protected Boolean doInBackground(Void... params) {
//Here i fetch the data from the procedure via a web service
//parse the result of web service and set a bool variable true or false based on whether the dataset fetched is empty or not.
}
protected void onPostExecute(Boolean value){
if(value == true){
"Please try again later!!"
}
else{
runOnUiThread(GenTable);
}
}
private Runnable GenTable = new Runnable(){
public void run(){
try {
displayReport(result); // in this method i build the table.
} catch (Exception e) {
ad.setTitle("Error..");
ad.setMessage(e.toString());
}
}
};
}
the above async class is an inner class in my main class which extends activity.
and this is how i am executing the asynctask..
DisplayReport dr = new DisplayReport();
dr.execute();
now when i debug, i get the "source not found" error on dr.execute()..
i tried searching a lot on the net, but i simply cannot find out anything concrete. Also, please let me know if my approach is incorrect..
this question might seem very silly, but i am new to android and java as well and any help would be really great..
Thanks!
Execute is going to start a new thread. You don't want to debug into it. Instead, put breakpoints in onPreExecute, doInBackground, and onPostExecute and you can see when each of those gets called.
onPostExecute is already being run in the UI thread, so you should not create another runnable for it. Just make your onPostExecute like this:
protected void onPostExecute(Boolean value){
if(value == true){
String message = "Please try again later!!";
// Do something here with your message
}
else{
displayReport(result);
}
}
my data is load from the internet, so I use the AsynTask(). execute() method to open a progressDialog first, then load the data in the background. it works, however, sometimes it takes too long to load the data so I want to cancel loading, and here is the problem: when I click back button the dialog dismiss but after it finish loading at the background, it start to do whatever it supposed to do after loading, e.g. start a new intent.
is there any way I can cancel the loading properly???
new GridViewAsyncTask().execute();
public class GridViewAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog myDialog;
#Override
protected void onPreExecute() {
// show your dialog here
myDialog = ProgressDialog.show(ScrollingTab.this, "Checking data",
"Please wait...", true, true);
}
#Override
protected Void doInBackground(Void... params) {
// update your DB - it will run in a different thread
loadingData();
return null;
}
#Override
protected void onPostExecute(Void result) {
// hide your dialog here
myDialog.dismiss();
}
Call mAsycntask.cancel(); when you want to stop the task.
Then
#Override
protected Void doInBackground(Void... params) {
// update your DB - it will run in a different thread
/* load data */
....
if (isCancelled())
return;
/* continue loading data. */
return null;
}
Documentation:
http://developer.android.com/reference/android/os/AsyncTask.html#isCancelled()
Declare your AsyncTask like asyncTask = new GridViewAsyncTask();
Then execute it as you did it before (asyncTask.execute();) and to cancel it:
asyncTask.cancel();
Add the onCanceled method to your AsyncTask class and override it. Perhaps to show a Log or something else!
#Override
protected Void onCancelled () {
// Your Log here. Will be triggered when you hit cancell.
}
The goal:
Using Google App Engine server and Android client, I'm trying to put on the Google map at the Android client Users overlays. Every 30 seconds I'm polling the server and getting Vector that contains users and adding it to the map.
Current status:
I'm dong all that using in one new thread, So after running the app I got:
weird behaviors(delayed overlays, multiple overlays) and after that crushed with ConcurrentModificationException.
After reading a bit i figured out that I need to work with AsyncTask.
Correct me if I'm wrong,But I understand that everything done in the Activity at at onCreate is "running" in UIhread so I need to put the "Logic" (All the Network handling) in doInBackground and all the UI Handling like putting overlays on the map in onPostExecute.
My Question are:
1) In the current status I'm doing:
new Thread()
{
#Override
public void run()
{
super.run();
while(true)
{
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
putNewOnlineUserOnTheMap();
}
}
}.start();
What is the right way to convert this To AsyncTask?
Do I poll the server still using new thread in the doInBackground or there is right way to do this?
2) Is there a specific list of what counts as UI to put in onPostExecute or any concepts list?
In my case I guess that in need to put putNewOnlineUserOnTheMap() in onPostExecute.
Thanks.
Something similar to the following:
class UpdateTask extends AsyncTask<Void, Vector, Void>{
#Override
protected Void doInBackground(Void... params) {
// this is running in a background thread.
while (!isCancelled()) {
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
// send the result back to the UI thread
// onProgressUpdate will be called then
publishProgress(responseFromServer);
}
return null;
}
#Override
protected void onProgressUpdate(Vector... values) {
// this is executed on the UI thread where we can safely touch UI stuff
putNewOnlineUserOnTheMap(values[0]);
}
}
You can't use the result of the task since the task is finished then. But you can use the progress publishing mechanism to get periodic results. If you use it like that and do the modification on the UI thread you should not get ConcurrentModificationException because you do the modifications on the one thread that can safely modify the UI.
One thing to note here: create new instances of your Vector in the background thread and then use it to update the UI. But don't touch the same object afterwards in the backgroundthread. That way you don't need any synchronization since after the background thread sends it away it is only the UI thread that touches it. (and you could use a simple ArrayList instead of a Vector)
AsyncTask uses generics and varargs.The parameters that are passed to the asyntask are . TypeOfVariableArgumentsParameters is passed into the doInBackground(), ProgressParam is used for progress information and ResultParam must be returned from doInBackground() and is passed to onPostExecute() as parameter.
example:--
protected class ParsingTask extends AsyncTask> {
private ProgressDialog loadingDialog = new ProgressDialog(JsonParserActivity.this);
protected void onPreExecute() {
loadingDialog.setMessage("loading app store..");
loadingDialog.show();
}
#Override
protected ArrayList<Items> doInBackground( Context... params ) {
// do ur process here.
return result;
}
if (!this.isCancelled()) {
}
return result;
}
#Override
protected void onProgressUpdate(String... s) {
super.onProgressUpdate(s);
Toast.makeText(getApplicationContext(), s[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute( ArrayList<Items> response ) {
//if u r dealing with list view and adapters set the adapter here at the onPostExecute()
loadingDialog.dismiss();
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(getApplicationContext(), "The operation was cancelled", 1).show();
}
}
You can use AsyncTask like below. Hope this will help you..
Class YourClass{
void YourClass(){
NetworkTask nT = new NetworkTasK();
nT.execute();
}
}
protected class NetworkTask extends AsyncTask<Void, String, Boolean>
{
#Override
protected Boolean doInBackground(Void... params)
{
try
{
String response;
while(keepreceiving)
{
response = in.readLine();//Prog Counter stops here until getting i/p.
if(response != null)
yourFunctionForResponse(response);
}
}
catch (Exception ex)
{
}
return null;
}
private void yourFunctionForResponse(String response){
//things to do....
}
}
You may also try runOnUiThread(Runnable action) along with this to implement your work.
I am using AsyncTask on button click to refresh the screen. Following is the sequence of events that happen on btn click
progress dialog shows up
The doInBackground is called and thread is initialized which calls a web service. The web service fetches/uploads data. A pass/fail flag is set once the web service is called.
My problem is the onPostExecute is never called and therefore the screen is never refreshed.
And secondly by the time the data is downloaded and the web service sets the flag my code has already hit return stmt in doInBackground.
Question is how do i stop execution in my asynctask so that the web service is done downloading/uploading the data and finally execute onPostexecute.
FYI
I also get the following warning in eclipse
The method onPostExecute(boolean) from
the type
Screen.ConnectWebService is
never used locally
private class ConnectWebService extends AsyncTask <Void, Void, Boolean>
{
private final ProgressDialog pd = new ProgressDialog(screen.this);
protected void onPreExecute() {
pd.show(Screen.this, "Sync", "Sync in progress",true,false);
}
protected Boolean doInBackground(Void... unused) {
if (SyncInProgress == false)
{
CallWSThread();//creates thread which calls web service
}
Log.d("doInBackground","doInBackground");
return SyncStatus;
}
protected Void onPostExecute(boolean result)
{
pd.dismiss();
if (result==true) drawRadioButtons();
return null;
}
}
It should be:
protected Void onPostExecute(Boolean result)
As djg noted, you have a typo in your method declaration. You can avoid these kinds of mistakes by using the annotation #Override when you're implementing methods from a super class.