I'm new to Android and I'm trying to work through a tutorial on using a ProgressBar in conjunction with a Handler. Just a note, I am targeting API 11.
Here is my code with the errors I am getting inline:
public class HandlerDemo extends Activity {
ProgressBar bar;
Handler handler = new Handler() {
#Override
public void handleMessage() { // Shows "method must override or implement supertype method" on this line.
bar.incrementProgressBy(5);
}
#Override
public void close() {
}
#Override
public void flush() {
}
#Override
public void publish(LogRecord arg0) {
}
};
AtomicBoolean isRunning = new AtomicBoolean(false);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_demo);
bar = (ProgressBar)findViewById(android.R.id.progress);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_handler_demo, menu);
return true;
}
public void onStart() {
super.onStart();
bar.setProgress(0);
Thread background = new Thread(new Runnable() {
#Override
public void run() {
try {
for(int i = 0; i < 20 && isRunning.get(); i++) {
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage()); // Shows "Method is undefined for type Handler" on this line.
}
} catch(Throwable t) { }
}
});
isRunning.set(true);
background.start();
}
public void onStop() {
super.onStop();
isRunning.set(false);
}
}
Why am I getting these errors?
Your Handler import is wrong. It should be android.os.Handler
Related
I write below method and i want run this method any 3000M/S
public void onShakeImage() {
Animation shake;
shake = AnimationUtils.loadAnimation(context, R.anim.shake);
arrowHelpImage.setAnimation(shake);
}
how can i do it?
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle) {
mHandler = new Handler();
startRepeatingTask();
}
#Override
public void onDestroy() {
super.onDestroy();
stopRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
onShakeImage(); //this function can change value of mInterval.
} finally {
mHandler.postDelayed(mStatusChecker, 3000);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
I have a thread in my callback function as follows:
#Override
public void onConnectError(final BluetoothDevice device, String message) {
Log.d("TAG","Trying again in 3 sec.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something
}
}, 2000);
}
});
}
I will to close the the above thread when I press the back button or onDestroy. How can I do it. Thank you
#Override
public void onBackPressed() {
// Close or distroy the thread
}
#Override
public void onDestroy() {
// Close or distroy the thread
}
Please do this like
private Handler handler;
private Runnable runnable;
#Override
public void onConnectError(final BluetoothDevice device, String message) {
Log.d("TAG","Trying again in 3 sec.");
runOnUiThread(new Runnable() {
#Override
public void run() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
//Do something
}
};
handler.postDelayed(runnable, 2000);
}
});
}
and
#Override
public void onBackPressed() {
if (handler != null && runnable != null) {
handler.removeCallbacks(runnable);
}
}
and same in onDestroy();
I'm mostly use thread in this way.See its independent in activity
public class TestActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.abc);
holdConnectionHandler.sendEmptyMessage(0);
}
Handler holdConnectionHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
// do some work
holdConnectionHandler.sendEmptyMessageDelayed(0, 10 * 1000);
}
};
#Override
public void onDestroy() {
super.onDestroy();
holdConnectionHandler.removeCallbacksAndMessages(null);
// or
holdConnectionHandler.removeMessages(0);
}
}
Thanks hope this will help you
I have a fragment with a thread inside it, starting in its onCreate method.
After thread finishes his work i need to send a message to the activity (myActivity) through the "clickButtonOperation".
This is the onCreate() method of my fragment:
public class HolderFragment extends My_Fragment{
private Thread myThread;
.
.
.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new Thread(new Runnable(){
#Override
public void run() {
int i=0;
while (i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
myThread.start();
}
onCreateView returns NULL.
My question is:
Is it guaranteed that my "clickButonOperation" gets called after the new activity has been attached? or could this method be called before this process?
TEMPORARY SOLUTION:
I created a custom Thread class:
public abstract class My_Thread extends Thread {
private boolean runnable=true;
private boolean paused=false;
private Object[] arguments;
private My_ThreadHolder myHolder;
protected void onPostExecute(Object[] arguments){
while(paused);
runnable=false;
}
protected abstract void execute(Object[] arguments);
protected void notifyUpdate(){
while (paused);
}
protected boolean isRunnable(){
return runnable;
}
public void setArguments(Object[] arguments){
this.arguments=arguments;
}
public Object[] getArguments() {
return arguments;
}
public final void run(){
while (runnable){
execute(arguments);
onPostExecute(arguments);
}
}
public void attach(My_ThreadHolder holder){
myHolder=holder;
}
public My_ThreadHolder getHolder() {
return myHolder;
}
public void startThread(){
runnable=true;
start();
}
public void stopThread(){
runnable=false;
}
public void pauseThread(){
paused=true;
printf("Thread paused");
}
public void resumeThread(){
paused=false;
printf("Thread resumed");
}
}
And created these two:
public class My_ThreadHolder extends My_Fragment{
private TestThread myThread;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new TestThread();
myThread.attach(this);
myThread.startThread();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (myThread!=null)myThread.resumeThread();
}
#Override
public void onDetach() {
super.onDetach();
myThread.pauseThread();
}
protected void onNotifyUpdateReceived(Object[] arguments){
myActivity.clickButtonOperation(arguments);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return null;}
#Override
protected void setGraphics(View view, Bundle savedInstanceState) {}
}
class TestThread extends My_Thread{
#Override
protected void onPostExecute(Object[] arguments) {
super.onPostExecute(arguments);
printf("Thread finished");
}
#Override
protected void execute(Object[] arguments) {
int i=0;
while(i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
Object[] myArguments= new Object[2];
myArguments[0]=0;
myArguments[1]=i;
setArguments(myArguments);
notifyUpdate();
}
}
#Override
protected void notifyUpdate() {
super.notifyUpdate();
getHolder().onNotifyUpdateReceived(getArguments());
}
}
You cannot touch the UI from a background thread.. you need to use runOnUiThread method from Activity class, something like this
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
while (i < 3) {
printf("Working...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
}
});
myThread.start();
}
My Timer doesn't stop running if I cancel it!
The Timer only stops if I shut down the whole app!
I don't know why the Timer is not cancelled. If I print out every try on cancelling the Timer I get hundrets of lines but the Timer does not stop!
My Class:
public class PlayActivity extends AppCompatActivity
implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, MediaplayerEvent {
//region Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Initialize_Layout();
Initialize_Objects();
}
#Override
protected void onResume() {
super.onResume();
MusicService.setMediaPlayerEvent(this);
txvSongtitle.setText(serviceInterface.MP_getActualSong().getTitle());
Start_Timer();
}
#Override
protected void onPause() {
timer.cancel();
MusicService.clearMediaPlayerEvent();
super.onPause();
}
#Override
public boolean onSupportNavigateUp() {
finish();
return super.onSupportNavigateUp();
}
//endregion
//region Methods
private void Start_Timer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (serviceInterface.MP_isPlaying()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
seekBar.setMax(serviceInterface.MP_getDuration());
seekBar.setProgress(serviceInterface.MP_getCurrentPosition());
}
});
}
else {
runOnUiThread(new Runnable() {
#Override
public void run() {
timer.cancel();
}
});
}
}
}, 0, 200);
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
serviceInterface.MP_seekTo(progress);
Start_Timer();
}
}
//endregion
}
I hope you can help me!
Thanks!
I would suggest using a Thread instead of a Timer. Your Start_Timer()code would change to something like the following:
private Thread mTimerThread;
...
private void Start_Timer() {
mTimerThread = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
if (serviceInterface.MP_isPlaying()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
seekBar.setMax(serviceInterface.MP_getDuration());
seekBar.setProgress(serviceInterface.MP_getCurrentPosition());
}
});
} else {
interrupt();
}
Thread.sleep(200);
}
} catch (InterruptedException e) {
}
}
}
mTimerThread.start();
}
Threads are more efficient and lightweight and perfect for your needs. Plus, by setting the Thread to a global variable, you can make sure to call mTimerThread.interrupt(); during Android lifecycle events, such as onPause().
I hope this fixes your issue. Remember, the Java Thread is your friend!
You're creating and starting a new timer the user moves the seekbar (in onProgressChanged()). That also means you lose the reference to the old one. When isPlaying turns false, all the timers will try to cancel timer -- which only references the most recent one.
The following code is from Beginning Android 3, Chapter 20. When the phone is rotated, a new activity will be created and onStart() will be called, and so bar.setProgress(0) is called. However, I don't see the bar's progress is back to the beginning. Why not?
public class HandlerDemo extends Activity {
ProgressBar bar;
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
AtomicBoolean isRunning=new AtomicBoolean(false);
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
bar=(ProgressBar)findViewById(R.id.progress);
}
public void onStart() {
super.onStart();
bar.setProgress(0);
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage());
}
} catch (Throwable t) {
// just end the background thread
}
}
});
isRunning.set(true);
background.start();
}
public void onStop() {
super.onStop();
isRunning.set(false);
}
}
Try using this code
#Override
protected void onPause() {
super.onPause();
isRunning.set(false);
bar.setProgress(0);
}