public class MainActivity extends Activity implements Runnable{
private int progressBarStatus = 0;
private Handler progressBarHandler = new Handler();
ProgressBar linProgressBar;
private long fileSize = 0;
Thread t1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button)findViewById(R.id.button1);
Button b2 = (Button)findViewById(R.id.button2);
b2.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
linProgressBar.setProgress(0);
t1.interrupt();
}
});
b1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
basicInitializations();
}
});
}
public void basicInitializations(){
linProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
linProgressBar.setProgress(0);
linProgressBar.setMax(100);
try{
t1 = new Thread()
{
public void run() {
while (progressBarStatus < 100) {
// process some tasks
progressBarStatus = doSomeTasks();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
linProgressBar.setProgress(progressBarStatus);
}
});
}
if (progressBarStatus >= 100) {
try {
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
t1.start();
}catch (Exception e) {
}
}
public int doSomeTasks() {
while (fileSize <= 1000000) {
fileSize++;
if (fileSize == 100000) {
return 10;
} else if (fileSize == 200000) {
return 20;
} else if (fileSize == 300000) {
return 30;
}else if (fileSize == 400000) {
return 40;
}else if (fileSize == 500000) {
return 50;
}
}
return 100;
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
this is my main code and i could not stop this thread .
i want to stop it when i click the button b2(say cancel button).
the above code is not the original code and is a model , so please tell me how to stop that thread .
thankyou in advance . . . .
I have a alternate answer can try the same, inside your runnable loop always check a flag as run_flag, create it as a member variable and set it as true once you stared the loop, you can make it run_flag as false wenever you are done and at the same time you can set null to your thread also ... a safer way to come out through runnable loop and thread.
try{
t1 = new Thread()
{
public void run() {
while (progressBarStatus < 100 && run_flag == true) { // added run_flag here
// process some tasks
progressBarStatus = doSomeTasks();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
linProgressBar.setProgress(progressBarStatus);
}
});
}
if (progressBarStatus >= 100) {
try {
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
t1.start();
}catch (Exception e) {
}
Your thread spends most of its time in Thread.sleep(), which is helpful. The thread pointer, t1, is a class member, which is also helpful. From your button handler, you can check to see if t1 is still alive and, if so, call t1.interrupt();. This will cause the thread's current sleep and future sleeps to throw the InterruptedException... now you just need to modify your exception handler to quit the thread in that case.
Related
I'm trying to change a textView from my thread, but it always crashes. Why?
public void startProgress(View view) {
bar.setProgress(0);
new Thread(new Task()).start();
}
class Task implements Runnable {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar.setProgress(value);
text.setText("i = "+i);
}
}
}
I don't know why i can't change it. Anyone knows why?
Thanks.
Views can only be modified by their parent thread. This is a common problem that people face, unfortunately you just have to work around it.
Use runOnUiThread
runOnUiThread(new Runnable(){
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar.setProgress(value);
text.setText("i = "+i);
}
}
});
As #dodo or #CommonsWare said you must access View hiearhcy in the main ui thread.
To comply with this rule, use Handler.post(Context.getMainLooper())
new Handler(context.getMainLooper()).post(new Runnable() {
public void run() {
bar.setProgress(value);
text.setText("i = "+i);
}
});
Finally I fixed it. Thanks anyway.
public void startProgress(View view) {
bar.setProgress(0);
//new Thread(new Task()).start();
Thread th = new Thread(new Runnable() {
public void run() {
for (int i=0; i<10;i++){
final int timer = i;
runOnUiThread(new Runnable() {
#Override
public void run() {
text.setText("velocitat: "+timer);
}
});
bar.setProgress(timer);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
th.start();
}
I am trying to update seekbar with respect to the progress of the song in MediaPlayer.
I am using Thread to do that task.
First i have used Thred inside thread and trying to update the UI but it crashing the app and says that only original thread can attached to the view.
Then i have try to update it with handler inside the thread runnable. which works fine but it is not updating the seekbar. When i have do log then i come to know loop is not going inside my handler. I dont know where is the problem. Please help me to updating SeekBar.
Code:
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
try {
if ((musicPath != mIRemoteService.getPath())) {
System.out.println("..... MUSIC CHANGE.....");
setOrUpdateData();
updateFragmentLayout();
}
// Displaying Current Duration time/Progress
new Handler().post(new Runnable() {
#Override
public void run() {
try {
songCurrentDurationLabel.setText(""+ Utilities.milliSecondsToTimer(mIRemoteService.position()));
songProgressBar.setProgress((int)mIRemoteService.position());
System.out.println("Runnnnn.........");
//songProgressBar.invalidate();
} catch (RemoteException e) {
e.printStackTrace();
System.out.println("Runnnnn......... EXCEPTION....");
}
}
});
System.out.println("Runnnnn.........MAIN....");
if (!(mIRemoteService.isPlayerRunning())) {
btnPlay.setImageDrawable(getResources().getDrawable(R.drawable.play_now_playing));
mHandler.removeCallbacks(mUpdateTimeTask);
System.out.println("Runnnnn.........MAIN....IF");
}else{
System.out.println("Runnnnn.........MAIN....ELSE");
mHandler.post(mUpdateTimeTask);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
you can use either a handler or a thread, with thread you should make sure to post the modifications on the UI thread:
private class UpdateSeekBar extends Thread
{
#Override
public void run()
{
super.run();
while (null != mp && mp.isPlaying() && this.isAlive())
{
//final int min = (mp.getCurrentPosition() / 1000) / 60;
//final int sec = (mp.getCurrentPosition() / 1000) % 60;
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
try
{
songCurrentDurationLabel.setText("" + Utilities.milliSecondsToTimer(mIRemoteService.position()));
songProgressBar.setProgress((int) mIRemoteService.position());
System.out.println("Runnnnn.........");
// songProgressBar.invalidate();
}
catch (RemoteException e)
{
e.printStackTrace();
System.out.println("Runnnnn......... EXCEPTION....");
}
}
});
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
I want run run a thread after one thread completes its execution.
Here I am using progress bar, after progress bar completes the method do1() should execute but when I am run the application the application force close.
here is my code..
public void onenc(View view) {
progressBar = new ProgressDialog(view.getContext());
progressBar.setCancelable(true);
progressBar.setMessage("Ecoding Text ...");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.show();
//reset progress bar status
progressBarStatus = 0;
//reset filesize
fileSize = 0;
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
// process some tasks
progressBarStatus = doSomeTasks();
// your computer is too fast, sleep 1 second
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
// ok, file is downloaded,
if (progressBarStatus >= 100) {
// sleep 2 seconds, so that you can see the 100%
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
// close the progress bar dialog
progressBar.dismiss();
}
}
}).start();
Thread tt =new Thread(new Runnable() {
public void run() {
do1();
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
tt.start();
}
I have also tried AsyncTask but both run simultaneously.
Please help me I am a newbie in android.
Thanks in advance.
Update:
After AsyncTask
class MyFirstTask extends AsyncTask<String, Boolean, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
return null;
//Do Stuff
}
public void progressUpdate(Integer progress) {
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
// process some tasks
progressBarStatus = doSomeTasks();
// your computer is too fast, sleep 1 second
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
// ok, file is downloaded,
if (progressBarStatus >= 100) {
// sleep 2 seconds, so that you can see the 100%
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
// close the progress bar dialog
progressBar.dismiss();
}
}
}).start();
}
#Override
protected void onPostExecute(Boolean result) {
//Call your next task
Thread tt =new Thread(new Runnable() {
public void run() {
do1();
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
tt.start();
}
}
Now not even a single thread is executing the application force closes
After Another Update
class MyFirstTask extends AsyncTask<String, Boolean, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
// process some tasks
progressBarStatus = doSomeTasks();
// your computer is too fast, sleep 1 second
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
// ok, file is downloaded,
if (progressBarStatus >= 100) {
// sleep 2 seconds, so that you can see the 100%
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
// close the progress bar dialog
progressBar.dismiss();
}
}
}).start();
return null;
//Do Stuff
}
public void progressUpdate(Integer progress) {
}
#Override
protected void onPostExecute(Boolean result) {
do1();
//Call your next task
/* Thread tt =new Thread(new Runnable() {
public void run() {
do1();
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
tt.start();*/
}
}
Now the function do1() executes before progress bar completes.
Finally Solved it....Here is the answer.
Hope it will help others
class MyFirstTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.show();
}
#Override
protected String doInBackground(String... params) {
int i=0;
while(fileSize<100)
{
fileSize=fileSize+1;
publishProgress(""+(int)(fileSize));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
publishProgress(""+(int)(fileSize));
return null;
}
public void onProgressUpdate(String... progress) {
progressBar.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String result) {
progressBar.dismiss();
do1();
}
}
Don't use Thread() at all. Use AsyncTask as it makes life easier and implement the onPostExecute() method to call the next AsyncTask
class MyFirstTask extends AsyncTask<String, Boolean, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
//Do Stuff that takes ages (background thread)
for(int i=0;i<100;i++){
doStuff();
Thread.sleep(1000L); //sleep because I'm just tired
publishProgress(i);
Thread.sleep(2000L); //sleep some more
}
}
#Override
public void progressUpdate(Integer progress) {
//Update progress bar (ui thread)
progressBar.setProgress(progress);
}
#Override
protected void onPostExecute(Boolean result) {
//Call your next task (ui thread)
new MyNextTask().execute();
}
Start your first task
new MyFirstTask().execute();
You can simply use join() method.
Thread first = new Thread();
Thread secThread =new Thread();
first.start();
first.join();
secThread.start();
but do not do this on main thread.
I am starting a thread when invoking a method to play an audio file.
The code runs ok the first time but when I call the play method again I need the thread to start as if it were being called the first time. I have tried to interrupt the thread and even stop it but nothing seems to work.
How can I properly restart the thread?
Here is some code to help explain.
Global variable
private Thread thread1;
Thread code:
thread1 = new Thread(new Runnable()
{
#Override
public void run()
{
try {
int i=0;
final TextView timeDuration = (TextView) findViewById(R.id.timeDisplay);
final SeekBar seekBar = (SeekBar)findViewById(R.id.seekBar1);
while (running)
{
info();
j = 0;
while(i>0 && running)
{
while(j<duration && running && (playStatus.getValue() == "TRANSITIONING" || playStatus.getValue() == "PLAYING"))
{
seekBar.setMax((int) duration);
seekBar.setProgress(0);
runOnUiThread(new Runnable()
{
public void run()
{
System.out.println("PLAYBACK STATUS: "+playStatus.getValue());
timeDuration.setText(""+(j+1));
seekBar.setProgress(j+1);
if(j==(duration-1))
{
setRunning(false);
}
}
});
Thread.sleep(1 * 1000);
j++;
if(seekBar.getProgress() == seekBar.getMax())
{
runOnUiThread(new Runnable()
{
public void run()
{
playButton.setVisibility(View.VISIBLE);
pauseButton.setVisibility(View.GONE);
timeDuration.setText(""+"0");
seekBar.setProgress(0);
flag = false;
System.out.println("J VALUE 1: = "+j);
duration = 0;
setRunning(false);
}
});
}
}
}
j = 0;
i++;
Thread.sleep(1 * 1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
play();
This code works fine and plays the track. It then resets the seekbar and awaits for the play method to be called again.
public void play()
{
try
{
thread1.start();
}
catch(Exception e)
{
return;
}
}
Here is the setRunning method recommended to me.
public void setRunning(boolean b)
{
this.running = b;
}
If anyone know of a solution to this problem I would really appreciate it.
Threads are not supposed to be stopped manually. You should use a boolean instead of true in your while loop, and put the boolean to false through a setter when you want to stop:
private boolean running;
#Override
public void run(){
running = true;
while(running) {...}
}
public void setRunning(boolean b){
this.running = b;
}
To restart your player you need to prepare again.
public void restartAudio() {
Log.e(TAG, "restartAudio");
if (mp.isPlaying()) {
mp.seekTo(0);
}else{
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
When using extra boolean flag to controll thread's while loop don't forget to use volatile modifier on it:
private volatile boolean running;
or put appropriate synchronization.
Apart from that, I'd think about using Thread.isInterrupted() method instead of the additional 'running' flag:
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#isInterrupted()
here's why:
https://stackoverflow.com/a/3196058/1350225
i try to make my screen blinking like this:
for (int i=0;i<10;i++)
{
targetView.setBackgroundColor(Color.BLUE);
for (int j=0;j<500;j++); //delay
targetView.setBackgroundColor(Color.RED);
}
but it wont work
Try this,
targetView.setBackgroundColor(Color.BLUE);
try {
Thread.sleep(5000); // milliseconds to wait...
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
targetView.setBackgroundColor(Color.RED);
EDIT
public class TSActivity extends Activity {
LinearLayout lin;
private int finalStatus = 0;
private Handler colorHandler = new Handler();
boolean flag = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lin = (LinearLayout)findViewById(R.id.linMain);
new Thread(new Runnable() {
public void run() {
while (finalStatus < 100) {
// process some tasks
finalStatus = doSomeTasks();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the color
colorHandler.post(new Runnable() {
public void run() {
if(flag)
{
lin.setBackgroundColor(Color.BLUE);
flag = false;
}
else
{
lin.setBackgroundColor(Color.GREEN);
flag = true;
}
}
});
}
}
}).start();
}
// color changer simulator... a really simple
public int doSomeTasks() {
long fileSize = 0;
while (fileSize <= 1000000) {
fileSize++;
if (fileSize == 100000) {
return 10;
} else if (fileSize == 200000) {
return 20;
} else if (fileSize == 300000) {
return 30;
}
// ...add your own
}
return 100;
}
}
Hope this will help you..
Thanks...
You can use handler also.
Runnable r=new Runnable(){
public void run(){
if(red){
targetView.setBackgroundColor(Color.RED);
red=false;
}
else{
targetView.setBackgroundColor(Color.BLUE);
red=true;
}
if(!stop_blinking) handler.postDelayed(this,1000);
}
};
handler=new Handler();
handler.postDelayed(r,1000); //1000 is in mili secs.
stop_blinking is boolean which you need to set whenever you want the view to stop blinking.