I have created an AsyncTask. I want to pair with a bluetooth device, and only after pairing it should go to next activity. My code is
public class YourTask extends AsyncTask<String, Void, Void>
{
public BluetoothDevice d;
#Override
protected Void doInBackground(String... urls)
{
//pairDevice(d);
return null;
}
public void onPreExecute()
{
pairDevice(d);
}
#Override
protected void onPostExecute(Void result)
{
Context context = getApplicationContext();
int duration = Toast.LENGTH_SHORT;
CharSequence text = "Pairing";
Toast toast = Toast.makeText(context, text, duration);
toast.show();
startActivity(new Intent(NewDeviceActivity.this,DevicesActivity.class));
finish();
}
}
void pairDevice(BluetoothDevice device) {
try {
Method m = device.getClass()
.getMethod("createBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
The onPostExecute function gets executed even before pairDevice function has finished. Please help
The onPostExecute() method gets triggered after the tasks in doInBackground() have been completed. In your example you are not executing any tasks in doInBackground(), resulting in onPostExecute() to be called immediately. Move your method pairDevice(BluetoothDevice device) into the doInBackground() method and it should work.
Background Long operations should be done only in doInBackground method. This is the actual flow.
#Override
public void onPreExecute()
{
// this executes before Background operation starts
// here you can start showing ProgressBar to let the users know that it's still doing the work and you can dismiss in onPostExecute
}
#Override
protected Void doInBackground(String... urls)
{
// here you should do the long operation
return null;
}
#Override
protected void onPostExecute(Void result)
{
// here you can update the UI or move to other activity after long task has been done
}
The problem is, you are trying to run Background operation in onPreExecute.
public void onPreExecute()
{
pairDevice(d);
}
Just move the pairDevice(d) method to doInBackground method which is not correct.
Related
I have a specific case where I want to run an AsyncTask's doInBackground on UI Thread. How can I do that?
You definitively could, but as #Devrath said, it is pointless. AsyncTask are used for background operation.
Here is a sample that uses the runOnUiThread method:
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// WORK on UI thread here
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
I ended up doing the following:
Got all the code from doInBackground and moved it to a method.
In doInBackground I make a call only to this method.
In the cases where I need the asynctask to be executed normally, I call LongOperation().execute()
In the cases where I need the asynctask to be ran on the UI thread, I dont call it but I call the method instead.
Try this
public void commentBuilder() {
new Thread(new Runnable() {
#Override
public void run() {
//Your code
}
}).start();
}
Also, see this for more detail https://stackoverflow.com/a/14038370
As far i know ..... You cannot !
AsyncTask are designed to perform background task which takes
longer time to perform
So they have to be performed in a seperate thread different from the
mainthread
Mainthread takes care of all the UI for your app
If you want ot update a UI while performing a background operation::
Just use onProgressUpdate method of the AsyncTask to update the
UI during the background operation
else use onPre method to update UI before the beckground call is
made
Else finally use onPost method to update after rte async task
completes doInBackground
{SAMPLE}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
In my acivity, i need to run two background service.
main background service:
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
return null;
}
}
Second background service.
class mloadingTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return "";
}
protected void onPostExecute(String s) {
pd.dismiss();
}
}
In my onCreate() method I want to call the first background and when it finished loading the second background service starts. Part of my background service is as follows.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
However the second background service doesn't seem to start. i am not getting the a print also. I think I miss a step or android doesn't allow more than one background service in the same activity. A help please.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
there is a 99% chance that the if() block will never pass.
You first execute the first asyncTask named loadTask and RIGHT after check if it finished.
Small chance that it actually finishes by then.
The easy approach:
Use only one async task. You want to finish asyncTask 1 and then fire asyncTask 2, its exactly the same as having only one asyncTask doing both operations.
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return null;
}
}
The difficult approach:
How I solve this kind of thing is(our situation is different, but it should do)
Create an interface, with one method. for example:
public interface OnDataChangedListner {
void dataChanged(Class listener);
}
Then somewhere (i use my repository classes)
write a method to add and remove entires to a list of OnDataChangedListener interfaces
private ArrayList<OnDataChangedListner> mOnDataChangedListners;
public void addOnDataChangedListner(OnDataChangedListner onDataChangedListner){
synchronized (mOnDataChangedListners){
mOnDataChangedListners.add(onDataChangedListner);
}
}
public void removeOnDataChangedListner(OnDataChangedListner onyDataChangedListner){
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener .equals(onDataChangedListner))
it.remove();
}
}
}
}
This might be overkill. But this example should help you with updating the UI while your tasks are running. A free extra! :))
With the above code in place, create an onDataChanged() method in the same class where u defined the add and remove listener methods.
In that code call a handler
// Need handler for callbacks to the UI thread
final static Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mNotifyDataChanged = new Runnable() {
public void run() {
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener != null)
listener.dataChanged(this.getClass());
else
it.remove();
}
}
}
}
};
/**
* will notify registerred delegates on the main (UI) thread
*/
public void notifyDataChanged(){
mHandler.post(mNotifyDataChanged);
}
Ok, so I ended up giving out an entire sample.
Where you place this code is upto you. But when you call notifyDataChanged() it will fire the handler, which in turn will loop trough all current registered listeners for this class
then in turn it will call the listeners datachanged method.
To make this all work, all you have to do is have a class implement the interface
call addOnDataChangedListener(this);
and implement the method provided in the interface.
Note that this is deffinetly not the easiest way to do things.
I don't know what the easiest way to do what you want is. I never have been in that situation before.
but you can execute the second task in the implemented method. Should work..
AsyncTask is Asynchronous as its name suggest. You need to call your 2nd AsyncTask in onPostExecute of your 1st AsyncTask
OR
Loop and wait till AsyncTask is finished in your activity, but it may take more time and you can get Application Not Responding message.
As soon as you call execute() method, control comes to next statement which loadTask.getStatus(). As task is just started, loadTask.getStatus() will not return FINISH and your 2nd task is never getting executed.
In my application when i click on Button it sometimes shows the progressdialog and sometimes not show the progressdialog on click of button.
Asynchronous Task code is:
public class LoadData extends AsyncTask<Void, Void, Void>
{
ProgressDialog pd;
#Override
protected void onPreExecute()
{
pd = ProgressDialog.show(MainActivity.this, "", "Loading...");
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
LoadActivities(); // function to load data from url
}
});
return null;
}
#Override
protected void onPostExecute(Void unused)
{
pd.dismiss();
}
}
and on button click event call this as:
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new LoadMoreData().execute(null);
}
});
the wrong think you are doing is that in doInBackground you use runOnUiThreade . just remove that from your code . It solves your problem.
never use any thread in doInBackground.
Why you have taken run method again in doInBackground, doInBackground method performs computation on a background thread, so no need to take runOnUiThread
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
LoadActivities(); // function to load data from url
}
});
Just write
protected Boolean doInBackground(final String... args) {
try {
LoadActivities();
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
And also change new LoadMoreData().execute(); don't write null
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new LoadMoreData().execute();
}});
Nirali's answer seems correct, just to make further explaination and some edits.
Progress Dialog will be shown by the time doInBackground method returns value. and in your code it just create another thread, and completes execution, so to display progress dialog by the time LoadActivities exectues, execute this statement in the same thread doInBackground executes, so change to following:
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
MainActivity.this.runOnUiThread(new Runnable() {
LoadActivities(); // function to load data from url
return null;
}
i want to add a progress Dialog button when i click on this button before the new activity apperar, i think i don't need a thread, i did search but i find only that i need to do a thread and many other think it s not clear
i just want when i clik on a progress Dialog say to the user to wait so a few sec the other activity will appear that's all:
btn_newsfeed.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// Launching News Feed Screen
Intent i = new Intent(getApplicationContext(), CustomizedListView.class);
startActivity(i);
}
});
There are three different different ways in which you can use a ProgressDailog -using threads, handlers and async tasks.
here a example of async task for using a progress Dialog
private class Operation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params)
{
// code to be executed in background thread
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
// runs on UI thread and updated UI after executing doInBackground
progressDialog.dismiss();
}
#Override
protected void onPreExecute() {
ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "Title ", "Loading...");
progressDialog.show();
}
#Override
protected void onProgressUpdate(Void... values) {
// runs on UI thread and starts first
}
}
I want show dialog after finish Thread.
In thread I am changing TextView's Value like as 0 to 100...
When TextView Value is reach 100 then i want to show dialog..
What i do for it.
Thanks in advance...
Code Snippet:
final Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
synchronized (this)
{
try
{
for(int i=0 ; i<speed; i++)
{
final int value=i+1;
wait(3000/speed);
Test.this.runOnUiThread(new Runnable() {#Override public void run()
{
accText.setText(String.valueOf(value));
}});
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread.start();
this is asyntask code snippet...
class setTextBackgroundTask extends AsyncTask<String , Integer, Void>
{
#Override
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(String... params)
{
Thread th = new Thread();
int value;
for(int i=0 ; i<speed; i++)
{
value=i+1;
publishProgress(value);
try {
th.sleep(3000/speed);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values)
{
accText.setText(String.valueOf(values[0]));
System.out.println("Value=="+values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result)
{
showShareDialog();
}
}
This document explains how you can create dialogs.
Please note that you will have to do any dialog creation code on the UI thread.
You already have code that runs something on the UI thread, just do that outside the loop,but with the dialog creation code inside.
You should use AsyncTask: subclass AsyncTask, override doInBackground() to execute your time consuming action on another thread, and then override onPostExecute() to show your dialog.
Note that you cannot change UI elements from a non-UI (background) thread. AsyncTask takes care of that for you: it calls doInBackground() on a new thread and then calls onPostExecute() on the UI thread as soon as the background task is complete.