i'm developing an android App.
The user registration process calls a service that sends an email so it takes several seconds, like 5 or 6 seconds,that's why I execute that task within a thread. The problem is, the Dialog is never dismissing. It stays rolling and the user can do nothing. Here's my code:
try
{
final ProgressDialog progDailog = new ProgressDialog(ActividadAltaUsuario.this);
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
URL url = new URL("slowWS");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
InputStream in = new BufferedInputStream(conn.getInputStream());
String response = IOUtils.toString(in, "UTF-8");
final JSONObject jsonPrincipal = new JSONObject(response);
Boolean success = jsonPrincipal.get("status").toString() == "true";
if (success)
{
ActividadAltaUsuario.this.runOnUiThread(new Runnable() {
#Override
public void run() {
progDailog.show(ActividadAltaUsuario.this, "Sendind email");
}
});
final String idUsuario = jsonPrincipal.get("idUsuario").toString();
URL url2 = new URL("anotherSlowWS");
HttpURLConnection conn2 = (HttpURLConnection) url2.openConnection();
conn2.setRequestMethod("POST");
InputStream in2 = new BufferedInputStream(conn2.getInputStream());
String response2 = IOUtils.toString(in2, "UTF-8");
JSONObject jsonRtaMail = new JSONObject(response2);
//finish();
}
else
{
//finish();
showToast(jsonPrincipal.get("message").toString());
}
ActividadAltaUsuario.this.runOnUiThread(new Runnable() {
#Override
public void run() {
progDailog.dismiss();
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
}).start();
}
catch(Exception e)
{
Log.e("log_tag", "Error in http connection" + e.toString());
}
Can anybody help me?
Thanks!
AsyncTask would be a better approach instead of thread, Replace your network call from thread to use AsyncTask. You can use something like this
private class LongOperation extends AsyncTask<Void, Void, Void> {
#Override
protected String doInBackground(Void... params) {
//Main stuff that needs to be done in background
}
#Override
protected void onPostExecute(Void result) {
//Post Execution this method will be called, handle result accordingly
//You can dismiss your dialog here
}
#Override
protected void onPreExecute() {
//Do initialization relative stuff here
// Initialize your dialog here.
}
}
As both onPostExecute() and onPreExecute() work on main thread you can show and dismiss your dialog in this methods.
The UI controls have to be accessed only from the UI thread.
Usually I do this in class that extends AsyncTask
Something like:
public class MyTask extends AsyncTask {
protected void onPreExecute() {
//create and display your alert here
progDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Logging ...", true);
}
protected Void doInBackground(Void... unused) {
// here is the thread's work ( what is on your method run()
...
// if we want to show some progress in UI, then call
publishProgress(item)
}
protected void onProgressUpdate(Item... item) {
// theoretically you can show the progress here
}
protected void onPostExecute(Void unused) {
//dismiss dialog here where the thread has finished his work
progDialog.dismiss();
}
}
LE:
More detalis about AsyncTask https://developer.android.com/reference/android/os/AsyncTask
check especially the Protected Methods
Related
I edited my code according dear Mayank'answer but It does not show any message that is sended as input in displayMsg() method before method begines..I should say MethodTest() is started with nfc and in method onNewIntent(Intent intent)
#Override
protected void onNewIntent(Intent intent) {
MethodTest();
..............
}
public void MethodTest() {
DisplayMsg("method 1 is running");
Method1();
DisplayMsg("method 2 is running");
Method2();
DisplayMsg("method 3 is running");
Method3();
}
private int DisplayMsg(String msg) {
totalMsg += msg;
DisplayMsgClass dc = new DisplayMsgClass();
dc.doInBackground(totalMsg);
}
private class DisplayMsgClass extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
textView.setText("Hello !!!");
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.VISIBLE);
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... Messages) {
return Messages[0];
}
#Override
protected void onPostExecute(String result) {
progressBar.setVisibility(View.INVISIBLE);
textView.setText(result);
}
}
in my layout:
<LinearLayout>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="#+id/progressBar1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textv1"
android:hint="AppletPass"
android:gravity="center"/>
</LinearLayout>
Remember that AsyncTasks should ideally be used for short operations (a few seconds at the most.)
Try to learn more about AsyncTask and there are so many mistakes in your code
Do not call doInBackground() manually.
dc.doInBackground(totalMsg); // Error
DisplayMsg() called several times, each time a new instance of class DisplayMsgClass created
DisplayMsgClass dc = new DisplayMsgClass(); // Error
onPreExecute()
textView.setText("Hello !!!"); // NullPointerException. textView.setText() is called without initializing it.
Caution
Do not call AsyncTask.execute() more than one on a same intance.
For eg:
DisplayMsgClass displayMsgClass = new DisplayMsgClass();
displayMsgClass.execute();
displayMsgClass.execute(); //Error, IllegalStateException
will show you a basic demo based on you implementation and you can simply modify it according to your own way.
public void MethodTest() {
// execute task
new DisplayMsgClass().execute("Download now");
}
/*
public void MethodTest() {
DisplayMsg("method 1 is running");
Method1();
DisplayMsg("method 2 is running");
Method2();
DisplayMsg("method 3 is running");
Method3();
}
private int DisplayMsg(String msg) {
totalMsg += msg;
DisplayMsgClass dc = new DisplayMsgClass();
dc.doInBackground(totalMsg);
}
*/
private class DisplayMsgClass extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// retrieve the widgets
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
textView = (TextView) findViewById(R.id.textv1);
textView.setText("Download initialized");
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... Messages) {
// read commands
String command = Messages[0];
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Download completed";
}
#Override
protected void onPostExecute(String result) {
//invoked on the UI thread after the background computation finishes
progressBar.setVisibility(View.INVISIBLE);
textView.setText(result);
}
}
The reason why you are seeing onProgressUpdate(Progress...) called at the end of if(...) is because publishProgress(Progress... values) posts a message to an internal handler, this internal handler later processes the message to update the progress. In other words, publishProgress(Progress... values) doesn't synchronously call onProgressUpdate(Progress...) See implementation here: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java#L649
This is necessary because publishProgress(Progress... values) is expected to be called from doInBackground(Params...), which is on the worker thread for an AsyncTask, whereas onProgressUpdate(Progress...) happens on the UI thread so the UI can reflect the progress change. By posting a message to the handler on the UI thread, the progress info can be synced from worker thread to the UI thread without blocking either thread.
Try below code
private int DisplayMsg(String msg) {
totalMsg += msg;
DisplayMsgClass dc = new DisplayMsgClass();
dc.runner.execute(totalMsg);
}
Hope it will work
:)GlbMP
create progress bar in xml layout and set its visibility gone by default and create code as sample
// AsyncTask .
private class DownloadWebPageTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
//textView.setText("Hello !!!");
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.VISIBLE);
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
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 (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
progressBar.setVisibility(View.INVISIBLE);
textView.setText(result);
}
}
I am currently using an AsyncTask to fetch the JSON array when pressing a button. After that i have another button called ParseJson which opens a new activity in which a list is shown with the JSONArray.
What i would like, is to have one button instead of 2, but since the getJSON button (first button above) is starting a backgroundtask which needs to be finnished first, before launching the other activity (ParseJSON button), this doesnt work in one button right now.
I heard something about using a loading dialog, but i am quite new to this and have no idea how to solve it.
This is the code i use, but i also need the the value from the Textview in the background task. I will send the value of the textview to a php file (by POST) which fetches the data from the database.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void getJSON(View view) {
TextView txv = (TextView) findViewById(R.id.orderID);
txv.getText().toString;
//I need this value in the backgroundtask later
new BackgroundTask().execute();
}
class BackgroundTask extends AsyncTask<Void, Void, String>
{
String json_url = "MYJSONURL";
String JSON_STRING;
#Override
protected String doInBackground(Void... params) {
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
while ((JSON_STRING = bufferedReader.readLine())!=null)
{
stringBuilder.append(JSON_STRING+"\n");
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
return stringBuilder.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
json_string = result;
}
}
public void parseJSON(View view)
{
if(json_string==null)
{
Toast.makeText(getApplicationContext(), "First Get JSON", Toast.LENGTH_LONG).show();
}
else
{
Intent intent = new Intent(this, DisplayListView.class);
intent.putExtra("json_data", json_string);
startActivity(intent);
}
}
Instead of starting the AsyncTask by a button press you code in a way by which it can be started as soon as your main activity is launched. Use onProgressUpdate method of the AsyncTask which will show some progress, once that method is finished your data is loaded. Then you use one button to parse and display the data in the list.
You may refer this to know more about AsyncTask methods
You can have a look at the below code to understand how communication can happen between an activity and AsyncTask. For simplicity I have a count loop running inside AsyncTask which will update the progress on the activity.
Please be warned that this code communicates with the same activity which started the AsyncTask. So, if you would like to perform any such background task, you should be having the AsyncTask attached to your second activity.
public class MainActivity extends Activity {
private ProgressBar mProgress;
private int mProgressStatus = 0;
TextView percentage = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgress = (ProgressBar) findViewById(R.id.progress_bar);
percentage = (TextView) findViewById(R.id.percentage);
new CountProgress().execute();
}
class CountProgress extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
mProgress.setProgress(0);
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... unused) {
for (int i=0; i<101;i++ ) {
if (isCancelled())
break;
publishProgress(i);
SystemClock.sleep(200);
}
return(null);
}
#Override
protected void onProgressUpdate(Integer... progress) {
if (!isCancelled()) {
mProgress.setVisibility(View.VISIBLE);
// updating progress bar value
mProgress.setProgress(progress[0]);
// updating progess percentage text
percentage.setText(progress[0].toString() + "%");
}
}
#Override
protected void onPostExecute(Void unused) {
Toast.makeText(getApplicationContext(), R.string.done, Toast.LENGTH_SHORT).show();
}
}
}
A full working app code can be downloaded from here and you can extend it further for your needs.
how to kill Async task after a specific time.
Here is My code
public class EnterTextAsyc extends AsyncTask<Integer, Integer, Integer> {
/* displays the progress dialog untill background task is completed */
#Override
protected void onPreExecute() {
progressDialog(context, "Please Wait !!!!!...");
super.onPreExecute();
}
/* Task of EnterTextAsyc performing in the background */
#SuppressLint("NewApi") #Override
protected Integer doInBackground(Integer... params) {
try {
socket = new Socket(SERVER_IP, SERVERPORT);
out = new PrintStream(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out.write(("BE").getBytes());
ServerData = in.readLine();
if (ServerData == null || ServerData.equalsIgnoreCase("")) {
ServerData = "IsNull";
}
} catch (NetworkOnMainThreadException e) {
ServerData = "IsNull";
} catch (IOException ex) {
ServerData = "IsNull";
}
return null;
}
How to set a timeout message if there is no response from Server(ServerData = in.readLine();).
Handler h;
private static final int DELAY=3000; //milis
#Override
protected void onPreExecute() {
h = new Handler();
h.postDelayed(new Runnable(){
public void run() {
if(h!=null)
h.removeCallbacksAndMessages(null);
cancelAfterTimeout(true);
}
}, DELAY);
progressDialog(context, "Please Wait !!!!!...");
super.onPreExecute();
}
private void cancelAfterTimeout(boolean interrupt){
//cancel/force interrupt/dissable/remove connection here
//which you are initializing in doInBackground
cancel(interrupt);
}
#Override
protected void onPostExecute(Boolean result) {
if(h!=null)
h.removeCallbacksAndMessages(null);
}
even if you pass mayInterrupt as true the connection is still executing, you might create new method for cancelling online connections and then super.cancel(true);. more info and some methods for override here - onCanceled() and onCanceled(Boolean result) for you
PS canceling Socket connection while executing might be difficult, thread about this here . maybe try HttpClient or HTTPConnection?
I want to show a progress dialog while loading some data from remote server :
I'm using the following thread in order to get the data and it's working, but i'm not able to show the progress bar on the activity:
public class Request {
public String text ;
public boolean downloadText(String urlStr) {
final String url = urlStr;
new Thread () {
public void run() {
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=2;
try {
in = openHttpConnection(url);
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
would you please tell me how can i do it !!
create the class as below and just call the object of this class.
class MyTask extends AsyncTask<Void, Void, Void> {
ProgressDialog Asycdialog = new ProgressDialog(ActivityName.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
Asycdialog.setMessage("Loading...");
Asycdialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// do the task you want to do. This will be executed in background.
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Asycdialog.dismiss();
}
}
Use progressDialog
final ProgressDialog progress=ProgressDialog.show(youractivity.this,"","message");
new Thread()
{
public void run()
{
try{
youractivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
// your code
}
});
}
catch(Exception e)
{
}
progress.dismiss();
}
}.start()
Also, note that if you want to use Toast, you should use runOnUiThread
If you do not want to change the structure of your code, you can use runOnUiThread or an Handler to show and dissmiss the progress dialog. Show it when the firs line of the run method is excuted and dismiss it in the finally block.
public void run() {
runOnUiThread(new Runnable() {
public void run(){
// show progress dialog
}
});
/// your code here
try {
} catch (IOException e) {
} finally {
runOnUiThread(new Runnable() {
public void run(){
// dismiss progress dialog
}
});
}
}
Create Progress Dialog in AsyncTask
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... args) {
// do background work here
return null;
}
protected void onPostExecute(Void result) {
// do UI work here
}
}
pDialog = ProgressDialog.show(context, null, "Loading...", true);
pDialog.setCancelable(false);
new Thread() {
public void run() {
// handle the exception somehow, or do nothing
// run code on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
// do yor ui part here
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}.start();
I am trying to use ProgressDialog. when i run my app the Progress Dialog box show and disappear after 1 second. I want to show it on completion of my process.. Here is my code:
public class MainActivity extends Activity {
android.view.View.OnClickListener mSearchListenerListener;
private ProgressDialog dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new YourCustomAsyncTask().execute(new String[] {null, null});
}
private class YourCustomAsyncTask extends AsyncTask <String, Void, Void> {
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading....");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show(); //Maybe you should call it in ruinOnUIThread in doInBackGround as suggested from a previous answer
}
protected void doInBackground(String strings) {
try {
// search(strings[0], string[1]);
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
dialog.dismiss();
//result
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
return null;
}
}
}
Updated Question:
#Override
public void onCreate(SQLiteDatabase db) {
mDatabase = db;
Log.i("PATH",""+mDatabase.getPath());
mDatabase.execSQL(FTS_TABLE_CREATE);
loadDictionary();
}
/**
* Starts a thread to load the database table with words
*/
private void loadDictionary() {
new Thread(new Runnable() {
public void run() {
try {
loadWords();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private void loadWords() throws IOException {
Log.d(TAG, "Loading words...");
for(int i=0;i<=25;i++)
{ //***//
final Resources resources = mHelperContext.getResources();
InputStream inputStream = resources.openRawResource(raw_textFiles[i]);
//InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
StringBuilder sb = new StringBuilder();
while ((word = reader.readLine()) != null)
{
sb.append(word);
// Log.i("WORD in Parser", ""+word);
}
String contents = sb.toString();
StringTokenizer st = new StringTokenizer(contents, "||");
while (st.hasMoreElements()) {
String row = st.nextElement().toString();
String title = row.substring(0, row.indexOf("$$$"));
String desc = row.substring(row.indexOf("$$$") + 3);
// Log.i("Strings in Database",""+title+""+desc);
long id = addWord(title,desc);
if (id < 0) {
Log.e(TAG, "unable to add word: " + title);
}
}
} finally {
reader.close();
}
}
Log.d(TAG, "DONE loading words.");
}
I want to show ProgressDialogue box untill all words are not entered in the database. This code is in inner calss which extends SQLITEHELPER. so how to can i use ProgressDialogue in that inner class and run my addWords() method in background.
You cannot have this
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
in your doInBackground().
Progress dialog doesn't take priority when there is some other action being performed on the main UI thread. They are intended only when the actions are done in the background. runonUIthread inside doInBackground will not help you. And this is normal behavior for the progressdialog to be visible only for few seconds.
You have two doInBackground() methods inside your AsyncTask Class. Remove the runOnUiThread() from First doInBackground() and move it to second doInBackground() which has #Override annotation.
I don't know whether you wantedly written two doInBackground() methods or by mistake but it is not good to have such confusion between the Method. Your AsyncTask is not calling the first doInBackground() and it will call doInBackground() which has #Override annotation. So your ProgressDialog is dismissed in 1 second of time as it returns null immediately.