I am working on an app that counts the number of words in a paragraphs/page of text.
After the scanning is done, I would love to show the output total number of words after the number goes from 0 to TOTAL (No of Words).
Example: So, for 100 words: 0..wait..1..wait..2..wait..3..wait..4..wait..5,6,7,8,9 10.......99,100 and then STOP.
I have tried a couple of different techniques:
TextView sentScore = (TextView) findViewById(R.id.sentScore);
long freezeTime = SystemClock.uptimeMillis();
for (int i = 0; i < sent; i++) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
sentScore.setText(sent.toString());
}
}
Also I tried this:
for (int i = 0; i < sent; i++) {
// try {
Thread.sleep(500);
} catch (InterruptedException ie) {
sentScore.setText(i.toString());
}
}
But nothing is helped me. I am sure these are both completely amateur attempts.
Any help? Thanks
The below code will help you current gap is 100 ms but you can change as per your convenience
for (int i = 0; i < sent; i++) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
sentScore.setText(sent.toString());
}
}, 100 * i);
}
In android you are supposed to use AsyncTask for this kind of work
http://developer.android.com/reference/android/os/AsyncTask.html
private class CountUpTask extends AsyncTask<Void, Void, Void> {
private TextView textview;
private int current, total, interval;
public CountUpTask(TextView textview, int total, int interval) {
this.textview = textview;
this.current = 0;
this.total = total;
this.interval = interval;
}
#Override
protected void doInBackground() {
while(this.current < this.total){
Thread.sleep(this.interval);
this.current++;
publishProgress(this.current);
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.textview.setText("0");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
this.textview.setText(progress+"");
}
#Override
protected void onPostExecute() {
}
}
As you can see, doInBackground is executed in a background thread, onPrexcute, onProgressUpdate and onPostExecute are executed in UI thread, allowing you to update the UI.
CountUpTask countUpTask = new CountUpTask ((TextView) findViewById(R.id.sentScore), sent, 500);
countUpTask.execute();
Related
I'm new to android and have a problem with my simple application.
I using a very simple counter using AsyncTask.
When I run the app and start the counter, it counts to 10, and then instead of printing "DONE!" the app just crushes, I have no idea why. Here's my code.
(The activity has 3 buttons to create, start and cancel the task).
public class AsyncTaskActivity extends AppCompatActivity {
AsyncTask myAsyncTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task);
}
public static void startActivity(Context context){
Intent intent = new Intent(context, AsyncTaskActivity.class);
context.startActivity(intent);
}
public void createNewTask(View view) {
TextView textView = findViewById(R.id.text_view_id);
myAsyncTask = new MyAsyncTask(textView);
}
public void startTask(View view) {
myAsyncTask.execute();
}
public void cancelTask(View view) {
myAsyncTask.cancel(true);
}
private static class MyAsyncTask extends AsyncTask{
private TextView textView;
public MyAsyncTask(TextView textView){
this.textView = textView;
}
#Override
protected Object doInBackground(Object[] objects) {
for(int counter = 0; counter <= 10; counter ++){
if(!isCancelled()) {
textView.setText(String.valueOf(counter));
SystemClock.sleep(500);
}
else
break;
}
textView.setText("DONE!");
return null;
}
}
You cannot update UI from background thread mean the code inside doInBackGround runs on background thread
#Override
protected Object doInBackground(Object[] objects) {
for(int counter = 0; counter <= 10; counter ++){
if(!isCancelled()) {
textView.setText(String.valueOf(counter));
SystemClock.sleep(500);
}
else
break;
}
textView.setText("DONE!");
// ^^^^^ crash , cannot update UI from background thread
return null;
}
so instead use onPostExecuted
protected void onPostExecute(Long result) {
textView.setText("DONE!");
}
Note: if you cancel the task then you will find the same crash with textView.setText(String.valueOf(counter));.
Always use generic types and pass the resultant counter value and update UI accordingly.
private static class MyAsyncTask extends AsyncTask<Void,Void,Integer>{
private TextView textView;
public MyAsyncTask(TextView textView){
this.textView = textView;
}
protected Long doInBackground(Void... obj) {
for(int counter = 0; counter <= 10; counter ++){
if(!isCancelled()) {
SystemClock.sleep(500);
return counter;
}
else
break;
}
return null;
}
protected void onPostExecute(Integer result) {
if(result != null)
textView.setText(String.valueOf(result));
else
textView.setText(String.valueOf("Done"));
// your current code will set done no matter the task is cancelled or not
}
}
You can't edit View from AsyncTask doInBackground (only main thread). So move setText to onPostExecute
#Override
protected void onPostExecute(Void result)
textView.setText("DONE!");
}
I am new to android, don't have much experience to manage threads. I am working on an activity where I want to display progress bar for say 5 seconds and then repeat. During those 5 seconds, I will display some text for the user to work on the text. I want to repeat this for say N times.
Currently, I have the following code that works for 1 such progress. I tried looping it but it didn't help, as threads executed at same time. How can I repeat this for N number of times? Am I on the correct path in order to solve my the problem?
public class test extends Activity {
private ProgressBar progressBar;
private int progressStatus = 0;
private TextView textView;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loop);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
textView = (TextView) findViewById(R.id.textView1);
progressBar.setScaleY(3f);
// Start long running operation in a background thread
for(int i=0; i<5; i++)
Progress();
}
public void Progress(){
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
I am not sure I would recommend using the pattern you are following but here is the way to get the threads to run one after another rather than all at the same time:
public void progress(final int numberOfRuns) {
if (numberOfRuns <= 0 ) {
return;
}
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus + "/" + progressBar.getMax());
// For the UI Changes. Eg update the loop number
myTextView.setText(Integer.toString(totalLoop));
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progressStatus = 0;
totalLoop = totalLoop+1;
progress(numberOfRuns - 1);
}
}).start();
}
then just call progress(numberOfRuns), no need for any loops.
My goal is when the user tap start button, letters "o" "n" "o" "m" and so forth will appear at the center of the screen. "o" will appear first then after a few seconds will be replaced by "n" then "o" and so forth.
note: for brevity, i just make the guessword = onomatopoeia, first. In reality, guessword will changes every time i tap the start bottom.
this is the code:
private String guessword = "onomatopoeia";
private TextView showchar;
private int n = guessword.length();
private char letArray[]= guessword.toCharArray();;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
addStartListener();
}
public void addStartListener(){
Button start = (Button) findViewById(R.id.start);
showchar = (TextView) findViewById (R.id.charView);
start.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread = new Thread()
{
#Override
public void run() {
try {
for(int i = 0 ; i < n ; i++) {
sleep(1000);
showchar.setText(letArray[i]);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
});
}
thanks for the help
I decided to implement runonuithread but still it crashes:
this is the updated version:
private String guessword = "onomatopoeia";
private TextView showchar;
private int n = guessword.length();
private char letArray[]= guessword.toCharArray();
private Handler handler;
private int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
handler = new Handler();
showchar = (TextView) findViewById (R.id.charView);
}
public void startGame(View view){
new Thread() {
public void run() {
while(i++ < n) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
showchar.setText(letArray[i]);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
use this code for setting the text in your textview
runOnUiThread(new Runnable() {
#Override
public void run() {
showchar.setText(letArray[i]);
}
});
You are updating ui from a thread which is not possible.
showchar.setText(letArray[i]);
UI must be updated ui thread.
All you are doing is repeatedly setting value to TextView you can use Handler with a delay for this purpose.
You could use runOnUiThread also but i don't see the need for a thread for what you are doing.
Use a Handler. You can find an example #
Android Thread for a timer
i want to increment a progress dialog from a thread inside a service, i have really hard time doing that, this is my code please help me.
I tried many different ways including asyncTask (I had problem with context)
and tried with static functions but its not working properly,
I pretty new with android please explain me the problem here.
the activity
public class MainActivity extends Activity {
ProgressDialog progressBar;
private void showProgrssBar() {
progressBar.show();
}
private void dismissProgressBar() {
progressBar.dismiss();
}
private void increaseProgressBar(int total) {
progressBar.incrementProgressBy(total);
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createProgressBarDialog();
Intent n = new Intent(this, myService.class);
startService(n);
}
private void createProgressBarDialog()
{
progressBar = new ProgressDialog(this);
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setMax(200);
progressBar.setMessage("Recieving bluetooth data");
progressBar.setCanceledOnTouchOutside(false);
}
the service:
public class myService extends Service
{
private myThread myThread;
Handler handler = new Handler()
{
#Override
public void handleMessage(android.os.Message msg)
{
int total = msg.getData().getInt("total");
if (total == -1)
{
dismissProgressBar();
}
else if (total == 0)
{
showProgrssBar();
}
else
{
increaseProgressBar(total);
}
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
myThread = new myThread(handler);
myThread.start();
return START_STICKY;
}
the thread
class myThread extends Thread
{
Handler h;
int numOfLinesToRead = 220;
int line = 0;
public myThread(Handler h)
{
this.h = h;
}
private void increaseProgressBarOnActivity(int i_MsgType)
{
Message msg = h.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", i_MsgType);
msg.setData(b);
h.sendMessage(msg);
}
#Override
public void run() {
super.run();
int increase;
try
{
Thread.sleep(1);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
for (; line < 220; line++)
{
increase = (line*100/numOfLinesToRead);
if (increase != 0)
{
increaseProgressBarOnActivity(increase);
try
{
Thread.sleep(90);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
Despite you having already tried AsyncTask, I still would strongly recommend to use it.
Just take a look at the onProgressUpdate() method. It is made to update the UI from AsyncTask.
Here is an example of how it could look like:
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
private ProgressDialog progressBar;
#Override
protected void onPreExecute(){
super.onPreExecute();
progressBar= new ProgressDialog(getApplicationContext());
progressBar.setMessage("Loading...");
progressBar.show();
}
protected Long doInBackground(String... params) {
long someLong;
// do something here with params
// the Integer variable is used for progress
publishProgress(i);
// call it for example while downloading a file
return someLong;
}
// this is called whenever you call puhlishProgress(Integer)
protected void onProgressUpdate(Integer... progress) {
progressBar.incrementProgressBy(progress[0]);
}
// the onPostexecute method receives the return type of doInBackGround()
protected void onPostExecute(Long result) {
// do something with the result
progressBar.dismiss();
}
}
You said your problem was getting the Context. Well: Service is a Context
So you could simply make the AsyncTask an inner class of your Service and then use its Context.
i have implemented code form the below link to check the idle time of the application
How to intent to another page on android/pop up a message from idle time?
Instead using thread i used asyntask...Now my problem once it reaches the idle time..i want to show dialog to the user application is end relogin from the login activity..
How can i call dialog from the asynctask onpostExcute
public class session extends AsyncTask<Void,Void,Void> {
private static final String TAG=session.class.getName();
private long lastUsed;
private long period;
private boolean stop;
Context context;
final Dialog dialog = new Dialog(context);
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//here i do the process.......
}
#Override
protected void onPostExecute(Void x){
//stuff to be done after task executes(done on UI thread)
// For Dialog Button**********************************
dialog.setContentView(R.layout.dialog);
dialog.setTitle("Result");
final TextView dialogtxt = (TextView) dialog
.findViewById(R.id.textView1);
final Button closeButton = (Button) dialog
.findViewById(R.id.button1);
closeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
dialogtxt.setText("session time out");
dialog.show();
// ****************************************************
}
#Override
protected void onPreExecute(){
//stuff to be done after task executes(done on UI thread)
}
}
You can do it by calling the dialog from either one of the methods except the doInBackground method.
You may call it in the onPreExecute and show the dialog there and after your background task is done you can cancel it from the onPostExecite method. If you want even more control you can also do it using onProgressUpdate. Just dispatch the progress from your background task by calling publishProgress and overwrite the onProgressUpdate method and do whatever you want there.
This is an example taken right out of the docs.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
The Asynctask need to get the Context.
If your Asynctask is embeded into the activity, just call the java Activity.this as a context.
You can also put a context as a field in the Asynctask and then give it as an arg to Asynctask.
You can call the Dialog.show in the onPostExecute, it's on UI Thread.
This sample AsyncTask is embeded into an activity
public class AsyncDialogBuilder extends AsyncTask {
private Context context = DriverOnTripActivity.this;
private final AlertDialog.Builder dialog = new AlertDialog.Builder(context);
private Integer remoteAllWaitinOnCount;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
}
#Override
protected Integer doInBackground(Integer... integers) {
remoteAllWaitinOnCount = User.getRemoteAllWaitinOnCount(latestClosestKojo.getRemoteId());
if (remoteAllWaitinOnCount > 0) {
try {
makeDialog();
} catch (Exception e) {
e.printStackTrace();
}
return 100;
} else {
return 99;
}
}
private void makeDialog() {
dialog.setTitle(latestClosestKojo.getName()
+ " - "
+ remoteAllWaitinOnCount
+ " Kojoalas");
dialog.setPositiveButton("S'arreter", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
isDialogPrompted = false;
dialogInterface.dismiss();
goToOnBoardingActivity();
}
});
dialog.setNegativeButton("Ignorer", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
isDialogPrompted = false;
dialogInterface.dismiss();
}
});
}
#Override
protected void onPostExecute(Integer integers) {
if (integers >= 100 && dialog != null) {
dialog.show();
isDialogPrompted = true;
}
}
}