New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes Resources$NotFoundException when accessing app module resource from dynamic feature module #1367
base: master
Are you sure you want to change the base?
Conversation
…from dynamic feature module
dependencies { | ||
implementation files('libs/external.aar') | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike library
module, application
module does not generate symbol_list_with_package_name/[variant]/package-aware-r.txt
when there is no dependency. So I have to add one dependency in the test.
In reality, application
module will always have dependencies, so there is no issue about that. We do not have to check if symbol_list_with_package_name/[variant]/package-aware-r.txt
exists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so this is an awesome solution given your source digging into AGP internals, but I'm concerned this depends on internals too much and will break every time we bump AGP.
I'm curious if there is a DSL one level up that exposes this to plugin or build script authors. In other words,
Looking at line 105 of ArtifactPublishingUtil
in AGP 8.2.2:
fun publishBuildArtifacts(
creationConfig: ComponentCreationConfig,
publishInfo: VariantPublishingInfo?
) {
for (outputSpec in PublishingSpecs.getVariantPublishingSpec(creationConfig.componentType).outputs) {
ultimately, it looks like this approach replaces publishInfo
with the additionalSpecs
needed to drive this business logic correctly. Is there a way via DSL to configure the variant publishing spec such that:
PublishingSpecs.getVariantPublishingSpec(creationConfig.componentType).outputs
in AGP internal will execute the desired path in your implementation of publishBuildArtifacts
?
@@ -65,6 +85,12 @@ public class PaparazziPlugin : Plugin<Project> { | |||
|
|||
supportedPlugins.forEach { plugin -> | |||
project.plugins.withId(plugin) { | |||
project.extensions.getByType(AndroidComponentsExtension::class.java).onVariants { variant -> | |||
variant.components.filterIsInstance<ApplicationVariantImpl>().forEach { | |||
publishBuildArtifacts(it as ComponentImpl<*>, getApplicationAdditionalSpec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we move publishBuildArtifacts, etc. to a new file dynamicFeaturesSupport.kt
to highlight the reason from this added source?
OutputSpec(InternalArtifactType.PACKAGED_RES, ArtifactType.ANDROID_RES, RUNTIME_ELEMENTS_ONLY), | ||
OutputSpec(InternalArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME, ArtifactType.SYMBOL_LIST_WITH_PACKAGE_NAME) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline
private val API_AND_RUNTIME_ELEMENTS: List<AndroidArtifacts.PublishedConfigType> = | ||
listOf(API_ELEMENTS, RUNTIME_ELEMENTS) | ||
private val RUNTIME_ELEMENTS_ONLY: List<AndroidArtifacts.PublishedConfigType> = | ||
listOf(RUNTIME_ELEMENTS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline
* | ||
* Publish intermediate artifacts in the BuildArtifactsHolder in addition to default PublishingSpecs. | ||
* | ||
* ignore original publishInfo: VariantPublishingInfo? parameter as we are not using publication config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be passed as null
, since the signature of com.android.build.gradle.internal.scope.ArtifactPublishingUtil.kt#publishBuildArtifacts
is:
fun publishBuildArtifacts(
creationConfig: ComponentCreationConfig,
publishInfo: VariantPublishingInfo?
) {
Why mimic what ComponentTypeImpl.LIBRARY does? Is a dynamic feature considered a LIBRARY component type for the purposes of publishing?
How come? Any ideas how we can avoid this? Android Studio doesn't require this, so it'd be an odd user experience to require this. |
PublishingSpecs.getVariantPublishingSpec is referring to a private static map which is initialized with hardcoded builder. I did not find a way to intercept the initialization and add more artifact type there. And it is immutable after initialization. |
The root cause is not dynamic feature itself, but its dependency So the propose solution is actually to mimic what ComponentTypeImpl.LIBRARY does for application module. In order to do that, we have to apply
As I have investigated, Android Studio gets application module as an instance of |
Related to #1060
Fixes Resources$NotFoundException when accessing app module resource from dynamic feature module.
The cause is in PublishingSpecs.kt,
PACKAGED_RES
andSYMBOL_LIST_WITH_PACKAGE_NAME
are not properly associated with correspondent ArtifactType when publishing asComponentTypeImpl.BASE_APK
fromapplication
module. So these artifacts are not available fordynamic feature
module during the execution ofpreparePaparazziDebugResources
.The proposed solution is to replicate the logic in ArtifactPublishingUtil.kt to map above artifacts to their respective ArtifactType like what ComponentTypeImpl.LIBRARY does. However, this approach requires application module to apply
PaparazziPlugin
, even if it does not have any snapshot tests of its own.