When I close my app by pressing the BACK button (onBackPressed() called), the CountDownTimer doesn't stop, until it is done with counting. How can I put the CountDownTimer cancel(); in my onBackPressed()?
Because, when I quit my application (shown below with descriptions) I don't want counter toasts on my screen anymore.
On top of my code:
boolean network_connected = false;
What's in my onCreate():
if (check_network.isInternetAvailable(this)) {
network_connected = true;
new connect_task_main().execute("");
} else {
network_connected = false;
}
if (network_connected == false) {
new CountDownTimer(11000, 1000) {
public void onTick(long millisUntilFinished) {
global.toast.setText("No Internet Connection!" + "\n" + "Automatic Refresh In: " + millisUntilFinished / 1000); //set text for toast
global.toast.show(); //show toast
}
public void onFinish() {
if (network_connected == false) {
global.cancel_toast(0); //stop all toasts
finish(); //quit activity
startActivity(new Intent(main_activity.this, main_activity.class)); //start activity
} else {
}
}
}.start(); //start the countdowntimer
} else {
network_connected = true;
}
onBackPressed() method
#Override
public void onBackPressed() {
if (page_number > global.page_number_min) { //does not matter
page_number--; //does not matter
global.cancel_toast(0); //stop all toasts
network_connected = true;
finish();
} else {
global.cancel_toast(0);
network_connected = true;
finish(); //quit activity
super.onBackPressed(); //quit application
}
}
Thanks.
Create a global object of CountDownTimer eg.
On top of the main_activity class set: CountDownTimer timer; after that do the things below.
timer = new CountDownTimer(11000, 1000)
{
public void onTick(long millisUntilFinished)
{
global.toast.setText("No Internet Connection!" + "\n" + "Automatic Refresh In: " + millisUntilFinished / 1000); //set text for toast
global.toast.show(); //show toast
}
public void onFinish()
{
if (network_connected == false)
{
global.cancel_toast(0); //stop all toasts
finish(); //quit activity
startActivity(new Intent(main_activity.this, main_activity.class)); //start activity
}
else
{
}
}
}.start(); //start the countdowntimer
}
and on onBackPressed call timer.cancel(); like
#Override
public void onBackPressed()
{
if (page_number > global.page_number_min)
{ //does not matter
page_number--; //does not matter
global.cancel_toast(0); //stop all toasts
network_connected = true;
finish();
}
else
{
global.cancel_toast(0);
network_connected = true;
finish(); //quit activity
super.onBackPressed(); //quit application
}
timer.cancel();
}
Related
I write in Java music player for Android. It have a special function to trim a fragment of audio with range seekbar. After replay button is turned ON this fragment is looped. It works and selected fragment with range seekbar is played but not always as it would be necessary. Sometimes it gets out of max selected duration and goes to end of song.I can't find the place why this is happening...
Preview
Many thanks for any help and suggestions.
Here is the logic responsible for playing the song, that is activated when PLAY button is pressed:
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mMediaPlayer != null){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
playButton.setText("PLAY");
timer.shutdown();
}else{
mMediaPlayer.start();
playButton.setText("PAUSE");
timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
playProgress();
if (mMediaPlayer != null) {
if (!mSeekBar.isPressed()) {
mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
}
}
}
},10,10, TimeUnit.MILLISECONDS);
}
}
}
});
A function that regulates the playback of a fragment in rangeSeekbar
private void playProgress () {
if (mMediaPlayer.getCurrentPosition() == max) {
if(isRepeat == true) {
mMediaPlayer.seekTo(min);
}else{
mMediaPlayer.seekTo(min);
mMediaPlayer.pause();
}
}
if (mMediaPlayer.isPlaying()) {
mRunnable = new Runnable() {
#Override
public void run() {
playProgress();
}
};
mHandler.postDelayed(mRunnable, 0);
}
}
The logic responsible for "creating" the player that will form when the song is opened:
public void createMediaPlayer(Uri uri){
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
);
try {
mMediaPlayer.setDataSource(getApplicationContext(), uri);
mMediaPlayer.prepare();
title.setText(getNameFromUri(uri));
playButton.setEnabled(true);
mRangeSeekBar.setNotifyWhileDragging(true);
max = mMediaPlayer.getDuration();
mRangeSeekBar.setRangeValues(0, mMediaPlayer.getDuration());
mSeekBar.setMax(mMediaPlayer.getDuration());
long total_secs = TimeUnit.SECONDS.convert(max, TimeUnit.MILLISECONDS);
long mins = TimeUnit.MINUTES.convert(total_secs, TimeUnit.SECONDS);
long secs = total_secs - (mins*60);
duration = mins + ":" + secs;
elapse.setText("00:00 / " + duration);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
}
});
} catch (IOException e){
title.setText(e.toString());
}
}
Replay function activated by the REPLAY button
replayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//repeat = false
if(isRepeat){
isRepeat = false;
mMediaPlayer.setLooping(false);
replayButton.setText("Powtórka wyłączona");
Toast.makeText(PlayerActivity.this, "Tryb powtórki jest wyłączony", Toast.LENGTH_SHORT).show();
}else{
isRepeat = true;
mMediaPlayer.setLooping(true);
replayButton.setText("Powtórka włączona");
Toast.makeText(PlayerActivity.this, "Tryb powtórki jest włączony", Toast.LENGTH_SHORT).show();
}
//mediaPlayer.setLooping(true);
// Toast.makeText(PlayerActivity.this, "Repeat if ON", Toast.LENGTH_SHORT).show();
}
});
Here is code for this double slider that is supposed to set the beginning and end:
mRangeSeekBar.setOnRangeSeekBarChangeListener(new RangeSeekBar.OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
//mRangeSeekBar.setNotifyWhileDragging(true);
mMediaPlayer.seekTo(minValue);
max = maxValue;
min = minValue;
String infoMax = String.valueOf(max);
Log.i("MAX", infoMax);
}
});
And here for this green bar with one point representing the duration of the song:
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (mMediaPlayer != null){
int millis = mMediaPlayer.getCurrentPosition();
long total_secs = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
long mins = TimeUnit.MINUTES.convert(total_secs, TimeUnit.SECONDS);
long secs = total_secs - (mins*60);
elapse.setText(mins + ":" + secs + " / " + duration);
In my application i want a Recording Screen and for this I write below code.
After running application, there's no call to my Recorder service and after using Log.e it still does not show me logs?
I write Recording code into onActivityResult.
For this I used countDownTimer and I want, when this timer has finished, for the recording to start.
For checking if it works I used Log.e and it shows a log into onFinished code (for timer), but does not show any logs into onActivtyResult code
My Activity code:
public class RecordingActivity extends BaseActivity {
private TextView txtTesterCounter;
Thread thread;
private int counter;
private CountDownTimer countDownTimer;
private MediaProjection mMediaProjection;
private MediaProjectionManager mProjectionManager;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tester_tutorial_count_down);
init();
reverseTimer(4).start();
//Create video direction
createDir();
}
private void init() {
txtTesterCounter = findViewById(R.id.txtTesterCounter);
counter = 3;
//Acquiring media projection service to start screen mirroring
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
private CountDownTimer reverseTimer(int second) {
return countDownTimer = new CountDownTimer(second * 1000, 1000) {
#SuppressLint("SetTextI18n")
#Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished <= 800) {
onFinish();
} else {
int second = (int) (millisUntilFinished / 1000);
txtTesterCounter.setText(App.enToFa(second + ""));
}
}
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish();
}
};
}
//Create application directory
public static void createDir() {
File appDir = new File(Environment.getExternalStorageDirectory() + File.separator + ConstKeys.APPDIR);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !appDir.isDirectory()) {
appDir.mkdirs();
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("RecordingLog","OnActivityResult");
//The user has denied permission for screen mirroring. Let's notify the user
if (resultCode == RESULT_CANCELED && requestCode == ConstKeys.SCREEN_RECORD_REQUEST_CODE) {
return;
}
Intent recorderService = new Intent(this, RecorderService.class);
recorderService.setAction(ConstKeys.SCREEN_RECORDING_START);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_DATA, data);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_RESULT, resultCode);
startService(recorderService);
Log.e("RecordingLog","Recorder Service");
}
}
How can i fix this?
onActivityResult called when the child activity is finished. In your case after you start an activity, you finish the RecordingActivity.
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish(); // what does this method do?
}
I assume that finish method finished your activity. If it does so, onActivityResult will never be called because you finish parent activity.
I'm using this code:
private static long back_pressed;
#Override
public void onBackPressed() {
if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
else Toast.makeText(getBaseContext(), "click again to leave", Toast.LENGTH_SHORT).show();
back_pressed = System.currentTimeMillis();
}
It only closes the current Activity, how to close the entire app when back button is clicked twice?
You can use following:
#Override
public void onBackPressed() {
if (back_pressed + 2000 > System.currentTimeMillis()) {
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
else Toast.makeText(getBaseContext(), "click again to leave", Toast.LENGTH_SHORT).show();
back_pressed = System.currentTimeMillis();
}
i need to close and activity and start another only when the user presses back twice. I am using this code
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
On pressing back once the app exits and shows the Toast message.
It doesnt wait for the second press. How can i resolve this?
Thank you.
EDIT
Found it to be working as expected when the back button is pressed. However shows aforesaid issue when called from
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id==android.R.id.home){
onBackPressed();
}
}
you can also do this with on keydown event as code below remove backpressed
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==KeyEvent.ACTION_DOWN && keyCode==KeyEvent.KEYCODE_BACK)
{
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
return false;
}
}
return super.onKeyDown(keyCode, event);
}
Here's an example of "Press Twice to Exit" with fragments:
boolean doublePressToQuit = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
if (doublePressToQuit) {
DashBoardActivity.this.finish();
} else {
this.doublePressToQuit = true;
Toast.makeText(this, getString(R.string.quit_notification), Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doublePressToQuit = false;
}
}, 2000);
}
}
}
Include super.onBackPressed(); inside your IF statement to override the onBackPressed() event.
Try the below code, it works for me
boolean firstBackPressed = false;
.
.
.
#Override
public void onBackPressed() {
if (!firstBackPressed) {
firstBackPressed = true;
Toast.makeText(MainMenu.this, "Press back again to exit", Toast.LENGTH_SHORT).show();
} else {
super.onBackPressed();
}
}
Please find this
private boolean isShownExit;
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(Gravity.LEFT)) {
drawerLayout.closeDrawer(Gravity.LEFT);
isShownExit = false;
return;
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
if (!isShownExit) {
isShownExit = true;
showToast(this, "Press again to exit");
} else {
hideSoftKeyboardDialogDismiss(this);
startAnotherActivityHereWhichDoYouwant();
}
} else {
getSupportFragmentManager().popBackStack();
}
}
}
How can I configure the back button to be pressed twice before the app exits? I want to trigger
#Override
public void onBackPressed() {
//custom actions
//display toast "press again to quit app"
super.onBackPressed();
}
Try this:
private boolean doubleBackToExitPressedOnce = false;
#Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
}
This snippet handle also the reset state when the activityis resumed
I see this question is a bit old but I though this might help some people looking for an alternative to the answers already given.
This is how I handle backing out of my applications. If someone has a better -- or a Google suggested -- method of accomplishing this I'd like to know.
Edit -- Forgot to mention this is for Android 2.0 and up. For previous versions override onKeyDown(int keyCode, KeyEvent event) and check for keyCode == KeyEvent.KEYCODE_BACK. Here is a good link to check out.
private boolean mIsBackEligible = false;
#Override
public void onBackPressed() {
if (mIsBackEligible) {
super.onBackPressed();
} else {
mIsBackEligible = true;
new Runnable() {
// Spin up new runnable to reset the mIsBackEnabled var after 3 seconds
#Override
public void run() {
CountDownTimer cdt = new CountDownTimer(3000, 3000) {
#Override
public void onTick(long millisUntilFinished) {
// I don't want to do anything onTick
}
#Override
public void onFinish() {
mIsBackEligible = false;
}
}.start();
}
}.run(); // End Runnable()
Toast.makeText(this.getApplicationContext(),
"Press back once more to exit", Toast.LENGTH_SHORT).show();
}
}
You could do what you're asking with a global integer and just count it, if > 2, quit.
But you could take a better (IMO) approach, where you question the user if they would like to quit or not:
private void questionQuit(){
final CharSequence[] items = {"Yes, quit now", "No, cancel and go back"};
builder = new AlertDialog.Builder(mContext);
builder.setCancelable(false);
builder.setTitle("Are you sure you want to quit?");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
switch(item){
case 0:
quit();
break;
case 1:
default:
break;
}
}
}).show();
AlertDialog alert = builder.create();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK :
int i = 0 ;
if(i == 1 )
{
finish();
}
i++;
return true;
}
}
return super.onKeyDown(keyCode, event);
}