In my app when i do some long work i'm using a Progress Dialog while the work isn't finished.
I'm looking for it in every place but without sucess. Everything that i founded is all about saving user interface elements states.
Then, i would like to know how i can save progress dialog state correctly ?
I want this working because when the orientation screen change the app crashes.
Shoul i use onSaveInstanceState() method ? How ? I try using saving as a bundle but without succes...
Any advice would be nice...
thanks
I think, your dialog crashes on orientation change because you are not using
#Override
protected Dialog onCreateDialog(int dialogID, Bundle args)
and
showDialog(dialogID);
to show your dialog.
I had the same problem with an alert dialog. As I see it, if you don't create dialog that way, it becomes linked to your activity, and when activity is dead, the system finds that a dialog still try to access that dead activity, not new one.
You need to add this to the manifest file for the activity in which you are showing the dialog:
android:configChanges="keyboardHidden|orientation"
to handle the screen orientation you must use onRetainNonConfigurationInstance()
you can find a more extensive explanation about screen orientation here: Faster Screen Orientation.
The way I do this in my applications is overriding the onConfigurationChanged() method in the Activity like so:
#Override
public void onConfigurationChanged(Configuration config) {
//Just switch the layout without respawning the activity
super.onConfigurationChanged(config);
}
This hasn't given me any issues as of yet and my Activity doesn't reload or restart when the orientation is changed.
Related
I have an Activity that I have already implemented sometime ago.
It involves around making a in app purchase, so all the logic is relatively self contained. it doesn't need to care about anything else.
Now, i wish to make that Activity to optionally show up in a dialog in some other activity. Is there a quick way to do that? I still need to keep the old behavior however, where the activity show up as a regular screen.
So is there someway that I could launch the activity with that make it show up as a dialog?
Thanks
You cant show activity as dialog.
Your options are:
1: Open the other activity with some boolean extra like "showDialog", true
Intent intent = new Intent(this, OtherActivity.class);
intent.putExtra("showDialog", true);
and in the other activity in (for example) onCreate:
Boolean showDialog = getIntent().getExtras().getBoolean("showDialog");
if (showDialog) {
// Code to show dialog
}
2: Create a DialogFragment and show it in your original activity. This custom DialogFragment you can use on both activities
https://guides.codepath.com/android/Using-DialogFragment
Probably your cleanest option depending on how complex your Activity is, is to create a new DialogFragment based on your current activity.
A DialogFragment is basically a Fragment, so has a relatively similar set of lifecycle callbacks to your Activity so it shouldn't be too difficult to re-work as a DialogFragment.
If the in-app purchase framework has specific callback requirements with an Activity then you will need to take that into account.
Another separate option would be to mock the appearance of a Dialog, by creating an Activity that may be transparent around the border of the main content.
Just Inflate the layout one button click on onCreate Method.
WhAT I WILL SUGGEST IS try alert box and in place of normal layout inflate you activity layout .
these might help
The easiest way to do that is to apply a dialog theme to the activity:
<activity android:theme="#style/Theme.AppCompat.Dialog" />
Or in the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_Dialog);
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
}
You can customize parameters of the theme in styles.xml, e.g. dim enabled/disabled, click outside behavior.
The crucial point is to perform setTheme() before super.onCreate(), because Theme is immutable, once set through super.onCreate() it cannot be mutated later.
I have seen the following links before posting this question
http://www.devx.com/wireless/Article/40792/1954
Saving Android Activity state using Save Instance State
http://www.gitshah.com/2011/03/how-to-handle-screen-orientation_28.html
How to save state during orientation change in Android if the state is made of my classes?
I am not getting how should i override the following function :
#Override
public Object onRetainNonConfigurationInstance() {
return someExpensiveObject;
}
In my application i have layout with one editext visible and other editext get visible when the data of first editext validates to true.I have set the visbility of all other editextes and textviews to false and make them visible after validating.
So in my activity if the screen orientation is changed then all the items having android:visibility="false" get invisible.
I have also came to know that when our activities screen orientation changes it calls onStop() followed by onDestroy() and then again starts a fresh activity by calling onCreate()
This is the cause .. But i am not getting how to resolve it ..
Here You can see the screenshots of my application :
in this image all fields are loaded
and in another image when the screen orientation is changed to landscape they are all gone
Any link to tutorial or piece of code will be highly appreciable.
And also my application crashes when a progress dialog is shown up and i try to change screen orientation.How to handle this ??
Thanks
Well if you have the same layout for both screens then there is no need to do so just add below line in your manifest in Activity node
android:configChanges="keyboardHidden|orientation"
for Android 3.2 (API level 13) and newer:
android:configChanges="keyboardHidden|orientation|screenSize"
because the "screen size" also changes when the device switches between portrait and landscape orientation.
From documentation here: http://developer.android.com/guide/topics/manifest/activity-element.html
There is another possibility using which you can keep the state as it is even on Orientation change using the onConfigurationChanged(Configuration newConfig).
Called by the system when the device configuration changes while your activity is running. Note that this will only be called if you have selected configurations you would like to handle with the configChanges attribute in your manifest. If any configuration change occurs that is not selected to be reported by that attribute, then instead of reporting it the system will stop and restart the activity (to have it launched with the new configuration).
At the time that this function has been called, your Resources object will have been updated to return resource values matching the new configuration.
There are 2 ways of doing this, the first one is in the AndroidManifest.xml file. You can add this to your activity's tag. This documentation will give you an in depth explanation, but put simply it uses these values and tells the activity not to restart when one of these values changes.
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
And the second one is: overriding onSaveInstanceState and onRestoreInstanceState. This method requires some more effort, but arguably is better. onSaveInstanceState saves the values set (manually by the developer) from the activity before it's killed, and onRestoreInstanceState restores that information after onStart() Refer to the official documentation for a more in depth look. You don't have to implement onRestoreInstanceState, but that would involve sticking that code in onCreate().
In my sample code below, I am saving 2 int values, the current position of the spinner as well as a radio button.
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
spinPosition = options.getSelectedItemPosition();
savedInstanceState.putInt(Constants.KEY, spinPosition);
savedInstanceState.putInt(Constants.KEY_RADIO, radioPosition);
super.onSaveInstanceState(savedInstanceState);
}
// And we restore those values with `getInt`, then we can pass those stored values into the spinner and radio button group, for example, to select the same values that we saved earlier.
#Override
public void onRestoreInstanceState(#NotNull Bundle savedInstanceState) {
spinPosition = savedInstanceState.getInt(Constants.KEY);
radioPosition = savedInstanceState.getInt(Constants.KEY_RADIO);
options.setSelection(spinPosition, true);
type.check(radioPosition);
super.onRestoreInstanceState(savedInstanceState);
}
I have a class that extends android.app.Dialog, the layout is done in an xml file, and the setup (button listeners, etc) is done on the onCreate method. My problem is that whenever the dialog is displayed, then dismissed, and displayed again, the Editable TextViews are still populated with the information that was displayed previously. What is the common way to clear these text fields? Remember - this is a separate class that extends Dialog - so there is no 'onDialogCreate' like Activity has.
Or, perhaps I am extending the wrong class? There is just a lot of processing being done, and do not want to have all the code in the main Activity. I would like it to be in a separate Class. I tried to extend AlertDialog, but it does not create the border like Dialog does. Any help would be great.
The dialog is shown via the Activity:
protected Dialog onCreateDialog(int id) {
switch(id){
case DIALOG_NEW_SAFE:
return(new NewSafeDialog(this));
default:
return(null);
}
}
onCreateDialog(..) caches the dialog which means the same instance is reused.
3 ways to fix the undesired behavior off my head:
Override onPrepareDialog(..), use findViewById(..) to get whatever you want to clear, clear it.
Don't rely on managed dialogs at all, do new NewSafeDialog(this).show() each time you want to show the dialog.
Add onCancelListener(..), onDismissListener(..) inside your custom dialog that would call a method to clear itself.
The good way to create a dialog is by using showDialog() as you did so don't change it.
The good and easy way to force deletion of a dialog in order to make your creation code recalled again is:
void removeDialog (int id)
So if you simply do the following, it's gonna work ;)
removeDialog(DIALOG_NEW_SAFE);
showDialog(DIALOG_NEW_SAFE);
Try clearing the text in the constructor of the NewSafeDialog i.e. your dialog class.
1) I launch a background task (via AsyncTask)
new FindJourneyTask().execute(); // FindJourneyTask extends AsyncTask
2) Still in the main thread (just before new thread is launched) I create a dialog with showDialog(dialogId)
// this method is in FindJourneyTask
protected void onPreExecute() {
showDialog(DIALOG_FINDING_JOURNEY);
}
3) Screen orientation changes and the Activity is recreated
4) How can I now dismiss the dialog from the FindJourneyTask? Calling dismissDialog(dialogId) does nothing.
// this method is in FindJourneyTask
protected void onPostExecute(FindJourneyResult result) {
dismissDialog(DIALOG_FINDING_JOURNEY); // does nothing
}
This is a common problem, and there are no real good solutions. The issue is that on screen orientation change, the entire Activity is destroyed and recreated. At the same time, the Dialog you previously had is re-created in the new Activity, but the old background task still refers to the old Activity when it tries to dismiss the dialog. The result is that it dismisses a dialog which was long ago destroyed, rather than dismissing the dialog the new orientation created.
There are three basic solutions:
Override the default orientation-handling code so that your Activity is not destroyed upon rotation. This is probably the least satisfactory answer, as it blocks a lot of code that is automatically run upon orientation changes.
Create a static member variable of your Activity that references the Activity itself, so you can call STATIC_ACTIVITY_VARIABLE.dismissDialog().
Code a solution in which the background task keeps track of the current Activity and updates itself as necessary.
These three solutions are discussed at length here: http://groups.google.com/group/android-developers/browse_thread/thread/bf046b95cf38832d/
There is a better solution to this problem now which involves using fragments.
If you create a dialog using DialogFragment, then this fragment will be responsible for maintaining your dialog's lifecycle. When you show a dialog, you supply a tag for your fragment (DialogFragment.show()). When you need to access your dialog, you just look for the necessary DialogFragment using FragmentManager.findFragmentByTag instead of having a reference to the dialog itself.
This way if device changes orientation, you will get a new fragment instead of the old one, and everything will work.
Here's some code based also in #peresisUser answer:
public void onSaveInstanceState(Bundle outState) {
AppCompatActivity activity = (AppCompatActivity) context;
FragmentManager fragmentManager = activity.getSupportFragmentManager();
DialogFragment dialogFragment = (DialogFragment) fragmentManager.findFragmentByTag("your_dialog_tag");
if(dialogFragment!=null) {
Dialog dialog = dialogFragment.getDialog();
if(dialog!=null && dialog.isShowing()) {
dialogFragment.dismiss();
}
}
}
This is long after the question was asked and answered, but i stumbled upon this problem also and wanted to share my solution...
I check in onSavedInstance() which runs on orientation change, whether the dialog is showing or not with dialog.isShowing(), and pass it into outState variable. Then in your onCreate(), you check this var if it's true. If it is, you simply dismiss your dialog with dialog.dismiss()
Hope this helps others :()
I tried adding setRetainInstance(true); on OnCreate function of DialogFragment. This will cause dialog to dismiss on rotation.
Just add this line to specific activity in your Manifest to solve this problem android:configChanges="orientation|screenSize|smallestScreenSize"
like this,
<activity
android:name=".PDFTools"
android:exported="false"
android:configChanges="orientation|screenSize|smallestScreenSize"
android:theme="#style/Theme.DocScanner.NoActionBar" />
In my activity, I'd like to show simple info dialogs, stuff like:
new AlertDialog.Builder(context).setMessage(message).show();
if I do that, the dialog will leak when I rotate that phone (not to mention it will disappear as well, so the user may miss it). I can use the managed dialogs, but I'm not sure how you use it sensibly for these types of short messages? Looks like you have to do this:
showDialog(SOME_DLG_ID);
...
#Override
onCreateDialog(int id) {
if (id == SOME_DLG_ID) {
new AlertDialog.Builder(context).setMessage(message).show();
}
}
there's no way to pass what the message should be into onCreateDialog since its an override method. I'd hate to make a member variable of the parent activity that just stores whatever the current message should be. How do you all do it?
Thanks
if I do that, the dialog will leak
when I rotate that phone (not to
mention it will disappear as well, so
the user may miss it)
You can add
<activity
android:configChanges="orientation|keyboardHidden"
>
to your AndroidManifest.xml to prevent restarting the activity when the phone rotates. I am using it in my app and my AlertDialog survives the rotation of phone.
You can implement Activity.onPrepareDialog(int, Dialog) to switch out the message before the dialog is shown on the screen. So you could do something like:
#Override protected void onPrepareDialog(int id, Dialog dialog) {
if (id == SOME_DLG_ID) {
((AlertDialog) dialog).setMessage(message);
}
}
You'd still have to keep track of the message you're current showing in your activity, but at least this way, you're not creating a Dialog object for each message you want to show.
Using DialogFragment to manage the dialog ensures that it correctly handles lifecycle events such as when the user rotates the screen or presses the Back button.