i'm trying to restart the interrupted thread in onResume (i'm interpreting the thread in onPause). For this i saw lot of examples in online but nothing was helpful (May it's my fault). So,please tell me how to restart interrupted thread in onResume
My code:
private void runThread(){
threadService = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Thread", "thread");
if (freshMSgId != null) {
getPrevChatVolleyInThread();
}
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadService.start();
}
#Override
protected void onPause() {
super.onPause();
if (threadService != null) {
threadService.interrupt();
}
}
#npace Thank you, i got the idea from your comment. I restarted the interrupted thread in onResume like
#Override
protected void onResume() {
super.onResume();
runThread();
}
Related
I Have an EventBus() that runs and looping until it goes to my other Fragment when my app starts. when I idle the app for at least 30++ minutes, I'm getting this stacktrace:
10-11 10:23:46.315 3790-4797/com.jti.mikee.jti_pos W/libc: pthread_create failed: couldn't allocate 1040384-byte stack: Out of memory
10-11 10:23:46.315 3790-4797/com.jti.mikee.jti_pos E/dalvikvm: pthread_create (stack size 16384 bytes) failed: Try again
I also use ScheduleExecutorService() on onCreateView()
scheduledExecutorService = Executors.newScheduledThreadPool(4);
This is the declaration of my EventBus()
public static final Runnable mRunnable = new Runnable() {
#Override
public void run() {
EventBus.getDefault().post(new EB_TapCard());
}
};
and on my onResume() this is the code
#Override
public void onResume() {
Log.e("current_module",current_module);
super.onResume();
try {
EventBus.getDefault().register(this);
rfscanner = scheduledExecutorService.scheduleAtFixedRate(mRunnable, 0, 2, TimeUnit.SECONDS);
} catch (Throwable e) {
e.printStackTrace();
}
}
and lastly, this is my onPause() method
#Override
public void onPause() {
try {
getContext().unregisterReceiver(broadcastReceiver);
} catch (Throwable e) {
e.printStackTrace();
}
rfscanner.cancel(true);
EventBus.getDefault().unregister(this);
super.onPause();
}
I'm wondering that when I idle my device, The runnable is still running. How can I pause/resume it? much appreciated.
EDIT
As of now, I have tried to add a function Callback(). It's working well but after I tap the card, The Card Reader is not reading the second card. how can I make it loop without making the memory full??
class CallBackThread extends Thread {
#Override
public void run() {
try {
RFCardInterface.waitForCardPresent(RFCardInterface.CONTACTLESS_CARD_MODE_AUTO, 1, -1);
if (RFCardInterface.isCallBackCalled &&
RFCardInterface.notifyEvent.eventID == RFCardInterface.CONTACTLESS_CARD_EVENT_FOUND_CARD) {
IDCatcher = StringUtility.ByteArrayToString(RFCardInterface.notifyEvent.eventData,
RFCardInterface.notifyEvent.eventData.length);
IDCatcher = IDCatcher.substring(9, 21).replace(" ", "");
Log.e("IDCatcher", IDCatcher);
EventBus.getDefault().post(new EBTest2());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Try something along these lines:
private Handler mHandler; // the handler to this activity
private Runnable mCallback; // the callback to 2s loop
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
mHandler = new Handler();
mCallback = new Runnable() {
#Override
public void run() {
EventBus.getDefault().post(new EB_TapCard());
// schedule next run here
scheduleNextRun();
}
};
}
#Override
public void onResume() {
scheduleNextRun();
}
#Override
public void onPause() {
cleanUpRun();
}
#Override
public void onDestroy() {
// needed in case the system will force-kill your process
cleanUpRun();
}
private void cleanUpRun() {
if (mHandler != null) {
mHandler.removeCallbacks(mCallback);
}
}
private void scheduleNextRun() {
// clean up beforehand
cleanUpRun();
if (mHandler != null) {
mHandler.postDelayed(mCallback, 2000L);
}
}
idea is that every time you enter the page, you post-delayed your runnable, and you remove it when you go out; once you run it, and it gets the callback executed, you schedule the next run, and so on.
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.
Is there a slicker/simpler way of doing the following? I have a method in a class that shows a progressbar while a thread runs. This code works but it just seems a little overly clunky having 3 steps.
private void pause() {
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.VISIBLE);
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
//do stuff
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.GONE);
}
});
}
This does not show a progress bar while a thread runs.
Your thread can run 10 seconds but the visibility of the ProgressBar will only blink if you can see it at all.
Instead, you should hide only once the thread has completed, so this would be correct:
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.VISIBLE);
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
//do stuff
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.GONE);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
For a "slicker" way, you could use an AsyncTask which was created for this very task. Example:
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Guaranteed to run on the UI thread
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
// Do stuff
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// Guaranteed to run on the UI thread
mProgressBar.setVisibility(View.GONE);
}
}.execute();
Here you can use the handlers concept to communicate with UI Thread.
I.e,
Handler handler=new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case 1:
mProgressBar.setVisibility(View.VISIBLE);
break;
case 2:
mProgressBar.setVisibility(View.GONE);
break;
}
}
}
new Thread(new Runnable() {
#Override
public void run() {
Message processStart = handler.obtainMessage(1);
processStart.sendToTarget();
try {
//do stuff
} catch (InterruptedException e) {
e.printStackTrace();
}
Message processStart = handler.obtainMessage(2);
processStart.sendToTarget();
}
}).start();
I hope this one will helps you :)
I have a question.
Recently I develop simple "Logging system" for Android.
There is one singleton class which name is "Logger".
protected Logger(){
....
_logHandler = new LogHandler(_logQueue);
_logHandler.start();
....
}
public static Logger getInstance(){
...
}
In "Logger", one thread is running just like below.
#Override
public void run() {
try{
while (isAlive){
execute();
synchronized (lock) {
try {
while (isPaused) {
lock.wait();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
}
}catch(InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
public void requestShutDown(){
isAlive = false;
interrupt();
}
What i want is when application is terminated, I would like to call "requestShutDown()" method to stop thread above.
But i can't find proper moment.
So, Do I have to
When onPause() method executed in Activity, call requestShutDown(). And onResume() method executed in Activity, call thread.start() again?
Is there another way?
Or When Application is terminated, all the resources in application(include thread, Logger class in above) are garbage collected properly?
thanks in advance.
you can create thread like :
Thread th;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
th = new Thread(new Runnable() {
#Override
public void run() {
//do your stuff
}
});
th.run() //to start thread
}
public void requestShutDown(){
if(th.isAlive())
{
th.yield(); //to close thread
}
}
#dwnz Thank you!!
Finally, I call "onDestory()" method in MainActivity. In onDestory(), if isFinishing() of Activity is true, it will be terminated(Of course, this is not "necessary and sufficient condition".)
I'd appreciate your help in interrupting an Android/Java sleep. What I have in my layout is a button, which if clicked, calls the Skip method and starts a new activity. FYI The same activity would be called anyway when the Sleep method terminates.
Here's my failing code:
public class Splash extends Activity {
private Thread timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
timer = new Thread() {
public void run() {
try {
sleep(5000);
} catch (Exception e) {
e.printStackTrace();
onPause();
return;
} finally {
onPause();
startActivity(new Intent("net.example.splashscreenexample.MainActivity"));
}
}
};
timer.start();
}
#Override
public void onPause() {
timer.interrupt();
super.onPause();
finish();
}
public void Skip() {
timer.interrupt();
startActivity(new Intent("net.example.splashscreenexample.MainActivity"));
}
Now Resolved!
I've now got it all working. In addition to #RocketSpock's suggestions there was also a stupid error in my code in that I'd failed to include the View view paramater into my Skip method call. So the fully working code now looks like this:
public class Splash extends Activity {
private Thread timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
timer = new Thread() {
public void run() {
synchronized (this) {
try {
sleep(5000);
} catch (Exception e) {
e.printStackTrace();
onPause();
return;
} finally {
onPause();
startActivity(new Intent(
"net.rogw.splashscreenexample.MainActivity"));
}
}
}
};
timer.start();
}
#Override
public void onPause() {
timer.interrupt();
super.onPause();
finish();
}
public void Skip(View view) {
synchronized (this) {
this.notify();
}
startActivity(new Intent("net.rogw.splashscreenexample.MainActivity"));
}
}
If you want to be able to interrupt it you should be using a wait.
public class Splash extends Activity {
private Thread timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
timer = new Thread() {
public void run() {
synchronized(this) {
try {
wait(5000);
} catch (Exception e) {
e.printStackTrace();
onPause();
return;
} finally {
onPause();
startActivity(new Intent("net.example.splashscreenexample.MainActivity"));
}
}
}
};
timer.start();
}
#Override
public void onPause() {
timer.interrupt();
super.onPause();
finish();
}
public void Skip() {
//You may need to replace this with the timer object
synchronized (this) {
//Informs the wait to interrupt.
this.notify();
}
startActivity(new Intent("net.example.splashscreenexample.MainActivity"));
}