I have tried overriding onBackPressed to not only finish the current activity but also to interrupt the thread as I am calling an intent to the next activity within. When I pressed back before, the splash activity finished, but the thread kept running and call the intent to the next activity. Now that I've include the thread interruption onBackPressed,the app crashes when I press back. What am I doing wrong?
skipscreen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences savestate = getSharedPreferences("skip", MODE_PRIVATE);
savestate.edit().putBoolean("skip", true).apply();
skip= true;
homeintent();
}
});
Thread splashthread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
if (!skip) { homeintent();}
} catch (InterruptedException Interrupt) {
Interrupt.printStackTrace();
}
}
};
splashthread.start();
}
private void homeintent() {
Intent i = new Intent(splash.this, home.class);
startActivity(i);
finish();
}
#Override
public void onBackPressed() {
splashthread.interrupt();
finish();
}
}
UPDATED: (This solution has worked for me).
skipscreen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences savestate = getSharedPreferences("skip", MODE_PRIVATE);
savestate.edit().putBoolean("skip", true).apply();
skip= true;
homeintent();
}
});
Thread splashthread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
if (!skip) { homeintent();}
} catch (InterruptedException Interrupt) {
Interrupt.printStackTrace();
}
}
};
splashthread.start();
}
private void homeintent() {
if (!ThreadInterrupted) {
Intent i = new Intent(splash.this, home.class);
startActivity(i);
}
finish();
}
#Override
public void onBackPressed() {
SharedPreferences savestate= getSharedPreferences("ThreadInterrupted", MODE_PRIVATE);
savestate.edit().putBoolean("ThreadInterrupted", true).apply();
ThreadInterrupted = true;
homeintent();
}
}
To give you a succint answer as well as to explain how to do this in the future,take a look at the Handler class and the Handler.postDelayed() method.
private Handler homeIntenthandler;
#Override
protected void onCreate(){
//other things
skipscreen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences savestate = getSharedPreferences("skip", MODE_PRIVATE);
savestate.edit().putBoolean("skip", true).apply();
skip= true;
homeintent();
}
});
//initialise handler and set timer;
homeIntenthandler= new Handler();
homeIntenthandler.postDelayed(new Runnable() {
#Override
public void run() {
homeintent();
}
},3000);
}
}
private void homeintent() {
Intent i = new Intent(splash.this, home.class);
startActivity(i);
finish();
}
#Override
public void onBackPressed() {
if(homeIntenthandler!=null)
homeIntenthandler.removeCallbacksAndMessages(null)
finish();
}
}
the Handler.removeCallbacksAndMessages(null) is based on the documentation given for the same
When you call interrupt() method on your thread, while in sleep, an InterruptedException will be thrown.
You can check inside your thread weather it should continue:
Thread splashthread = new Thread() {
#Override
public void run() {
while (shouldContinue) {
doSomeWork();
}
}
};
You can then change shouldContinue to false in your onBackPressed method:
#Override
public void onBackPressed() {
shouldContinue = false;
finish();
}
Udi I has answered your question.
But i refer you to use TimerTask and Timer instead of Thread.
Timer timer;
TimerTask timertask;
timer = new Timer();
timertask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
homeintent();
}
});
}
};
timer.schedule(timertask, 3000);
#Override
public void onBackPressed() {
if(timertask!=null){
timertask.cancel();
}
if(timer!=null){
timer.cancel();
}
finish();
}
You can create a volatile boolean check to stop thread from progressing, see following code:
private volatile boolean cancelled = false;
Thread splashthread = new Thread() {
#Override
public void run() {
if ( cancelled ) {
return; // or handle this however you want
}else{
// do what ever you want to do here
}
}
};
splashthread.start();
And in onBackPressed do something like this:
#Override
public void onBackPressed() {
cancelled = true;
finish();
}
The volatile keyword is recommended because, generally, the thread doing the cancelling not necessarily will be the same thread that is being cancelled. Marking boolean check as volatile ensures that the thread checking the flag will see the up to date value.
Related
I have a long running operation. Inside a thread I start a new activity like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
startActivity(new Intent(MainActivity.this,MainActivity.class));
}
});
}
}).start();
}
The problem is when I run another app and the thread finishes, that activity appears on the top of the screen. How to force that activity not to apear on the top?
you can use like below..
Handler splashHandler;
splashHandler = new Handler();
splashHandler.postDelayed(new Runnable() {
#Override
public void run() {
Intent loginIntent = new Intent(Splash.this, LoginActivity.class);
startActivity(loginIntent);
finish();
}
}, 2000);
#Override
public void onBackPressed() {
super.onBackPressed();
if (splashHandler != null)
splashHandler.removeCallbacksAndMessages(null);
}
#Override
protected void onResume() {
super.onResume();
if (splashHandler != null)
splashHandler.removeCallbacksAndMessages(null);
}
This happens because you're getting the Context out of the "other app". You should pass in the application context rather than a context from the local activity. Use context.getApplicationContext() and save that in a local variable, then use this context to start the activity
The code should be something like this:
#Override
protected void onPostExecute(List<VideoDataDescription> result) {
super.onPostExecute(result);
MainActivity.progressDialog.dismiss();
context.startActivity(new Intent(context, MainActivity.class));
}
}
you'd call it like this:
new MyTask(context).execute();
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.
I have splash activity and 1 thread. Thread starts timer and after some time main activity will start.
Unlike on other apps I don't want to disable backPressed button in Splash Activity. I want when backpressed is pressed to cancel thread and finish activity. But I can't get it to work.
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.starter);
Thread Logo = new Thread() {
public void run() {
try {
sleep(1 * 1500);
Intent i = new Intent(getBaseContext(),
MainActivity.class);
startActivity(i);
finish();
} catch (Exception exception) {
}
}
};
Logo.start();
}
...
#Override
public void onBackPressed() {
Thread.currentThread().interrupt();
super.onBackPressed();
this.finish();
}
}
But this doesn't stop thread, it only finish activity and thread keeps running in background(and ofc starts activity)
Make Thread Logo Object Globally and do Logo.interrupt();
You should stop the thread that you already Started before. and also as #TmKVU answer's Thread.currentThread(); return main UI/Main Thread but you have to Stop your Logo Thread.
Try this If you wish to stop the thread if Back button is pressed by the user:
#Override
public void onBackPressed()
{
// First check if the thread isAlive(). To avoid NullPointerException
if(Logo.isAlive())
{
Logo.interrupt();
}
super.onBackPressed();
}
Do like this:
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
// your logic
SplashActivity.this.finish();
} catch (InterruptedException e) {
finish();
}
}
});
thread.start();
}
#Override
public void onBackPressed() {
thread.interrupt();
super.onBackPressed();
}
It will work as it works in my all apps. Because when you inturrept thread then InterruptedException will be called. At that time finish your activity.
Thread.currentThread() will refer to you Main thread, since it is the currently active Thread.
You should make a field from your thread, so you can access it in your onBackPressed()method. You can then call logo.interrupt()
Use a Handler and Runnable. Instead of the inner new Runnable, create it outside as an object then pass it as a parameter to the handler. When you press back, call this method handler.removeCallbacks(runnable); to cancel the execution. Make sure to keep the variables in a global scope so you can access them anywhere.
handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
startActivity(new Intent(SplashScreenActivity.this, MainActivity.class));
finish();
}
}, SPLASH_SCREEN_TIMEOUT);
Try this code, it may help you.
private Thread Logo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.starter);
logo = new Thread() {
public void run() {
try {
if(!isInterrupted()){
sleep(1 * 1500);
Intent i = new Intent(getBaseContext(),
MainActivity.class);
startActivity(i);
finish();
}
} catch (Exception exception) {
}
}
};
Logo.start();
}
#Override
protected void onStop() {
super.onStop();
System.out.println("On Stop");
logo.interrupt();
}
...
#Override
public void onBackPressed() {
logo.interrupt();
super.onBackPressed();
}
}
I want to change the view/Activity of my app after few seconds
I mean i have created a home View for my app and i want to move to the next Activity after like 3 seconds, How should I achieve that.
Thank You
try this,
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Intent i = new Intent(FirstActivity.this,SeconActivity.class);
startActivity(i);
};
};
mHandler.sendEmptyMessageDelayed(0, 3000);
You can make slash Activity. Try this code....hop your problem will solve
public class SplashActivity extends Activity {
private final int SPLASH_DISPLAY_LENGHT = 2000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
/* Create an Intent that will start the Menu-Activity. */
Intent mainIntent = new Intent(SplashActivity.this, NightClubMain.class);
SplashActivity.this.startActivity(mainIntent);
SplashActivity.this.finish();
}
}, SPLASH_DISPLAY_LENGHT);
}
view.postDelayed(Runnable r, int delay);
You can use Timer for that.
Timer myTimer;
startTimerTask();
public void startTimerTask() {
MyTimerTask myTask = new MyTimerTask();
myTimer = new Timer();
myTimer.schedule(myTask, 0, 3000);
}
#Override
public void onPause() {
super.onPause();
try {
myTimer.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onStop() {
super.onStop();
try {
myTimer.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
class MyTimerTask extends TimerTask {
public void run() {
try {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
//
Do YOUR STUFF HERE
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
I made a splash image to show at the start of my activity..
The image show perfectly.But the problem is when i call this
public class SplashImageActivity extends Activity {
protected boolean active = true;
protected int splashTime = 5000; // time to display the splash screen in ms
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
// thread for displaying the SplashScreen
Thread splashTread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
while(active && (waited < splashTime)) {
sleep(100);
if(active) {
waited += 100;
}
}
} catch(InterruptedException e) {
// do nothing
} finally {
startActivity(new Intent(SplashImageActivity.this,Myapps.class));
finish();
//startActivity(new Intent("com.splash.com.MyApps"));
//startActivity( new Intent(getApplicationContext(), Myapps.class));
}
}
};
splashTread.start();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
active = false;
}
return true;
}
}
go for next activity the stop() does not work. And it does not go to this activity. I add all activity in manifest. The stop() shows in code like this
what's the problem?
No need to call stop() and call finish() after starting activity
finally
{
startActivity(new Intent(currentclass.this,nextActivity.class);
finish();
}
I use thread to show the Splash screen, and it works for me:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
mSplashThread = new Thread(){
#Override
public void run(){
try {
synchronized(this){
wait(4000);
}
}catch(InterruptedException ex){
}
finish();
Intent i=new Intent(getApplicationContext(),NextActivity.class);
startActivity(i);
interrupt();
}
};
mSplashThread.start();
}
Please try below code..
public class Splashscreen extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread t2 = new Thread() {
public void run() {
try {
sleep(2000);
startActivity( new Intent(getApplicationContext(), Exercise.class));
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
};
t2.start();
}
}
No need to call stop() just call finish() after starting activity
finally {
startActivity(new Intent(currentclass.this,nextActivity.class);
finish();
}
You can also use handler an postdelayed() to make a splash screen like below
public class SplashScreenActivity extends Activity{
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
final Runnable runnable = new Runnable() {
#Override
public void run() {
Intent intent=new Intent(SplashScreenActivity.this, nextActivity.class);
startActivity(intent);
finish();
}
};
handler = new Handler();
handler.postDelayed(runnable, 5000);
}
}
You will show your splash screen for 5 seconds and then move to next Activity
first thing it is not onStop of Activity so looks you are calling stop function of thread which is Deprecated that's why you are getting the strike line so use other way to stop the thread of use better way to implement the splash ........
as looks you try some thing like this link