Here is an interesting one...
I have an application I am writing for devices running android 2.3.3 and above.
It has a main activity which calls the camera via an Intent.
If the user clicks a button to launch the camera; then takes a picture; then clicks "Done" to return to the main activity - the application works fine and displays the new picture in an imageview on the main activity.
however, if the user uses the main activity in portrait orientation; then clicks the button to open the camera intent and changes the orientation to landscape; then click done to return to the main activity - the application crashes
but then...however, if the user uses the main activity in portrait orientation; then clicks the button to open the camera intent and changes the orientation to landscape; then changes the orientation back to portrait (in the camera) before clicking done to return to the main activity - then the application continues to run normally.
Stuff I have tried:
I have changed the manifest file to force the application (main activity) to be oriented in portrait (I have also removed this)
I have added this line to the main activity in an attempt to handle the re-drawing of the activity on it return from the camera intent:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
In the debug window I get errors describing nullpointer exceptions - I think this is because the views are no longer there after an orientation change for the image to be passed into unless the orientation is the same as when it was left.
I'm a bit stuck so would appreciate some advice.
When your screen orientation changes, your Activity is destroyed and recreated in the new orientation. So any variables that gained a reference during the life of the Activity will no longer refer to anything, and if you then try to access objects they refer to without re-assigning them values, you'll get a NullPointerException.
The method onSaveInstanceState() is used to save temporary data between configuration changes. This creates a Bundle which is passed to onCreate() when the Activity starts up again.
Without any code, I don't know if that's your problem, but it's worth a look.
See http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges for more information (and more accurate information than I've provided, no doubt).
hey i am not sure but try to put this property in manifest file hopefully it should work
android:configChanges="orientation|keyboardHidden"
Some Android devices like Samsung S3 and S4 have default camera surface view in Landscape mode.
When you call camera and capture image and come to your application, whether you had set orientation PORTRAIT it will first open in LANDSCAPE mode and then changes to PORTRAIT mode.
Its Android OS behaviour.
Due to this Activity Re-Creates it self. At that time you are getting Null Pointer Exception.
You can handle by setting configChanges in menifest file.
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
and you can store the data temporary in onSaveInstanceState() rightly said by #Spinner in his answer.
Related
I have the following problem on an Android 4.4.2 device, the Samsung Galaxy S4 Mini.
If I take a photo with the back-camera, my app kind of restarts and is in an inconsistent state. My main activity is recreated.
I tracked the problem and it seems that this strange behavior happens because the camera app rotates my app.
This is strange because I setup my app to work only in portrait mode. No O
orientation change is though considered.
Android correctly recognizes this misbehavior and rotates my app back, but exactly that's the problem. On orientation change the activity is recreated and my fragments state is lost.
I don't get this behavior on other phones and also when making a photo with the front camera on the S4 mini.
In my opinion that's a bug either in the android version or in the camera app.
See the following log for details:
Selfie Camera (OK):
Main activity onCreate
Fragment onCreate
User takes a photo and confirms it
onActivityResult called
Back Camera(NOT OK):
Main activity onCreate
Fragment onCreate
User takes a photo and confirms it
Fragment onCreate
Main activity onCreate (app rotated)
onActivityResult called
Fragment onCreate
Main activity onCreate (app rotated correctly back on portrait)
How can I deal with this situation?
Is there a way to stop the camera app doing this.
Or is this a known issue and a workaround exists?
You can use surface view SurfaceView Documentation which opens a camera inside the activity instead of using the camera application.
I am launching camera intent from my android application using this answer (I need user to be able to choose image from camera or from gallery)
But it seems that my whole app is recreated - activity's onCreate is called, and one of the classes, that is a singleton, has toString() value, that differs from the value before camera launch.
Here is also my activity description from android manifest:
<activity
android:name="xxx"
android:theme="#style/NoActionBarTheme"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name">
</activity>
Any ideas what is going wrong?
Make sure uncheck "Dont Keep Activities" from Developer Options in Settings.
Also check your manifest and code if your activity has correct launchMode.
On some devices(i observed samsung s3), when launch camera app, device orientation is changed to landscape & again to portrait when select captured photo to return to our app. Our activity is re-created again & we end up as just started activity.
In this case, you have to implement following pair of callbacks for activity. OnSaveInstanceState() & OnRestoreInstaceState().
You can save member variables & restore them back when come back to your activity from camera app.
e.g. imagePath (location you give for saving camera picture) can be saved & restored.
I would like to ask if the following behaviour is possible and, if it is, how I can achieve it. I need this behaviour for a very specific reason.
I have two activities, I will call them Activity A and Activity B. Now let's look at this example:
From activity A, in portrait orientation, I launch activity B (which has a fixed landscape orientation). The user, as the activity B is displayed in landscape, obviously rotates the device. The activity B is finished and activity A is resumed. The user keeps the device in landscape orientation so the orientation of the activity A will immediately be changed just after is resumed.
What I want is avoid that the orientation of the activity A changes when the user goes back to it. I want to resume the activity A in the last orientation it had and only allow orientation changes after that.
Locking the orientation is not an option as I want to allow the user to change it anytime.
The android:configChanges="orientation|screenSize" solution is neither an option as I want my activity to be re-created after an orientation change.
Do I have an option to achieve what I want?
Thanks!
EDIT: I forgot to say that saving the current orientation before the activity A is destroyed and restoring it when it is created again is not an option too. Activity A should NOT be re-created after activity B finishes.
EDIT 2: I was thinking now and I realized that I could rewrite the question from another point of view.
I would like to avoid the re-creation of the activity A when it is resumed after activity B finishes.
Afaik, when the device orientation change occurs, a message is sent to ActivityThread (with value RELAUNCH_ACTIVITY). That causes the activity A to be re-created with the new screen orientation.
I want to avoid the activity A relaunch as that would solve my problems and would keep the last orientation it had.
I don't think it is possible to do this as you've described. When the user returns from the landscape activity to your previous activity you would need to lock the orientation to portrait (in order to ignore the landscape orientation that the phone is now in). Now, if the user rotates the phone, you won't see the rotation and you won't be able to change the orientation. Since you can't really tell whether the user just rotated the phone or if the rotation is due to returning from a landscape-only activity, you can't tell these 2 conditions apart.
However, assuming that you can somehow differentiate between these 2 cases, try the following:
If you don't want Android to recreate your activity on an orientation change (even only in certain circumstances), then you will need to tell Android that you want to handle orientation changes by yourself by setting
android:configChanges="orientation|screenSize"
in the manifest.
Now you'll need to implement onConfigurationChanged() to get the behaviour that you want. In the case where your activity has launched another activity with fixed orientation, you'll want to save the current screen orientation before launching that activity. When the user returns to your activity Android won't destroy it and create a new instance it will just call onConfigurationChanged(). When you get the onConfigurationChanged() call you'll need to check if the user just rotated the device or if this is the result of returning from an orientation-locked activity. In the case where this is the return after launching another activity you can then lock the screen orientation to the previous orientation by calling setRequestedOrientation(). In the case where the user just rotated the phone, you can then either:
Recreate the activity by calling Activity.recreate() Note: this only works if you are running on API level 11 or higher
Recreate the activity by calling your own method that basically does everything necessary to recreate the Views (call setContentView()) and reset your member variables as if the activity were recreated
Recreate the activity by launching your activity again: startActivity(new Intent(this, this.class) and then calling finish() to get rid of the current instance.
You, probably could store your activity's current orientation in shared preferences in onStop() and restore it in onResume()
I have developed an application and it contains web view.
My issue
When my phone's orientation changes from portrait to landscape the whole application loads again and the web view reloads showing the first page of website.
So I am getting confused about the screen orientation or saving the data during that phase, so how do I fix it...
Yes, in Android the Activity is destroyed and recreated when your change the screen orientation. Thus you need to restore your applications state on recreation. On way is to use the callback method onSaveInstanceState() which you can use to save the state in a Bundle.
The Activities are explained here: http://developer.android.com/guide/components/activities.html and I suggest you take a look on that page for examples and more detailed instructions.
The default behaviour is to restart the activity when a configuration change happens (such as orientation change).
To override this you need to tell the system you'll handle orientation change yourself by adding this to your manifest file in your <activity> element:
android:configChanges="keyboardHidden|orientation|screenSize"
You may also want to override onConfigurationChanged which will be called when such a change happens.
See http://developer.android.com/guide/topics/manifest/activity-element.html#config
The Android Activity lifecycle clearly indicates this behaviour .
What happens
Whenever you start an Activty is gets created(after onStart() method) the
onCreate(Bundle onSavedInstance)
The variable onSavedInstance mentioned above initially recieves null as nothing is saved.
But during the orientation the whole layout hierarchy has to adjust according to the new mode from an existing mode(from portrait->landscape or vice-versa).This change may remove the previous data that you had in your activity.So to avoid such a problem(loosing data), there is a method
onConfigurationChange(Bundle saveSomething)
This method will be called for you to handle some configuration changes into this,
The default implementation will save you some data like some text in an editText.
Note This method as far the specs goes should be used to save some trivial data.
Example
Suppose you had applied a background colour to the activty layout and now you rotated it default implementation won't save it but onConfigurationChange if you want you can save it like this
saveSomething.putInt("color",1);
Inside onCreate
protected void onCreate(Bundle onSavedInstance){
if(onSavedInstance!=null){
int color=onSavedInstance.getInt("color");
if(color==1){
setBackgroundColor(Color.BLACK);
}
}
}
Add the following line inside the activity element of your manifest file you will be handling the changes in configuration
android:configChanges="keyboardHidden|orientation|screenSize"
I have activity with:
android:screenOrientation="portrait"
and code:
if(blah blah blah)
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
in activity onCreate.
1. When test on smartphone "setRequestedOrientation" causes destroy activity and create again with desired screen orientation.
2. When test on tablet device this code runs only once activity. After "setRequestedOrientation" it just continues without destroy and create again activity. This happens when start code without debuger or without breakpoint in onCreate. If I stop in onCreate function - I see in logs - destroying and onCreate again.
How to catch specific situation with tablet?
UPDATE:
- Problem with tablet occurs when 'Orientation lock' if off. If 'Orientation lock' is enabled program works in same way as in smartphone.
UPDATE2:
- Is it possible to set preffered screen orientation to whole application. So when activity starts to know desired orientation. This will make unnessesary call 'setScreenOrientation' and avoid second activity creation.
After whole day spent with this issue I made following changes in my application:
1. Every activity /without first/ are declared as android:screenOrientation="behind".
2. In first activity I set preferred screen orientation using user selected mode /from my menu.
3. I call setRequestedOrientation only when user changed mode in my menu options.
This causes activities to be created only once. Finaly :)
No.. you cannot set preffered screen orientation for whole application... instead you should call for setScreenOrientation in respective activies only... Refere this link here...
You can set
<activity ActivityName = "test_activity"
android:configChanges="orientation">
</activity>
in your android manifest file. It will not allow activity to restart on orientation change but onconfigurationchange will be called normaly.
Later you can getdisplayorientation in onconfigurationchange and set whatever you want.