Strange behaviour in Android 12+ with WallpaperManager
Asked Answered
U

1

8

Is this a bug with WallpaperManager in the latest versions of Android?

When setting the wallpaper, it will automatically destroy and reload the current activity.

This behaviour only seems to affect Android 12 and onwards. It's quite easy to replicate, code in Kotlin:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val randomResourceList = arrayListOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5)
    val randomValue = (0 until randomResourceList.size).random()
    val wallpaper = randomResourceList[randomValue]

    val bmp = BitmapFactory.decodeResource(resources, wallpaper)
    val wallpaperManager = WallpaperManager.getInstance(this)
    wallpaperManager.setBitmap(bmp, null, true)
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("tag", "Destroyed.")
}

Add a few images (include several because the wallpaper will not be set if the wallpaper image is the same as the last, hence the randomization)

You should then see the activity being destroyed and reloaded in a cycle. No errors are thrown and the wallpaper is actually changed each time.

In my particular case, this is causing havoc when setting the wallpaper on a timer in a foreground service. If the user happens to have an activity on the screen when the wallpaper is changed, it will get destroyed.

Ursulina answered 9/3, 2022 at 18:32 Comment(4)
I've never done anything with wallpaper, but this sounds similar to a question I happened to come across the other day: https://mcmap.net/q/591814/-android-12-how-to-prevent-activity-restart-on-changing-phone-wallpaper.Aspirator
Good catch. After a bit of testing, it does appear to be related to the configuration changes issue mentioned. The good news is, it only seems to affect the activities of the wallpaper changing app itself.Ursulina
@Ursulina it calls destroy() then onCreate() all previous activities. You will see it when back to them.Pali
Did you find any solution for this? I am losing the scrolled state of the recycler view on the home screen due to this. Any ideas?Kellum
A
0

You can do this using the onSaveInstanceState() and onRestoreInstanceState() methods.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val randomResourceList = arrayListOf(R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5)
    val randomValue = (0 until randomResourceList.size).random()
    val wallpaper = randomResourceList[randomValue]

    val bmp = BitmapFactory.decodeResource(resources, wallpaper)
    val wallpaperManager = WallpaperManager.getInstance(this)

    // Save the state of the activity.
    val savedState = saveState()

    // Set the wallpaper.
    wallpaperManager.setBitmap(bmp, null, true)

    // Restore the state of the activity.
    restoreState(savedState)
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("tag", "Destroyed.")
}
Astrid answered 26/9, 2023 at 3:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.