Android app crashes on screen orientation change - android

I'm developing an application which will support multiple screens. I have created three layouts (large, small, medium). I'm testing it. I have two screens sign in and sign up.
In sign in it is working fine. But when I click on sign up button then I go to sign up page and if I'm in portrait mode and changes the mode the app gets crashed and there is no something like crash report in the logcat as well.

If you have not added any code like android:configChanges="orientation|keyboardHidden" to your manifest, your current activity (sign up?) will restart if you change the mode. It could be that you cannot restart the activity at that point because not all the info will be available for the activity.
(btw: your question is not completely clear, but I gather that if you change mode (portrait/landscape) in a certain activity your application crashes)

By default, android restarts your activity in case of configuration changed. You should correctly treat this restart(by saving and restoring saved instance) or as a not recommended way override onConfigurationChanged() method.

Try to run you application in debug mode, in case of crash you will see exception that cause problem.

why u used different screen for portrait n landscape , many times we can't used different screen . we written code in that way , its common for both the screens
ex. in layout parameters u used "fill_parent" for width , it is effective in both cases
In your case , you make signin and signup form,i m also make a signin and signup form and
i don't feel to make different layouts or screen.
I suggest that make common screen for both Mode.

Related

Switching Fragments or Activities (ie layouts) on Orientation Change

I have a problem with switching activities & fragments on certain device sizes, when an orientation change happens. In my case it's large screens, but it could happen with other screen sizes depending on the app. I've looked around for answers, but nothing seems to properly address this.
I have two activities, MainActivity and SubordinateActivity. MainActivity is the only entry point to the app; MainActivity launches SubordinateActivity. Each activity has its own fragment, MainFragment and SubordinateFragment. When running on normal devices, there is only enough space on the screen for one fragment at a time, regardless of the orientation. In that case, each activity will manage its own fragment. On xlarge devices, there is enough space for two fragments, regardless of the orientation. In this case, there are different layout files which allow for two fragments on the screen. Both MainFragment and SubordinateFragment are managed by MainActivity (SubordinateActivity is never used).
The trouble arises with large screens. Using landscape orientation, there's enough space for two fragments, but in portrait orientation there is not. I have the proper layout files for each. In landscape mode, MainActivity manages both fragments (as with xlarge devices) and in portrait mode, each activity manages its own fragment (as with normal devices). This produces problems in two scenarios:
SubordinateActivity is loaded in portrait mode, and the orientation changes to landscape mode. What I want: SubordinateActivity should be discarded and MainActivity should load, with the content previously displayed by SubordinateActivity, displayed in its own SubordinateFragment. Problem: SubordinateActivity stays loaded by itself in landscape mode.
MainActivity is loaded with MainFragment and SubordinateFragment in landscape mode, and the orientation switches to portrait. What I want: The content previously displayed in SubordinateFragment should now be displayed alone by SubordinateActivity. Problem: MainActivity is shown with only the content from MainFragment.
A good example of this problem is the GMail app. Here are some screen shots from that app in case it's not clear what I'm talking about. I realize the UI of the GMail app is actually more complicated than mine, but the problem is the same.
I'm sure that this is a problem others have encountered because the GMail developers encountered it too. I can't figure out what a good solution is, because every possibility seems to involve either violating the Android UI best practices, or creating some ungodly tangle between Activity code and XML layouts.
Here are some ideas I have, none of which seems really correct:
Detect the orientation change in both activities, and launch the other activity (eg, by using FLAG_ACTIVITY_CLEAR_TOP) to go back down the stack and load a previously loaded activity, with a new intent. This is a problem because the orientation change code should only be executed on large devices, which means mingling code that checks which layouts are available with the activity code.
Drop SubordinateActivity altogether. It seems a bit superfluous and MainActivity can manage the fragments itself, even on normal size devices where it can just swap MainFragment and SubordinateFragment as necessary. In the end I don't think this solves the problem since MainActivity still relies on the layout files to tell it which and how many fragments to display. This also would violate the principle that an Activity represents a discrete thing that the user does.
Here are some resources I've been looking at to try to solve this problem. As I said, this seems to be a common problem, but there seems to be no canonical Android solution. This is a bit of a shortcoming since the documentation recommends using Fragments, and every developer who does, is going to run into this problem.
Tasks and Back Stack
How to Controll Android back stack
How to start a new activity when screen orientation changes? Android
onNewIntent() lifecycle and registered listeners
Multi-pane Layouts
Switch from dual pane to single pane on orientation change maintaining fragment stack
android Fragment issue with orientation change
Fragments restore state on orientation changed
Summary: I have the multi-pane mode working for xlarge devices. The problem I'm trying to solve is switching between single pane (portrait) and multi-pane (landscape) mode on large devices that can only handle multiple panes in landscape orientation.
Kill SubordinateActivity and have the only entry point in your application be MainActivity which then decides to either fill the entire viewport with MainFragment or SubordinateFragment. You can find an example on how to do this by looking at the developer docs for the design guide you linked to.
After you do this, you can create a resource folder specific for large and landscape, res/layout/large-land as stated here and set up your layout file for MainActivity to include two fragments similar to lesson #2 in the link from the previous paragraph.
Creating that, alongside your normal XML layouts changing to what's described in that doc should automatically handle everything you're describing since an orientation change is technically an activity re-creation.

Android ICS Launcher 4.0.x cannot keep screen orientation

I've got a strange case for Android ICS Launcher 4.0.x.
Pre-condition:
A ICS device with root permission
Download Android ICS Launcher 4.0.3/4 source code (to modify and run)
Procedure:
Go to market (Play Store), download "Go Task Manager"
Open Widgets tab on Launcher, find "Mem Optimize", drag to Home screen (workspace)
Download and install "Fruit Ninja"
Create "Fruit Ninja" shortcut next to "Mem Optimize" widget on Home screen.
Execute "Fruit Ninja" and keep your phone in LANDSCAPE (hold it in your hand in this position, don't change this)
On menu screen of "Fruit Ninja", slice "Exit" , select "Yes"
Now back on Launcher Home screen, touch on "Mem Optimize" widget
Current Result:
After step 7, the screen is rotated to LANDSCAPE for a while and return to PORTRAIT.
Expectation:
After step 7, the screen should be kept in PORTRAIT.
My Tries (modify Launcher ICS source code):
Add to "Manifest.xml": android:screenOrientation="portrait" => still can't fix the problem.
Handle configuration change, android:configChanges="orientation|screenSize" => still can't fix the problem.
Use: setRequestedScreenOrientation(PORTRAIT) => still can't fix the problem.
What I've tried worked on Android 2.x; however, from 4.0.3+ , somehow it's not working as expected. Does anyone have any idea about this?
The problem is not in the Launcher. The problem is that a single configuration ( and that includes the orientation) is shared among all activities on the phone.
So if you have an activity that set the orientation to Landspace,e.g. Camera ( this is classical example where I work), this will "make" all the other activities to be on landscape too, because as I said that information is unique in system and shared among all.
This happens since the beginning of Android albeit sometimes you will not notice that because the changes are pretty fast.
To check what I am saying do the follow. Write an activity with a dialog theme such as #android:style/Theme.Holo.Dialog, so it won't cover the entire screen and you'll still be able to see the activity that was bellow. That activity must have a fixed orientation. Let's say that you set it to landscape. Then use am start on Android shell to be able to start the activity you have just created on top of any other activity. You'll see that no matter the orientation that previous activity had, as soon as you launch you test activity, the previous activity will assume the same orientation than your test activity. When you hit back, the previous activity will restore the orientation. But sometimes it might take a while, so you see things like your current result.
The stock ICS launcher has a few places where it will set the orientation to unspecified. Just search Launcher.java for setRequestedOrientation, but specifically it's either on "eng" builds or tablets. It does it in onCreate but also after a drag/drop from the appscustomize.
From Launcher.java's onCreate:
// On large interfaces, we want the screen to auto-rotate based on the current orientation
if (LauncherApplication.isScreenLarge() || Build.TYPE.contentEquals("eng")) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

Compatibility mode and Activity lifecycle

Here are some preconditions:
the app is designed for smartphones (small, medium, large screens)
the app needs to also look so-so on tablets (xlarge screens)
the app needs to give users the option to switch between "Stretch to fill screen" and "Zoom to fill screen" when run on a tablet device.
The thing is - when user switches between these modes, the current Activity restarts => goes through the full lifecycle and I don't want that :)
I know that in case of, ie, rotating the device (going from landscape mode to portrait or vice versa) we can use the android:configChange param in the Manifest to prevent the Activity from restarting. But none of the possible options work in the case of Compatibilty Modes.
Any hints, ideas to NOT have the Activity restart when switching between zoom/stretch would be great :)
I know that this answer does not suit your original problem. But why do you want not to restart the activity? The new activity creation is needed to load (maybe new) resources, adjust width / height etc. You could save the data you need to keep and retain it in the onCreate of your activity. Some ways to retain data are listed on this link:
http://developer.android.com/guide/topics/data/data-storage.html
Maybe it is an option to look at fragments. If you place a fragment inside an activity you could restart the fragment (delete / add) instead of the activity. This way you won't be dealing with the activity life-cycle.

Why not use always android:configChanges="keyboardHidden|orientation"?

I was wondering why not use android:configChanges="keyboardHidden|orientation" in every (almost every ;)) activity?
Goods:
no need to worry about your activity been rotated
it's faster
Not so nice:
need to change your layouts if they are depending on screen size (e.g. layouts with two columns or so)
Bad:
no flexible way to have different layouts on different orientation
not so good when using fragments
But if we don't use different layouts, why not?
Quick Background
By default, when certain key configuration changes happen on Android (a common example is an orientation change), Android fully restarts the running Activity to help it adjust to such changes.
When you define android:configChanges="keyboardHidden|orientation" in your AndroidManifest, you are telling Android: "Please don't do the default reset when the keyboard is pulled out, or the phone is rotated; I want to handle this myself. Yes, I know what I'm doing"
Is this a good thing? We shall soon see...
No worries?
One of the pros you start with is that there is:
no need to worry about your activity been rotated
In many cases, people mistakenly believe that when they have an error that is being generated by an orientation change ("rotation"), they can simply fix it by putting in android:configChanges="keyboardHidden|orientation".
However, android:configChanges="keyboardHidden|orientation" is nothing more than a bandaid. In truth, there are many ways a configuration change can be triggered. For example, if the user selects a new language (i.e. the locale has changed), your activity will be restarted in the same way it does by an orientation change. If you want you can view a list of all the different types of config changes.
Edit: More importantly, though, as hackbod points out in the comments, your activity will also be restarted when your app is in the background and Android decides to free up some memory by killing it. When the user comes back to your app, Android will attempt to restart the activity in the same way it does if there was some other configuration change. If you can't handle that - the user will not be happy...
In other words, using android:configChanges="keyboardHidden|orientation" is not a solution for your "worries." The right way is to code your activities so that they are happy with any restart Android throws at them. This is a good practice that will help you down the road, so get used to it.
So when should I use it?
As you mentioned there is a distinct advantage. Overwriting the default configuration change for a rotation by handling it yourself will speed things up. However, this speed does come with a price of convenience.
To put it simply, if you use the same layout for both portrait and landscape you're in good shape by doing the overwrite. Instead of a full-blown reload of the activity, the views will simply shift around to fill the remaining space.
However, if for some reason you use a different layout when the device is in landscape, the fact that Android reloads your Activity is good because it will then load up the correct layout. [If you use the override on such an Activity, and want to do some magical re-layout at runtime... well, good luck - it's far from simple]
Quick Summary
By all means, if android:configChanges="keyboardHidden|orientation" is right for you, then use it. But PLEASE be sure to test what happens when something changes, because an orientation change is not the only way a full Activity restart can be triggered.
From my point of view: If the layout is the same in both landscape and portrait mode - you might aswell disable one of the two in your app.
The reason why I state this is that I as a user expect the app to provide me with some benefit, when I change orientation. If it doesn't matter how I hold my phone, then I don't need the choice.
Take for instance an app where you have a ListView, and upon clicking a ListItem you want to be shown a detailed view for that item. In landscape you would od this by dividing the screen in two, having the ListView on the left and the detailed view on the right. In Portrait you would have the list in one screen and then change the screen to the detailed view when a ListItem is selected. In that case orientation change makes sense as well as different layouts.
I don see why.... occasional restarts are ok in my opinion... configChanges handles most cases for me... well maybe in some types of applications this can be problem but it depends really on type of app and how you restore state when app restarts... When one of my app restarts user is logged back and last activity opens by my code and user jus loses some steps to go back where he was but not big deal.. In other some state is always persisted and some state is always restored on restart. When activity restarted it had to be that app have not been used or something... so no problem at all... In game for example this can be problem maybe or in some other type of app I don't know...
I say that when you do it this way applications just works fine under normal circumstances. And code is much more readable without ton of logic needed for saving and restoring where u just can make new bugs and have to maintain it all the time... sure if android gets out of power and kill you application window it lose the context and starts again, but this happen just in special situations and on newer devices I belive this is more and more rare...
So kill me, but I use this across applications quite successfully...
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
But I understand that for some special kind of applications it may be not good way but most of apps can live with this just OK.
Yeah I think pausing will make it quicker than releasing the player. Still have the pause though.
Have now found a solution that won't pause the song.
State in the manifest that you will handle the config change for screen orientation and then use the onConfigurationChanged method to load the layout file. By doing this in logCat I can see onPause, onCreate & onResume aren't called, and therefore the song isn't paused.
update the manifest to handle the orientation.
android:configChanges="orientation|screenSize"
add this code
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
}

appWidget Orientation Code

I have code in an appwidget that I want to run when the phone's orientation changes on the home screen, ie like when the keyboard flips out. I have an image that I want to change in an imageview in my appwidget. I can't use different layouts linked to the orientation (ie "layout" and "layout-land") because I don't know the name of the image file until runtime, it is created at runtime. Is there anyway to trigger code to run only if the home screen is shown, my appwidget is active and the orientation just changed?
I could listen for a configuration_change broadcast but that will run everytime the phone switches to landscape or portrait and I only want it to happen when the homescreen is shown. I cannot think of any good way in android to do this. Thanks
Ryan
There isn't a good way of doing this for images generated at runtime.
One approach would be to build both versions of the image and have two ImageViews that are visible depending on the layout/layout-land being used. (So the RemoteViews would update both ImageViews, but only the correct one would be visible.)
Jeff, what is the reason for this limitation ? I would love to be able to use images generated at runtime, or construct the RemoteView on the runtime as well, rather than use the precompiled XML - this is so inflexible.
There is more info at http://groups.google.com/group/android-developers/browse_thread/thread/0eb7c016be05e0b9/d31b312e2fa8530d
Basically update the widget from onConfigurationChanged() in an Activity and add android:configChanges="orientation" for that Activity in your manifest. Bad thing is, this doesn't cover all use cases.

Categories

Resources