Android: Two or more threads? (Program is working) - android

I have created a sample/demo/test program in Android that runs quite nicely, if you see below you will see I have created a thread. Now I want to create another thread to work with another handler... since I cannot have two run() methods... how do I do this?
This is my (working - no errors) program:
package com.ryan1;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class main extends Activity implements Runnable{
int level = 0;
int seconds_running=0;
TextView the_seconds,the_level;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
the_seconds = (TextView) findViewById(R.id.textview_seconds);
the_level = (TextView) findViewById(R.id.textview_level);
Thread thread = new Thread(this);
Thread thread2 = new Thread(this);
thread.start();
thread2.start();
}
public void run() {
while(seconds_running<500)
{
if(seconds_running %5 ==0){level++;}
try {
handler.sendEmptyMessage(0);
int a = 1000 - (level*100);
if(a<=100){a=25;}
Thread.sleep(a);
System.out.println("R "+Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
seconds_running++;
int a = 1000 - (level*100);
the_seconds.setText(" "+seconds_running);
the_level.setText(level+" "+a);
}
};
}

Use anonymous class like this.
Thread thread2 = new Thread( new Runnable() {
public void run() {
// code here with your new handler
}
});

make two inner classes that extends Thread.
create an object for both the classes and call start on those objects.

You are suggesting that you want two runnables, yet you only have one runnable defined, which is your 'main' class. So what you need to do is make two different runnables, so that each can have their own code that can be run.
I would make two new classes, lets say, Runnable1 and Runnable2. I would have both of them implement the runnable interface. Each one of them can then contain different code to run in a separate thread.
Finally, I would change your thread creation/start code to look like this:
Thread thread = new Thread(new Runnable1());
Thread thread2 = new Thread(new Runnable2());
thread.start();
thread2.start();

Related

Multiple downloading display in notification bar and also in activity

Right now in my application downloading code is working but when i download multiple files it download randomly not in queue, i need it download in queue and this current download is not displaying in notification bar only display in activity.
I want to know how to possible multiple downloading with displaying in notification bar and also display progress bar in current activity.
Thank you
Looper
By using looper you download multiple file in queue one by one.
Steps 1: Lets create DownloadThreadListener.java interface which will be used to get thread updates.
package com.example.looper;
public interface DownloadThreadListener {
void handleDownloadThreadUpdate();
}
Steps 2: Lets now create a class named DownloadTask.java which will simulate the downloading. We will be using random time sleep to simulate the download time.
package com.example.looper;
import java.util.Random;
import android.util.Log;
/**
* This is not a real download task. It just sleeps for some random time when
* it's launched. The idea is not to require a connection and not to eat it.
*
*/
public class DownloadTask implements Runnable {
private static final String TAG = DownloadTask.class.getSimpleName();
private static final Random random = new Random();
private int lengthSec;
public DownloadTask() {
lengthSec = random.nextInt(3) + 1;
}
#Override
public void run() {
try {
Thread.sleep(lengthSec * 1000);
// it's a good idea to always catch Throwable
// in isolated "codelets" like Runnable or Thread
// otherwise the exception might be sunk by some
// agent that actually runs your Runnable - you
// never know what it might be.
} catch (Throwable t) {
Log.e(TAG, "Error in DownloadTask", t);
}
}
}
Steps 3: Now lets create the thread subclass which will act as pipeline. First we will call Looper.prepare() to make this Thread act as pipeline. Next new Handler() will be called to handle message queue on this thread. Finally Looper.loop() will be called to start running the message loop. New tasks will be added using enqueueDownload(final DownloadTask task).
package com.example.looper;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
public final class DownloadThread extends Thread {
private static final String TAG = DownloadThread.class.getSimpleName();
private Handler handler;
private int totalQueued;
private int totalCompleted;
private DownloadThreadListener listener;
public DownloadThread(DownloadThreadListener listener) {
this.listener = listener;
}
#Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
Log.i(TAG, "DownloadThread entering the loop");
// now, the handler will automatically bind to the
// Looper that is attached to the current thread
// You don't need to specify the Looper explicitly
handler = new Handler();
// After the following line the thread will start
// running the message loop and will not normally
// exit the loop unless a problem happens or you
// quit() the looper (see below)
Looper.loop();
Log.i(TAG, "DownloadThread exiting gracefully");
} catch (Throwable t) {
Log.e(TAG, "DownloadThread halted due to an error", t);
}
}
// This method is allowed to be called from any thread
public synchronized void requestStop() {
// using the handler, post a Runnable that will quit()
// the Looper attached to our DownloadThread
// obviously, all previously queued tasks will be executed
// before the loop gets the quit Runnable
handler.post(new Runnable() {
#Override
public void run() {
// This is guaranteed to run on the DownloadThread
// so we can use myLooper() to get its looper
Log.i(TAG, "DownloadThread loop quitting by request");
Looper.myLooper().quit();
}
});
}
public synchronized void enqueueDownload(final DownloadTask task) {
// Wrap DownloadTask into another Runnable to track the statistics
handler.post(new Runnable() {
#Override
public void run() {
try {
task.run();
} finally {
// register task completion
synchronized (DownloadThread.this) {
totalCompleted++;
}
// tell the listener something has happened
signalUpdate();
}
}
});
totalQueued++;
// tell the listeners the queue is now longer
signalUpdate();
}
public synchronized int getTotalQueued() {
return totalQueued;
}
public synchronized int getTotalCompleted() {
return totalCompleted;
}
// Please note! This method will normally be called from the download
// thread.
// Thus, it is up for the listener to deal with that (in case it is a UI
// component,
// it has to execute the signal handling code in the UI thread using Handler
// - see
// DownloadQueueActivity for example).
private void signalUpdate() {
if (listener != null) {
listener.handleDownloadThreadUpdate();
}
}
}
Steps 4: Now add full functionality to MainActivity.java . Here also we will create handler so that we can post events on main thread.
package com.example.looper;
import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity implements DownloadThreadListener,
OnClickListener {
private DownloadThread downloadThread;
private Handler handler;
private ProgressBar progressBar;
private TextView statusText;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create and launch the download thread
downloadThread = new DownloadThread(this);
downloadThread.start();
// Create the Handler. It will implicitly bind to the Looper
// that is internally created for this thread (since it is the UI
// thread)
handler = new Handler();
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
statusText = (TextView) findViewById(R.id.status_text);
Button scheduleButton = (Button) findViewById(R.id.schedule_button);
scheduleButton.setOnClickListener(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
// request the thread to stop
downloadThread.requestStop();
}
// note! this might be called from another thread
#Override
public void handleDownloadThreadUpdate() {
// we want to modify the progress bar so we need to do it from the UI
// thread
// how can we make sure the code runs in the UI thread? use the handler!
handler.post(new Runnable() {
#Override
public void run() {
int total = downloadThread.getTotalQueued();
int completed = downloadThread.getTotalCompleted();
progressBar.setMax(total);
progressBar.setProgress(0); // need to do it due to a
// ProgressBar bug
progressBar.setProgress(completed);
statusText.setText(String.format("Downloaded %d/%d", completed,
total));
// vibrate for fun
if (completed == total) {
((Vibrator) getSystemService(VIBRATOR_SERVICE))
.vibrate(100);
}
}
});
}
#Override
public void onClick(View source) {
if (source.getId() == R.id.schedule_button) {
int totalTasks = new Random().nextInt(3) + 1;
for (int i = 0; i < totalTasks; ++i) {
downloadThread.enqueueDownload(new DownloadTask());
}
}
}
}
Steps 5: Add Vibrate permission
<uses-permission android:name="android.permission.VIBRATE" />
Original Post Complete tutorial here.

Timer in android crashed throwing java.util runtime error

I am trying to design a simple timer which would run in every second and update my button's text to the remaining time.
But when i run it keeps on crashing.
What i know is the fault is in my button because it my code happens to run for the 1st second, then crashes after that.
Here is my java code
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
public class information extends Activity {
Timer timer;
public Button button;
private int min = 5;
private int sec = 0;
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.information);
button = (Button) findViewById(R.id.gettime);
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if (sec == 0){
sec = 60;
min--;
}
sec--;
if (sec >=10)
Log.d("time",min+":"+sec);
else Log.d("time",min+":0"+sec);
button.setText("ankur");
}
}, 10, 1000);
}
public void onPause(){
super.onPause();
finish();
}
public void onBackPressed(){
super.onBackPressed();
finish();
}
}
button.setText("ankur"); updating ui in timer is not possible. Timer Task runs on a different thread. You can update ui only on the ui thread.
Your options
Use a Handler.
Use runOnUiThread.
You can use a CountDownTimer depending on your need.
You can use runOnUiThread as
runOnUiThread(new Runnable() {
public void run() {
button.setText("ankur")
}
});
For the Handler
Android Thread for a timer
Its because you are modifying UI from background thread in this line:
button.setText("ankur");
you must use handler like:
// in your activity and then
private Handler handler = new Handler();
and in your TimerTask:
handler.post(new Runnable() {
public void run(){
// do your UI job
}
});

Update a TextView in android with for loop and 1000 millisecond delay

I cannot make a simple program to update the UI.
What I am looking to do is create a timer in a for loop that is initiated on a button click
public void buttonClick(View v);
for(int i=0;i<100;i++){
textView.setText(i+"");
try{
thread.sleep(1000);
catch{(yadayadayada)
}
}
I'm trying to make a counter in a for loop to update a text view with a one millisecond delay.
My second try and still no good
package com.example.dbq;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Handler mHandler = new Handler();
TextView tv1;
Button b1;
int n=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1=(TextView)findViewById(R.id.textView1);
b1 =(Button)findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i=0;i<100;i++){
Runnable r=new Runnable() {
#Override
public void run() {
tv1.setText(n +" runs");
}
};
mHandler.post(r);
mHandler.postDelayed(r, 1000);
n++;
}
}
}); //end onclick
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Do not use thread.sleep - you do not need to sleep your thread - you need update your UI at certain intervals and this is something different. Simply use Handler, then create Runnable that either updates your UI or calls the methods to do so and finally post your Runnable using Handler.postDelayed(). To keep the timer work, your Runnable have to post itself again, but that's shall be pretty obvious. And remember to remove your queued runnable when you are going to leave your fragment/activity
Use a timer scheduled at a fixed rate. The below updated text view with a count which is incremented every second.
Remember to update text view on the UI thread and cancel the timer whenever required.
_tv = (TextView) findViewById( R.id.textView1 );
On Button click initiate a timer. Start button to start a timer.
_t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
}
});
}
}, 1000, 1000 );
Have another button stop to cancel the timer
_t.cancel();
You can also use a handler as suggested by WebnetMobile

Android : error when using a runnable in an async task

I want to update a variable in my activity once every one second and for that i am using an Async task and a runnable inside it. I keep getting this error saying "Cannot refer to a non-final variable myRunnable inside an inner class defined in a different method" . When i change the declaration to final , it shows "The local variable myRunnable may not have been initialized" . How do i rectify the error? Is there a better way of doing what i want to do?
import android.os.AsyncTask;
import android.os.Handler;
public class Timer extends AsyncTask<String, Process, Void>{
static int seconds=0;
TimerTask timer;
static int minutes=0;
static int hours=0;
private String timeTaken;
public Handler myhandler = new Handler();
#Override
protected Void doInBackground(String... params) {
final Runnable myRunnable = new Runnable() {
#Override
public void run() {
......
......
......
myhandler.postDelayed(myRunnable, 1000);
}
};
return null;
}
How about something like this instead of using an AsyncTask (although something similar can be done within an AsyncTask, and because it runs in another thread I could simply block this worker thread using Thread.sleep(...) instead of doing the whole Runnable thing...
private myhandler = new Handler();
private boolean periodicCallsEnabled=false;
public boolean isPeriodicUpdatingEnabled(){
return periodicCallsEnabled;
}
public void startPeriodicUpdates(){ //CALL THIS IN ORDER TO START THE PERIODIC UPDATES
periodicCallsEnabled=true;
periodicCall();
}
public void stopPeriodicUpdates(){ //CALL THIS TO STOP THEM
periodicCallsEnabled=false;
myhandler.removeCallbacksAndMessages(null);
}
void periodicCall(){
if(periodicCallsEnabled){
//INSERT CUSTOM CODE HERE TO BE EXECUTED EVERY SECOND
// ......
myhandler.postDelayed(new Runnable(){
public void run(){
periodicCall();
}
},1000);
}
}

cancel dialog after 3 seconds - keeps crashing my app after multiple uses

I have an extended dialog class that I want to show for 3 seconds then disappear. This works great the first 2 times it's called, but then it crashes my app after that. Admittedly, I'm not the best with threads and I think that's where my problem might be. As you can see from the code below (commented out section), I tried using a cancel event to kill the thread that is spawned, but that makes it crash the first time it's run. I've also tried doing all of this on the parent class' UI thread which yields the same result as this (crashes after 3 times displaying the dialog).
import java.util.Timer;
import java.util.TimerTask;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
public class HandResults extends Dialog implements DialogInterface {
HandResults hr;
Timer myTimer;
Handler hand = new Handler();
Thread t;
public HandResults(Context context) {
super(context);
setContentView(R.layout.handresults);
hr = this;
/*
this.setOnCancelListener(new OnCancelListener(){
public void onCancel(DialogInterface dialog) {
t.destroy();
}
});
*/
}
public void showHands(){
this.show();
myTimer = null;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 3000);
}
private void TimerMethod()
{
t = new Thread(){
public void run(){
hand.post(Timer_Tick);
}
};
t.start();
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
hr.cancel();
}
};
}
When the onCancel event is received you're calling t.destroy() and destroy is a deprecated method.
You don't need to start another thread if you're creating a timer, which already runs asynchronously.
So this might work better:
public class HandResults extends Dialog implements DialogInterface {
HandResults hr;
Timer myTimer;
Handler hand = new Handler();
public HandResults(Context context) {
super(context);
setContentView(R.layout.handresults);
hr = this;
}
public void showHands(){
this.show();
myTimer = null;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
hr.cancel(); // call the cancel method directly
}
}, 3000);
}
}
There is no need to create your own thread, so the above code should do approximately what you're trying to do.
You don't need the treat t here, you can run hand.post() inside the TimerTask. And even the TimerTask/Timer is not needed, you can use handler.postDelayed().
I don't know where the behaviour you observe comes from, though.
Also, you should consider that your Dialog is closed early (e.g. when the use rotates the screen). You can call handler.removeCallbacks() in that case.

Categories

Resources