I have an activity that runs the following:
private void loop() {
// TODO Auto-generated method stub
handler.postDelayed(new Runnable() {
public void run() {
DBListern();
handler.postDelayed(this, 5000);
}
}, 5000);
}
I would like to cancel this handle on back button:
public boolean onBackPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
handler.removeCallbacksAndMessages(null);
return true;
}
return super.onKeyDown(keyCode, event);
}
The handler is still running after back button is pressed, how can I stop it?
First of all the right name of the method you are looking for is onBackPressed(). So your code is simply not called by framework. Try
#Override
public void onBackPressed() {
handler.removeCallbacksAndMessages(null);
super.onBackPressed();
}
You need to do this way:
#Override
public void onBackPressed() {
if(mHandler!=null){
mHandler.removeCallbacks(mRunnable);
}
super.onBackPressed();
}
Reason: You need to manually remove callback of Runnable from Handler onBackPress.
Hope this would help you.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loop();
}
private void loop() {
// TODO Auto-generated method stub
handler.postDelayed(new Runnable() {
public void run() {
Log.i(TAG,"run");
handler.postDelayed(this, 5000);
}
}, 5000);
}
Handler handler = new Handler();
#Override
public void onBackPressed() {
super.onBackPressed();
handler.removeCallbacksAndMessages(null);
}
}
this works for me.
For removed handler messeges, you need set not null in method parametrs. Its Must bee lenk on object , or message type, what do yo like to remove. And why you made this chek
if (keyCode == KeyEvent.KEYCODE_BACK) {
its realy nesesary?
Related
Below is my code to exit my app.
Since I have more than 1 activity, where should I put exitBy2Click() so it can be use for all activities?
I tried to create a new class called "Global", and public exitBy2Click(), but Toast.makeText(this,... not work.
Thanks.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
exitBy2Click();
}
return false;
}
private static Boolean isExit = false;
private void exitBy2Click() {
Timer tExit = null;
if (!isExit) {
isExit = true;
Toast.makeText(this, "click again to quit", Toast.LENGTH_SHORT).show();
tExit = new Timer();
tExit.schedule(new TimerTask() {
#Override
public void run() {
isExit = false;
}
}, 2000);
} else {
finish();
System.exit(0);
}
}
Checking your method, I think that best option would be Inheritance..
Note on example below that you can override onBackPressed() instead of onKeyDown()
public class BaseActivity extends Activity {
private static Boolean isExit = false;
#Override
public void onBackPressed() {
exitBy2Click();
}
public void exitBy2Click() {
Timer tExit = null;
if (!isExit) {
isExit = true;
Toast.makeText(this, "click again to quit", Toast.LENGTH_SHORT).show();
tExit = new Timer();
tExit.schedule(new TimerTask() {
#Override
public void run() {
isExit = false;
}
}, 2000);
} else {
finish();
System.exit(0);
}
}
}
Then, your "real" activities can extends that BaseActivity and this way, onKeyDown and exitBy2Click will be commom to all classes.
public class MainActivity extends BaseActivity {
#override
public void onCreate(Bundle savedInstance) {
}
}
public class SecundaryActivity extends BaseActivity {
#override
public void onCreate(Bundle savedInstance) {
}
}
//ETC
The best place to put this code is literally "nowhere".
Forcibly terminating an Android app is not recommended, and calling System.exit is definitely not something you should ever do in an Android app.
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 want to implement the function : if user dosen't checked the autoLogin CheckBox, clear the login user information and logout when the application is quit normally or force closed(clean the memeory).
I write the code clearAutoStart() to clear user information both in finish() and OnDestory().
When the user press back button twice, the finish() will execute, and will logout success. But as you know, if the application force closed, OnDestory() will not execute all the time. So in this situation, it will not logout success.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
exitBy2Click(); //quit normal
}
return false;
}
private static Boolean isExit = false;
private void exitBy2Click() {
Timer tExit = null;
if (isExit == false) {
isExit = true;
Toast.makeText(this, "press again to quit", Toast.LENGTH_SHORT).show();
tExit = new Timer();
tExit.schedule(new TimerTask() {
#Override
public void run() {
isExit = false;
}
}, 2000);
} else {
finish();
System.exit(0);
}
}
#Override
protected void onDestroy() {
clearAutoStart();
super.onDestroy();
}
#Override
public void finish() {
clearAutoStart();
super.finish();
}
#Override
protected void onStop() {
Log.i("ws", "---->>SmarterActivity onStop");
super.onStop();
}
public void clearAutoStart() {
RememberUser rememberUser = RememberUser.getInstance();
if (rememberUser.getIsAutoStart() == false) {
Log.i("ws", "---->>clearAutoStart getIsAutoStart false ");
UserLocalStore userLocalStore = UserLocalStore.getInstance();
userLocalStore.setUserLoggedIn(false);
userLocalStore.clearUserData();
Log.i("ws", "---->>clearAutoStart getIsAutoStart false OK ");
} else {
Log.i("ws", "---->>clearAutoStart getIsAutoStart true ");
}
}
I try to add the clearAutoStart() in onStop(), but this means if I press the HOME button , the application will logout.
When you press HOME onPause() is called and then onStop().
So you can put a member variable that keep the track of what is happening:
#Override
protected void onPause() {
mIsPause = true;
super.onPause();
}
#Override
protected void onStop() {
Log.i("ws", "---->>SmarterActivity onStop");
if(!mIsPause)
clearAutoStart();
super.onStop();
}
I have a splash activity that is displayed for 2 seconds before opening the main activity.
If the user presses the back button while the splash activity is being displayed, the splash activity closes. But a short time later, the main activity [which was triggered by the splash activity] opens up.
I don't want this to happen. I want the entire application to close if the back button is pressed while the splash screen is being displayed.
How do I accomplish this?
Edit:
below is my code for splash activity:
public class Splash2 extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// fullscreen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// fading transition between activities
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
setContentView(R.layout.activity_splash2);
Thread timer = new Thread() {
public void run() {
try {
sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent open = new Intent(
"com.example.puzzletimer.HOMESCREEN");
startActivity(open);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
Just add this code to your SplashActivity...
#Override
public void onBackPressed() {
super.onBackPressed();
android.os.Process.killProcess(android.os.Process.myPid());
}
or maintain one flag to determine to start Activity or not in Thread...
public class Splash2 extends Activity {
private volatile boolean interrupt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// fullscreen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// fading transition between activities
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
setContentView(R.layout.activity_splash2);
Thread timer = new Thread() {
public void run() {
try {
sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (!interrupt) {
Intent open = new Intent(
"com.example.puzzletimer.HOMESCREEN");
startActivity(open);
}
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
#Override
public void onBackPressed() {
super.onBackPressed();
interrupt = true;
}
}
Try this-
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
Another way to do it is with runnable:
Declare Handler and Runnable in your Splash2 activity:
private Handler handler;
private Runnable startMain;
In onCreate(), initialize them and set the runnable to fire in 1.5 secs:
handler = new Handler();
startMain = new Runnable() {
#Override
public void run() {
Intent open = new Intent("com.example.puzzletimer.HOMESCREEN");
startActivity(open);
}
};
handler.postDelayed(startMain, 1500);
Override onBackPressed() and simply cancel runnable:
#Override
public void onBackPressed() {
handler.removeCallbacks(startMain);
super.onBackPressed();
}
That's it. If back key is pressed, it cancels runnable and your homescreen won't run.
In the app i m looking for the users location using gps.In the Async pre execute method i m showing a toast.I want that while i show that toast the back button should be disabled
aftr the location is found i want to enable the back button in the post execute!
to disable the back button i have used.But this is not working
OnKeyListener mainScreenKeyListener = new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
boolean disableEvent = false;
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
disableEvent = true;
}
return disableEvent;
}
};
You can declare global variable disableEvent by
final boolean disableEvent;
Your Preexecute method can set it to false by
disableEvent = false;
Your Postexecute method can set it to true by
disableEvent = true;
You can override onBackPressed as shown below:
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
if (disableEvent)
{
// do nothing
}
else
{
// do something
}
}
Here you go
Assign one static variable.and set its value to "NO" in onPreExecute.
in onPostExecute assign its value to "YES".
And write following code in your onBackPressed.
#Override
public void onBackPressed() {
if (decision.equals("NO")) { //Here no means dont allow user to go back
} else {
super.onBackPressed(); // Process Back key default behavior.
}
}
hi for disable you simply call the above function
public void onBackPressed()
{
}
for enable
public void onBackPressed()
{
super.onBackPressed();
super.finish();
//Intent
}
if you want both set flag inside the function
override onBackPress method in your activity
Class A
{
public static boolean isToastShown=false;
#Override
public void onBackPressed() {
if(isToastShown==true)
return false;
else
super.onBackPressed();
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Show your toast here
A.isToastShown=true;
new CountDownTimer(2000,2000) {
#Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
A.isToastShown=false;
}
}.start();
}