3

I have an activity. That activity contains a Fragment within a ViewPager. The fragment needs to copy files (with a ProgressDialog), but when I rotate the screen when it is busy, the activity restarts and everything just stops.

I tried adding android:configChanges="orientation|screenSize" to the AndroidManifest but that wont be a solution either because then my AdView and Toolbar won't reload on a rotation change:

Before:

After:

(Notice the difference with the Toolbar and AdView height?)

How can I keep the Activity/Fragment alive, with a working Toolbar and AdView?

Thanks

Thomas Vos
  • 12,271
  • 5
  • 33
  • 71
  • you may need 2 layouts -- http://stackoverflow.com/questions/17945130/prevent-activity-restarting-when-orientation-changes – Tasos Mar 26 '16 at 12:38
  • make the app either portrait/landscape; do the app need to allow both orientation; if not u can use this in manifest under the activity tag android:screenOrientation="portrait" – DJphy Mar 26 '16 at 12:41
  • @DJphy The app needs to be able to rotate for a good user experience. – Thomas Vos Mar 26 '16 at 12:42
  • @Tasos the layout isn't the problem, the `Toolbar` and the `Adview` need to be "recreated". – Thomas Vos Mar 26 '16 at 12:43
  • all i can do is to give the question a vote; thats what i have done now; good question; but android can't help ur use case i guess :) – DJphy Mar 26 '16 at 12:47
  • so use the orientation change function and restart the application -- http://stackoverflow.com/questions/15564614/how-to-restart-an-android-application-programmatically – Tasos Mar 26 '16 at 12:58
  • @Tasos Wouldn't that restart the whole activity? That's what I do not want because then a running `Thread` will be stopped. – Thomas Vos Mar 26 '16 at 13:00
  • yes it would, most probably you need to refresh the app – Tasos Mar 26 '16 at 13:25

1 Answers1

1

needs to copy files

what very little people usually realize about Android is that Activity and Fragment is not the place to execute long running operations, such as download stuff from internet or copying files.

Both Activity and Fragment are UI elements which can be destroyed, re-created, without much of a warning.

The correct way of dealing with such an issue is to have a Service to execute the long running operation, the Activity or Fragment should start the service and then immediately "bind" to it, executing the usual unbind and bind again upon rotation.

You can read here about service and bounds services: http://developer.android.com/guide/components/bound-services.html

After the activity (or fragment) is bound to the Service then it can register it self as a listener and the service reports back to it the status/progress of the operation.

On top of it, if the activity disconnects from the service, the service can use the command startForeground to put a notification on the device status bar and keep notifying the user on the operation progress without the need of an activity

I know that way takes a lot more code and is more complex to do. But that is the correct way of doing it.

Budius
  • 39,391
  • 16
  • 102
  • 144
  • Thanks for the answer. I'll try this and accept if it worked. – Thomas Vos Mar 26 '16 at 14:22
  • One small question. Is it better to bind it with the `Fragment` or `Activity`? – Thomas Vos Mar 26 '16 at 14:30
  • It makes no difference. Bind from the one that controls the progress bar. – Budius Mar 26 '16 at 14:36
  • Look at other options, such as loaders before you go to these lengths – brandall Mar 27 '16 at 00:39
  • @brandall That might be a good solution, but I think I'll go with a `Service`. Then I can also do the stuff in the background so the user does not have to wait for it to finish. – Thomas Vos Mar 27 '16 at 06:22
  • 1
    @brandall Loaders is for loading data in a background thread to be delivered back to the UI. On this case he needs the process to be completed regardless of the presence of the UI – Budius Mar 27 '16 at 08:06
  • @Budius I got it working, but when you rotate the screen there is a small moment it is still binding to the service. Is there a way to fix that, or should I just leave that? – Thomas Vos Mar 27 '16 at 11:23
  • @Budius And does it matter if the service is still running in the background or should I kill the service? – Thomas Vos Mar 27 '16 at 11:24
  • @Budius there is no mention of that in the question, just a problem with screen rotation? If the OP needs this process to complete, rather than cancel if the app is closed, then your suggestion is correct one. – brandall Mar 27 '16 at 11:33
  • @SuperThomasLab that's normal, there's a few milliseconds until it gets bind. Normally is fast enough that the user don't see the difference. And kill the service when it is not needed anymore – Budius Mar 27 '16 at 12:42
  • @SuperThomasLab to kill the service use the `stopSelf()` command from the service itself. – Budius Mar 27 '16 at 14:13
  • @Budius Thanks for your help. I also put a boolean in savedinstancestate so you won't notice that the dialog is gone for a spit second. – Thomas Vos Mar 27 '16 at 19:03