Changes to Android 12 wallpapers Recreate your activities
Following on from my previous post, and thanks to A crucial tip from cketti, Now we seem to know more about what happens with wallpaper changes in Android 12: Your activities will be recreated, similar to a regular configuration change, but without a cancellation mechanism.
The original change
Katie pointed at me This commitment of AOSP. It provides the engine for what I described above: it forces activities to be re-created:
The activities will be planned to be restarted through the regular life cycle. This is similar to a configuration change, but because ApplicationInfo changes are too low, we do not allow applications to revoke their consent.
The catch is the last seven words: “We do not allow apps to revoke their consent.” This is not an actual configuration change that you can revoke your consent through android:configChanges
.
The original rationale for this was for “super-layers of runtime resources and split APK”. I’m not 100% sure how split APKs come into play here, but
Layers on runtime resources (RRO)
Represents a mechanism for systemic theme changes. So it is not surprising that Google has connected to this mechanism for Android 12 wallpaper changes.
Confirm the wallpaper effect
You can determine after the fact that it occurred by comparison Configuration
Objects before and after the recreational activity. We do not accept onConfigurationChanged()
Repeat call b Activity
, Because we do not choose to cancel this entertainment process. However, e
Configuration
The object used in our previous activity instance will be fundamentally different from one of the Configuration
An object used in the alternate activity instance.
For example, here is trivial ViewModel
Who holds a Configuration?
resist:
class MainViewModel : ViewModel() {
var originalConfiguration: Configuration? = null
}
In this activity I keep the source Configuration
Object in viewmodel if originalConfiguration
he null
. Otherwise, I use diff()
On Configuration
Examine the difference between the source Configuration
And current:
class MainActivity : AppCompatActivity() {
private val vm: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// other good stuff goes here
if (vm.originalConfiguration == null) {
vm.originalConfiguration = resources.configuration
} else {
val diff = resources.configuration.diff(vm.originalConfiguration)
Log.d("WallpaperCCTest", "matches CONFIG_ASSETS_PATHS? ${(diff.toLong() and 0x80000000) != 0L}")
}
}
}
diff()
Returns a bit mask of the configuration components that differ between the two Configuration
stuff. The magic 0x80000000
Come from
Android source code
– It ActivityInfo.CONFIG_ASSETS_PATHS
, Constant marked b @hide
:
/**
* Bit in {@link #configChanges} that indicates that the activity
* can itself handle asset path changes. Set from the {@link android.R.attr#configChanges}
* attribute. This is not a core resource configuration, but a higher-level value, so its
* constant starts at the high bits.
* @hide We do not want apps handling this yet, but we do need some kind of bit for diffs.
*/
public static final int CONFIG_ASSETS_PATHS = 0x80000000;
In Android 12, after changing the wallpaper, usually else
The block is activated and the bitmask test comes out true
. I say “usually” because in my test, it seems like there is an occasional hiccup where the wallpaper changes and the activity is left alone and not recreated – I got it maybe once out of ten, and did not recognize the pattern.
My code shown above compares the current one Configuration
With the original – for production use, you should probably follow the recent look Configuration
And compare it to the current one.
updating: based on This comment By Nguyễn Hoài Nam, you can identify it using onConfigurationChanged()
In custom Application
Subdivision. However, this will be called for any configuration change; You will still need to use diff()
Or similar techniques to determine if the configuration change came from such a scenario.
Reduction approaches
You can use the above diff()
Access to detect that your activity has been re-created due to something like a wallpaper change. There are other things that will activate the same effect, since the RRO system is registered
By Sony
As early as 2017. Changes to Android 12 wallpapers may somewhat increase the frequency of this occurrence.
However, there is no clear way to prevent this destruction and recovery cycle from occurring. If anything, the various code comments indicate that Google+ has specifically blocked apps from blocking it. This may be why Google chose to go this route instead of introducing a new type of configuration change.
Even if your app tries to revoke your consent to any configuration changes – something that the Jetpack Compose team at Google supported – you can still destroy your activity and re-create it without stopping the process. Ideally your app handles this case, though
Not all apps do, apparently.
– October 31, 2021