Hi,
In my app im trying to use Thread.sleep(100) to pause my thread, while its backgrounded in order to use less cpu, but it freezes when I open it back up.
I realized that onResume is not being called when I reopen the app.
Any ideas why?
public void onPause() {
pause = true;
Log.d("mSTATE","THREADPAUSE");
}
public void onResume() {
pause = false;
running = true;
Log.d("mSTATE","THREADRESUME");
}
public void run() {
while(running){
while(pause && running){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (!pause && running) {
Canvas c = null;
try {
c = sHolder.lockCanvas(null);
synchronized (sHolder) {
doDraw(c);
powerUps();
}
} finally {
if (c != null) {
sHolder.unlockCanvasAndPost(c);
}
}
}
}
Log.d("mState","EndofRun");
}
When you put your thread to sleep you are also blocking the UI thread thus leading to freezing of your application.
You need to check the Threads in Android way for the best performance.
http://developer.android.com/resources/articles/painless-threading.html
Related
I am creating a simple Morse code app. The user can enter in text which is then translated to Morse and flashed in sequence on a new thread. I have implemented a for loop which is used to turn on/off the camera flash to represent the Morse sequence.
The problem is that when the user navigates away from the activity the on pause method releases the camera but i sometimes get the error 'method called after release'. I am not sure how to cancel the thread from running when the camera is released. I have already attempted to use a volatile Boolean value which is checked at the start of each loop iteration but if the loop is cancelled at any other time but the start then it results in an error.
Does anyone have any ideas/suggestions as to how i could solve this problem?
public void flashTranslation(String message) {
int offIntervalTime = 50;
char[] cArray = message.toCharArray();
for (int i = 0; i < cArray.length; i++) {
if (cArray[i] == '.') {
turnOn();
try {
Thread.sleep(50);
}catch(Exception e)
{
Log.d("One", "Two");
}
turnOff();
try {
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
} else if(cArray[i] == ' ')
{
Log.d("EMPTY!", "EMPTY!");
try{
Thread.sleep(100);
}catch(Exception e)
{
}
}
else {
try{
turnOn();
Thread.sleep(dash);
}catch(Exception e)
{
}
try{
turnOff();
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
}
}
}
The easiest way to do this is canceling the thread protecting against concurrent access via semaphore. Every time you try to flash on the thread, you check if the thread is canceled. Pseudocode:
Semaphore sem;
onPause(){
sem.take();
camera.turnOff();
camera.release();
thread.cancel();
sem.give();
}
thread.run() {
//This should be run before every call to turnOn or turnoff
sem.take();
if(isCanceled()) {
return;
}
turnOn();
sem.give();
}
onResume() {
new Thread.start();
}
I have a memory leak in my android application. It is a simple music player. At the bottom of the screen, I have a TextView which I use to display the elapsed time. It is updated in the thread below.
Each time I change the orientation, the heap size grows. From looking at the DDMS heap updates, it looks like my activity isn't being garbage collected. If, however, I comment out the 6 lines as I have done below, the GC keeps the heap at a fairly consistent size. Could you please let me know what it is that's causing this leak?
private void updateTimerAndSeekBar() {
Thread updater = new Thread() {
SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar1);
TextView timer = (TextView) findViewById(R.id.currentTime);
public void run() {
while (mediaPlayer.isPlaying()) {
// runOnUiThread(new Runnable() {
// #Override
// public void run() {
// timer.setText(msToMins(mediaPlayer.getCurrentPosition()));
// }
// });
try {
seekbar.setProgress(mediaPlayer.getCurrentPosition());
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
updater.start();
}
Each time you change the orientation, Android creates and starts a new activity. The memory leak is due to the fact that the garbage collector cannot collect the old activity that's no longer needed since the separate thread is still running and - as an inner class - is holding onto the activity.
To get rid of the memory leak, you need to stop and end the separate thread when the activity is destroyed.
boolean stopThread;
private void updateTimerAndSeekBar() {
stopThread = false;
Thread updater = new Thread() {
...
while (!stopThread && mediaPlayer.isPlaying()) {
try {
seekbar.setProgress(mediaPlayer.getCurrentPosition());
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
updater.start();
}
protected void onDestroy () {
stopThread = true;
super.onDestroy();
}
Maybe the code kind of shows what I'm attempting to do, so I'll start with that
private void getLicenseResults() {
if (licensed && didCheck == true) {
Thread timer = new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent openStartingPoint = new Intent(
"***.MAINACTIVITY");
startActivity(openStartingPoint);
finish();
}
}
};
timer.start();
}
if (didCheck == false) {
Toast.makeText(Splash.this, "Checking License, Please Wait",
Toast.LENGTH_LONG).show();
Thread timer = new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
getLicenseResults();
Log.i("LICENSE", "re-checking");
}
}
};
timer.start();
}
}
I ran the license check without trying to loop it before, and it worked except if the checking took more than a couple seconds it skipped over the
if (licensed && didCheck == true)
and the activity just kind of stood and waited without launching my main activity (this check is on the splash screen).
So I want the "if didCheck = true" part to be called only after didCheck is in fact finally true. I'm sure there's an easy solution, but I'm self-taught and I have no experience with loops or callbacks(?).
Thank you for any help!
You are not setting didCheck to true in your second if statement before the call to getLicenseResults
hi i am working on custom toast , and i am able to do that, but after when i move to next activity the thread is running or active of back activity , so what should i do for removing that thread or stop this thread.
my code is given below :
public void customToast(int x, int y, String str) {
if (Util.tipson == true) {
toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, x, y);
LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
toastView = li.inflate(R.layout.toastlayout, null);
toast.setView(toastView);
TextView text = (TextView) toastView.findViewById(R.id.text);
text.setText(str);
// toast.show();
fireLongToast();
}
}
private void fireLongToast() {
t = new Thread() {
public void run() {
int count = 0;
try {
while (true && count < 40) {
try {
toast.show();
sleep(100);
count++;
} catch (Exception e) {
// TODO: handle exception
}
// do some logic that breaks out of the while loop
}
toast = null;
toastView = null;
} catch (Exception e) {
Log.e("LongToast", "", e);
}
}
};
t.start();
}
You Need to stop your thread by yourself. Since java doesn't allow you to use stop() function.
Write class for your Thread as this
public class YourThread extends Thread {
private volatile boolean stopped = false;
public void run() {
int count = 0;
try {
while (true && count < 40 && !stopped) {
try {
toast.show();
sleep(100);
count++;
} catch (Exception e) {
// TODO: handle exception
}
// do some logic that breaks out of the while loop
}
toast = null;
toastView = null;
} catch (Exception e) {
Log.e("LongToast", "", e);
}
}
public void stopThread() {
stopped = true;
}
}
Now when your Activity which has the Thread Finishes stop Your thread
#Override
protected void onDestroy() {
if(isFinishing())
yourThreadVariable.stopThread();
}
Dont know for sure, but you can call the function join of thread in onDestroy of your activity.
To stop the thread you can just use interrupt(). But for better solution I would say not to use Thread. Just create a Handler with Runnable and manage your Runnable using Handler, that would be a nice way as Android has given Handler for managing one or more Runnables.
Creating a Runnable
Runnable runnable = new Runnable() {
#Override
public void run() {
// put your code stuff here
}
};
To start Runnable use
handler.postDelayed(runnable, your_time_in_millis);
To stop Runnable use
handler.removeCallbacks(runnable);
Does finishing the activity have any effect?
I would like to suggest Lalit Poptani method too and implement this:
protected void onStop(){
handler.removeCallbacks(runnable);
super.onStop();
}
The documentation for the method:
onStop,Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.
http://developer.android.com/reference/android/app/Activity.html
Wanted to stop a thread doing some downloads.
The code below work fine when i only have the stopNow = true; and no blocking occur.
I create the boolean stopNow = false; as a field in my IntentService.
Since stopNow only work when the connection is ongoing in the while loop
but it does not work if f.ex connection stales and start to block.
I wanted to add this code to really stop the blocking.
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
The question is if this is asynchronous so if the execution is ongoing in the
while loop the stopNow = true; will stop it and i can put a sleep(5000) after the stopNow = true; and then the if(socket != null) will be true only if the stopNow had no effect.
hope you follow me..
BroadcastReceiver that are located inside the run():
private class MyIncomingListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Consts.COM_CARLSBERG_STOPOUTGOING)) {
String b = intent.getStringExtra(Consts.COM_CARLSBERG_BATCHUUID);
if(b != null){
if(b.equals(batch.batchUuid)){
stopNow = true;
// sleep(5000) wait for stopNow to take effect
// if socket=null then stopNow did it's job
// if socket is alive then there is blocking to unblock
try{
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
} catch (Exception e) {}
}
}
}
}
}
this is actually working good so far
stopNow = true;
try{
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
} catch (Exception e) {}
public final void stop ()
Since: API Level 1
This method is deprecated.
because stopping a thread in this manner is unsafe and can leave your application and the VM in an unpredictable state.
Requests the receiver Thread to stop and throw ThreadDeath. The Thread is resumed if it was suspended and awakened if it was sleeping, so that it can proceed to throw ThreadDeath.
try {
int waited = 0;
while(_active && (waited < _splashTime)) {
sleep(100);
if(_active) {
waited += 100;
}
}
} catch(InterruptedException e) {
// do nothing
} finally {
finish();
Intent intent= new Intent(SplashActivity.this,LoginViewController.class);
startActivity(intent);
stop();
}