Activity recreated when returning from camera app
Asked Answered
K

2

5

This issue is only occurring on two older Samsung Galaxy models, but is nevertheless very reproducable.

I have a simple app that displays a photo that is taken through the device's camera app. It has one button to start that app, and processes the result in an AsyncTask to downsample it into an ImageView.

The trouble arises from the flow of the activity when returning from the camera app: for some reason, the activity is created, processes result in an AsyncTask in the onActivityResult(), is destroyed, only to immediately be recreated. Once the AsyncTask completes, it hold a reference to the incorrect/old activity.

Placing some debug statements into the various lifecycle callbacks reveals this odd behavior:

06-02 16:01:53.509: I/myapp(4437): onCreate com.myapp.PhotoActivity_@488cbef8
06-02 16:01:53.509: I/myapp(4437): onResume com.myapp.PhotoActivity_@488cbef8
06-02 16:01:58.298: I/myapp(4437): onPause com.myapp.PhotoActivity_@488cbef8
06-02 16:01:59.470: I/myapp(4437): onStop com.myapp.PhotoActivity_@488cbef8
[a photo is taken in the camera app]
06-02 16:02:10.196: I/myapp(4437): onCreate com.myapp.PhotoActivity_@4874f8b8
06-02 16:02:10.251: I/myapp(4437): onActivityResult com.myapp.PhotoActivity_@4874f8b8
06-02 16:02:10.259: I/myapp(4437): onResume com.myapp.PhotoActivity_@4874f8b8
06-02 16:02:10.712: I/myapp(4437): onPause com.myapp.PhotoActivity_@4874f8b8
06-02 16:02:10.720: I/myapp(4437): onStop com.myapp.PhotoActivity_@4874f8b8
06-02 16:02:10.923: I/myapp(4437): onCreate com.myapp.PhotoActivity_@48817118
06-02 16:02:10.931: I/myapp(4437): onResume com.myapp.PhotoActivity_@48817118
06-02 16:02:12.564: I/myapp(4437): onBitmapLoaded com.myapp.PhotoActivity_@4874f8b8

The instance of the activity on which onActivityResult() is called (note the hash codes above) no longer matches the final instance that is being displayed. When my bitmap loading through onBitmapLoaded() completes, it therefore also holds the incorrect instance.

Why is this happening, and how can I prevent the activity from being (needlessly) recreated?

Kwa answered 1/6, 2012 at 14:22 Comment(3)
This behavior does seem strange on the surface, and my guess is system memory pressure. Try adding logs in the onLowMemory() callback to see if that provides any additional information. Also, perhaps the Activity code so we can see if something is unnecessarily inflating the heap?Heritage
The heap is indeed being inflated due to decoding of the bitmap. Remarkably, the GC statements in the log only occur after the activity has been recreated (those would appear only prior to onBitmapLoaded in the log above).Kwa
I believe this problem is related to resource management and has to do with the behavior of recreating an activity as described in the documentation. It appears that the activity is resumed just long enough for it to call onSaveInstanceState(), and is subsequently destroyed for recreation. A solution to this specific problem might be to store the response from onActivityResult() into the instance state, and perform the same logic from onRestoreInstanceState().Kwa
W
4

Apparently configuration of application changes! Add logs in onDestroy and improve log in onCreate to show what is the value of Bundle savedInstanceState. if savedInstanceState is not null then configuration change enforced recreation of Activity. Adding logs in onSaveInstanceState(Bundle) could help to.

You can handle yourself configuration changes by setting Activity property android:configChanges in manifest.

Wayne answered 1/6, 2012 at 14:40 Comment(6)
Good theory, but it doesn't appear to be the case as onConfigurationChanged() is never called.Kwa
since it is called only when you set some values for android:configChanges in manifest! If this is not set then default behaviour is to recreate Activity and don't calls onConfigurationChanged. Like I wrote improve logs by checking value of savedInstanceState in onCreate add logs onSaveInstanceState!Wayne
Indeed, it seems you're right! When returning out of the camera, the activity has adopted the landscape orientation, despite that not being permitted by the manifest.Kwa
In my case (disclaimer: a very specific case), I could indeed avoid the strange recreation behavior by added configChanges="orientation" to the activity's entry in the manifest. This essentially just ignores the orientation change, which isn't a problem for my activity as it also has screenOrientation="portrait".Kwa
"nice" incoherency of Android. I recommend you to use configChanges="orientation|screenSize" since on tablets orientation changes will cause also screen size changes.Wayne
@MarekR Thanks for the helpful comment! You saved me a ton of time.Loricate
E
0

Small article about this issue, hope helps: The problem with an external camera in Android using MediaStore.ACTION_IMAGE_CAPTURE

Eponym answered 30/3, 2013 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.