20

On Android 12,

  1. If we open an activity

  2. Go to the home screen of the phone to change the wallpaper

  3. Switch back to our activity, the activity restarts.

It seems it is related to the Material You theming.

I would like to disable the restarting of activity when my app comes to the foreground. Is there a way?

q126y
  • 1,589
  • 4
  • 18
  • 50
  • 3
    Most likely this is a configuration change, no different than screen rotation, dark mode toggle, locale change, or any of the other configuration change sources. How are you handling configuration changes overall? – CommonsWare Oct 27 '21 at 15:55
  • @CommonsWare I thought the same, and have all config values under activity tag in manifest file, but the activity is still restarting. `android:configChanges="orientation|uiMode|mcc|mnc|locale|keyboard|keyboardHidden|navigation|screenLayout|fontScale|screenSize|smallestScreenSize"` – q126y Oct 27 '21 at 17:12
  • 1
    You are missing `layoutDirection`, `touchscreen`, and `density` in that list. While none of those would really fit, you could try adding those and see if it changes your behavior. I forget what Logcat logs around configuration changes, but you might find something there too. BTW, what device are you testing on? – CommonsWare Oct 27 '21 at 17:18
  • @CommonsWare I added the missing config values, and nothing changed. I didn't see any special log entry when the activity restarted on orientation change. I am testing it on Pixel device, official build. All other apps are restarting too. – q126y Oct 27 '21 at 19:03
  • 1
    If you are overriding `onConfigurationChanged()` in this activity, use debugging or logging to see if it is being called. If it is, then there is some new config change type that is not documented, and we'd need to figure out what that is. If it is *not* being called... that's bad. – CommonsWare Oct 27 '21 at 19:15
  • @CommonsWare `onConfigurationChanged()` is called only when we have the right `configchanges` flag set in the manifest. So no callback happens. The restart also happens on the emulator(API Sv2), so it is definitely Android 12 specific issue. – q126y Oct 28 '21 at 04:43
  • 2
    "onConfigurationChanged() is called only when we have the right configchanges flag set in the manifest" -- oh, right, sorry. I will try to look at this problem on the weekend. – CommonsWare Oct 28 '21 at 10:50
  • 3
    I see the same effect, and I cannot explain it. I filed [a comment on a seemingly-related existing issue](https://issuetracker.google.com/issues/199995249#comment4), wrote [a blog post about it](https://commonsware.com/blog/2021/10/30/wallpaper-configuration-changes.html), plus added the bounty here. With luck, we will get some answers out of all of that. – CommonsWare Oct 30 '21 at 20:26
  • 1
    We are talking about this issue at r/android_devs. I reproduce something I found interesting: what happens when the user uses an app that changes the wallpaper automatically? In this case, could the activity close automatically even when the user is using it? – anemomylos Oct 31 '21 at 11:43
  • 3
    It seems to be a configuration changes. I can catch the changes by overriding the `onConfigurationChanges` from the Application (which will be called for all such changes, regardless of the Manifest). The flag "assetsSeq" is updated. A demo here: https://lensdump.com/i/gmpwWA . I used the built-in Wallpaper App, and Pixel 4 running Android 12. – Nguyễn Hoài Nam Oct 31 '21 at 12:33
  • 2
    @NguyễnHoàiNam: Ooooo... I had forgotten about `Application` and `onConfigurationChanged()`! I included your tip in my answer and in an update to [my blog post on this](https://commonsware.com/blog/2021/10/31/android-12-wallpaper-changes-recreate-activities.html). Thanks for pointing that out! – CommonsWare Oct 31 '21 at 18:40
  • 1
    @anemomylos: You're correct, it appears it affects all wallpaper changing apps from Android 12+ too. In fact, I originally posted [this question](https://stackoverflow.com/questions/71414373/) before I was directed here. – Auc Mar 09 '22 at 21:13

1 Answers1

9

It is a non-traditional configuration change. By "non-traditional", I mean that it cannot be blocked by android:configChanges — your activity will be destroyed and recreated whether you like it or not.

If you have Configuration objects from before and after the change, you can determine that this scenario occurred by calling diff() on the newer Configuration to compare it to the older one:

val diff = resources.configuration.diff(vm.originalConfiguration)

Log.d("WallpaperCCTest", "matches CONFIG_ASSETS_PATHS? ${(diff.toLong() and 0x80000000) != 0L}")

Here, vm.originalConfiguration points to the older Configuration, and we get the current Configuration from the Resources object. (diff.toLong() and 0x80000000) != 0L will evaluate to true if a wallpaper change or something similar triggered the configuration change. There are other edge cases for this — this whole "unblockable configuration change" thing came about when Sony got Google to add support for runtime resource overlays (RROs) back in 2017. So, some of those "change the system theme" apps might trigger this same unblockable configuration change.

As Nguyễn Hoài Nam notes, you can detect this from onConfigurationChanged() of a custom Application. Or, have your viewmodel hold onto the previous Configuration and compare it with the current one in onCreate() of your activity.

I have more on this issue in this blog post. AFAIK, there is no way to opt out of this configuration change, so if your app was designed to avoid configuration changes, you may be out of luck.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Could you please take a look at this https://stackoverflow.com/questions/69985252/callback-when-task-goes-into-background-or-comes-into-foreground Thanks. – q126y Nov 17 '21 at 05:23