Activity not paused quickly enough - java

In my AppCompatActivity, I am showing an AlertDialog at a specific event.
Once the AlertDialog is shown, the user should not be able to click on anything in my AppCompatActivity anymore.
I tried to disable the activity in onPause(): getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
And to check whether it is not paused: getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
But it seems that onPause() is not called quickly enough for that.
I could set a static boolean to true whenever I pause the AppCompatActivity, set it on false in onResume() and check it in every single onClickListener/onTouchListener etc., but is there a better way to do it?
Every help is appreciated!
Edit:
Thanks for your comments! I found out, that when I am clicking on the screen while the UI thread is started (for opening the AlertDialog), the click is put in a queue. That's why the click event is executed while the AlertDialog is running. Do I need to save the AlertDialog and check if it is running or is there a better way?

I believe that you should let us know more about your code. However, I think that I can guess what you're saying. There is a setEnabled(false) method for every view component in android, and if you call it on a view component java object, it'll be disabled and no longer clickable. So you can simply disable your components whenever you want to show the AlertDialog and then enable them again by calling setEnabled(true) if you wish. I'm pretty sure pausing the activity is not what you should do. Because doing it manually, is not best practice anyway, at all.

I ended up saving an instance and writing a method to check if the Activity should not be active:
private void canRun() {
return (dialog == null || !dialog.isShowing()) && getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
}

Related

Confirm before dismissing DialogFragment in Android

I have defined a method for my DialogFragment which will pop another (alert) dialog, where I confirm that the user wants to dismiss the DialogFragment. If that is the case, then I call DialogFragment.dismiss(). If not, the dismissal of the DialogFragment should simply be ignored and the user should return to it as was before.
This method (say, confirmCancel()) is used for the 'Cancel' button at the bottom of the DialogFragment. Since I also want this to appear when the user presses the back button, or when they touch outside the DialogFragment, I have set confirmCancel as its onCancelListener (of course, I have also used getDialog().setCanceledOnTouchOutside(true) too).
This is the code for confirmCancel():
public void confirmCancel()
{
(new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.ic_baseline_warning_24)
.setTitle("Discard changes")
.setMessage("Are you sure you want to discard changes and go back?")
.setPositiveButton("Yes", ( dialogInterface, i ) -> dismiss())
.setNegativeButton("No", ( dialogInterface, i ) -> {})
.show()).setCanceledOnTouchOutside(true);
}
This works almost perfectly, except for the fact that by the time the AlertDialog is shown on screen, the DialogFragment is already dismissed, and the actions taken in the AlertDialog are of no use at all.
So what I need now is a way to 'cancel' the dismissal of the DialogFragment, or a method that is called before the its dismissal. How do I solve this?
P.S.: getDialog().setCancelable(false) is not helpful to me since I do want the dialog to be cancelled; it's just that I want it cancelled conditionally.
Neither DialogFragment nor Dialog offer a condition that is checked before a cancel/dismiss event, that you can set.
They only offer listeners that are notified after said events have been fired, when the damage has already been done.
I have combed through the source code and have determined their is no way to force it into a state to ignore the first cancel/dismiss call but still allow the listeners to fire so you can catch the event, I have considered reflection to mess with fields, but it got to messy. I also tried forcing exceptions, to create invalid states, but there are no invalid states that would allow the functionality you want.
Here are the two sources.
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Dialog.java
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-activity-release/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
You could play with the containing Activity's Window to handle touch events and send them back to the DialogFragment using a FragmentResultListener, ie the DialogFragment is set to non-cancelable and when the user touches the outside the
Activity picks it up and calls setFragmentResult to send it back to the DialogFragment. This may or may not work depending on how dialogs detect/receive outside touch events, does it consume them or let them fall through, when its non-cancalable.
The easiest solution by far is to copy the source code above, probably just the DialogFragment and make your own to solve this problem.
OR OR OR
I'm totally missing the most obvious solution.

Android - calling finish() on activity does not stop it from running

So I've looked up similar problems to this, and have followed the advice in those threads, but it seems to give me no change in behavior.
So I'm writing an app that essentially notifies the user when they're going too fast or too slow based on GPS onLocationChanged() calls. I overrided the onBackPressed() method to finish() and return but the activity continues to run in the background when I go back to the main activity.
To be clear, I DO want the activity to run when the app is minimized or screen is off. I only want it to stop when the user goes back to the menu (IE, hits the back button)
Here's the link to the class on pastebin:
http://pastebin.com/V7z5c3HH
Thanks for your help! =D
Unsubscribe your location listener in the onDestroy method.
However, what you need for your GPS processing is probably a Service, not an Activity.
You need to remove the updates for that listener.
#Override
protected void onDestroy() {
locationManager.removeUpdates(locationListener);
super.onDestroy();
}

Android screensaver in app if it's not used

I created an android app. The screen never turns off:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Now I want to show a picture if the screen is not pressed for 5 minutes or something else. The app should not be closed, when pressing on the image the app should be open.
How can I realize that?
I would discourage you from taking this approach. Users expect to have a consistent user experience between various apps on their devices, and likely have a preference to how their device sleeps, either by having specified a sleep timeout or displaying a daydream as introduced in Android 4.2.
If you'd like to provide users with the option to display a screensaver associated with your app, I suggest including a Daydream in your app and otherwise acknowledging the user's preferences.
That being said, if you cannot use Daydream, you could observe if the app is being used or not. Two things come to mind:
Have the root view of your activity intercept touch events to observe if any of its children have been touched.
Observe the activity's onPause() and onResume() to acknowledge that the activity is still being displayed.
You could then invoke a Runnable by posting it to a view using postDelayed(Runnable action, long delayMillis), being wary to remove it when the activity is paused or the timer should be reset using removeCallbacks(Runnable).
I solved the problem!!!
I used that event:
public boolean dispatchTouchEvent(MotionEvent ev)
{
super.dispatchTouchEvent(ev);
// cancel my Timer
return true;
}
Thanks!!

Exit from Application android

I tried some way to exit from application but each method just minimizes the app. I'd like to close down the app not minimize it. Exit Button is in MainAcitivity.
For now i'm calling this function, it works but not as i need.
public void AppExit()
{
this.finish();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
I know this question is asked a lot but i can't find solution exactly what i need.
After your advice i use this function
public void AppExit()
{
System.exit(0);
finish();
}
If you want to exit why you are starting activity again.
use only this.finish(), remove other statements.
Take look at activity life cycle for more info
Few things. In your code you can put finish(); after startActivity, this may help (did for me).
How it should be done however is the way the guidelines have it already. The back button does close the app. If you press the back button and then restart your app, you will be on the very first page activity, not where you left off.
In regards to the back button, you can Override it to control what it does if you are not happy with it. You can put your code in there and when the users presses the back button it will execute the code. Users are more accustomed to pressing the back button rather than a button within a layout (which I presume is what you may be doing).
This might be helpful if you are sticking to what you have: How to clear the Android Stack of activities?
Try with this single line code :
System.exit(0);
You need to navigate to your main activity with Intent.FLAG_ACTIVITY_CLEAR_TOP, pass it some data that it will know that you are exiting the application. And just call finish from your main activity.
Another suggestion is Kamlesh Arya answer. How ever it is a bad practice as it will not destroy the activity stack, and next time the use lunch your application it will not start from the main activity but from the last active activity.

Android how to update textview on UI

I have a textview in an activity. I am changing its visibility.
if(CheckBookmark(Constants.versusHeading.get(curVCount))) {
bookmark.setVisibility(View.VISIBLE);
bookmark.setText("Bookmarked");
}
else {
bookmark.setVisibility(View.GONE);
}
but UI is not updated. I have tried bookmark.invalidate() and bookmark.postinvalidate() but didn't work. If I change textview visibility how do I refresh UI? Activity is still alive and running.
Okay I think I need to add more details. My bad should have mentioned in the first place....Initially when activity is displayed bookmark is visible but have no text.
Then user creates a bookmark. Checkbookmark returns true if bookmark is successfully created. In that case I add bookmarked as text. I am setting it to visible as it wasn't working. If I quit activity and come back then bookmark text is displayed.
In general it should work the way you have it. The UI will update.
You need to make sure your if else is returning correctly.
Try setting the textview to VISIBILE intially to see if it appears and then try to toggle the TextView's visibility
As Pramod says, try
setVisibility(View.INVISIBLE)
instead of
setVisibility(View.GONE)

Categories