JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
14.85k stars 1.08k forks source link

sharedUserId breaks Compose Resources on Android #4742

Open garrison-henkle opened 2 weeks ago

garrison-henkle commented 2 weeks ago

Describe the bug Compose Resources fails to load resources on Android when the application is using a sharedUserId

Affected platforms

Versions

To Reproduce Minimal reproducer using kmp.jetbrains.com's Android template: https://github.com/garrison-henkle/composeResourcesSharedUserIdBug

Stacktrace is also in the above repo's README.md

Steps:

  1. Launch the application with the sharedUserId attribute in the Manifest.xml.

Expected behavior The app is able to load resources regardless of whether it uses a sharedUserId or not

Screenshots N/A

Additional context I maintain an application that has unfortunately inherited a sharedUserId. My team has been building out a replacement app using Compose Mutliplatform, and we recently added in the sharedUserId to prepare it for submission to the Play Store. The addition of the sharedUserId prevents the app from loading any images or strings (fonts load fine because the underlying implementation delegates to Android's asset loader).

I investigated the issue and narrowed it down to the class loader. Removing Thread.currentThread().contextClassLoader from ResourceReader.android.kt seemed to fix the issue for me:

// Before (crashes)
private fun getClassLoader(): ClassLoader {
    return Thread.currentThread().contextClassLoader ?: this.javaClass.classLoader!!
}

// After (runs)
private object ResourceReader
private fun getClassLoader(): ClassLoader {
    return ResourceReader.javaClass.classLoader!!
}

I know essentially nothing about class loaders, so I don't know the implications of just removing the Thread's context class loader here. Hopefully the above hack at least demonstrates what's causing the issue đŸ˜…

igordmn commented 1 week ago

Thanks!

@terrakok, it is reproduced on the provided project. sharedUserId is deprecated, but it isn't possible to migrate old projects that needs to be maintained. Can we use the suggested fix?

terrakok commented 1 week ago

The classloader logic was implemented by intention here: https://github.com/JetBrains/compose-multiplatform/pull/2490

I will investigate it more because it seems suspicious