Browse Source

Fix fonts duplication in android app. (#4284)

pull/4286/head
Konstantin 10 months ago committed by GitHub
parent
commit
fbf5dbe20f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 18
      components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt
  2. 0
      components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt
  3. 42
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt
  4. 6
      gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt

18
components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt

@ -0,0 +1,18 @@
package org.jetbrains.compose.resources
import java.io.File
private object AndroidResourceReader
@OptIn(ExperimentalResourceApi::class)
@InternalResourceApi
actual suspend fun readResourceBytes(path: String): ByteArray {
val classLoader = Thread.currentThread().contextClassLoader ?: AndroidResourceReader.javaClass.classLoader
val resource = classLoader.getResourceAsStream(path) ?: run {
//try to find a font in the android assets
if (File(path).parentFile?.name.orEmpty() == "font") {
classLoader.getResourceAsStream("assets/$path")
} else null
} ?: throw MissingResourceException(path)
return resource.readBytes()
}

0
components/resources/library/src/jvmAndAndroidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.jvmAndAndroid.kt → components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt

42
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt

@ -15,8 +15,6 @@ import org.jetbrains.compose.desktop.application.internal.ComposeProperties
import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID
import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID
import org.jetbrains.compose.internal.utils.* import org.jetbrains.compose.internal.utils.*
import org.jetbrains.compose.internal.utils.dependsOn
import org.jetbrains.compose.internal.utils.registerTask
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
@ -74,14 +72,27 @@ private fun Project.configureAndroidComposeResources(
kotlinExtension: KotlinMultiplatformExtension, kotlinExtension: KotlinMultiplatformExtension,
androidExtension: BaseExtension androidExtension: BaseExtension
) { ) {
val commonResourcesDir = projectDir.resolve("src/${KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME}/$COMPOSE_RESOURCES_DIR")
//Copy common compose resources except fonts to android resources
val copyCommonAndroidComposeResources = registerTask<CopyCommonAndroidComposeResources>(
"copyCommonAndroidComposeResources"
) {
from.set(commonResourcesDir)
outputDirectory.set(layout.buildDirectory.dir("$RES_GEN_DIR/commonAndroidComposeResources"))
}
tasks.configureEachWithType<ProcessJavaResTask> { dependsOn(copyCommonAndroidComposeResources) }
//mark all composeResources as Android resources //mark all composeResources as Android resources
kotlinExtension.targets.matching { it is KotlinAndroidTarget }.all { androidTarget -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).all { androidTarget ->
androidTarget.compilations.all { compilation: KotlinCompilation<*> -> androidTarget.compilations.all { compilation: KotlinCompilation<*> ->
compilation.defaultSourceSet.androidSourceSetInfoOrNull?.let { kotlinAndroidSourceSet -> compilation.defaultSourceSet.androidSourceSetInfoOrNull?.let { kotlinAndroidSourceSet ->
androidExtension.sourceSets androidExtension.sourceSets
.matching { it.name == kotlinAndroidSourceSet.androidSourceSetName } .matching { it.name == kotlinAndroidSourceSet.androidSourceSetName }
.all { androidSourceSet -> .all { androidSourceSet ->
(compilation.allKotlinSourceSets as ObservableSet<KotlinSourceSet>).forAll { kotlinSourceSet -> androidSourceSet.resources.srcDir(copyCommonAndroidComposeResources.flatMap { it.outputDirectory.asFile })
(compilation.allKotlinSourceSets as? ObservableSet<KotlinSourceSet>)?.forAll { kotlinSourceSet ->
if (kotlinSourceSet.name != KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) {
androidSourceSet.resources.srcDir( androidSourceSet.resources.srcDir(
projectDir.resolve("src/${kotlinSourceSet.name}/$COMPOSE_RESOURCES_DIR") projectDir.resolve("src/${kotlinSourceSet.name}/$COMPOSE_RESOURCES_DIR")
) )
@ -90,10 +101,10 @@ private fun Project.configureAndroidComposeResources(
} }
} }
} }
}
//copy fonts from the compose resources dir to android assets //copy fonts from the compose resources dir to android assets
val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return
val commonResourcesDir = projectDir.resolve("src/${KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME}/$COMPOSE_RESOURCES_DIR")
androidComponents.onVariants { variant -> androidComponents.onVariants { variant ->
val copyFonts = registerTask<CopyAndroidFontsToAssetsTask>( val copyFonts = registerTask<CopyAndroidFontsToAssetsTask>(
"copy${variant.name.uppercaseFirstChar()}FontsToAndroidAssets" "copy${variant.name.uppercaseFirstChar()}FontsToAndroidAssets"
@ -155,6 +166,27 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File,
} }
} }
internal abstract class CopyCommonAndroidComposeResources : DefaultTask() {
@get:Inject
abstract val fileSystem: FileSystemOperations
@get:InputFiles
abstract val from: Property<File>
@get:OutputDirectory
abstract val outputDirectory: DirectoryProperty
@TaskAction
fun action() {
fileSystem.copy {
it.includeEmptyDirs = false
it.from(from)
it.exclude("**/font*/*")
it.into(outputDirectory)
}
}
}
//Copy task doesn't work with 'variant.sources?.assets?.addGeneratedSourceDirectory' API //Copy task doesn't work with 'variant.sources?.assets?.addGeneratedSourceDirectory' API
internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() { internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() {
@get:Inject @get:Inject

6
gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt

@ -203,8 +203,12 @@ class ResourcesTest : GradlePluginTestBase() {
assertTrue(apk.exists()) assertTrue(apk.exists())
ZipFile(apk).use { zip -> ZipFile(apk).use { zip ->
commonResourcesFiles.forEach { res -> commonResourcesFiles.forEach { res ->
if (res == "font/emptyFont.otf") {
//android fonts should be only in assets
assertNull(zip.getEntry(res))
} else {
assertNotNull(zip.getEntry(res)) assertNotNull(zip.getEntry(res))
//todo fix duplicate fonts }
} }
assertNotNull(zip.getEntry("assets/font/emptyFont.otf")) assertNotNull(zip.getEntry("assets/font/emptyFont.otf"))
val platformTxt = zip.getEntry("files/platform.txt") val platformTxt = zip.getEntry("files/platform.txt")

Loading…
Cancel
Save