Browse Source

[resources] Fix android fonts in APKs (#4509)

Steps to reproduce:
1) Add a 'font-en' directory with a font to an android app with compose
resources
2) build the app with `assembleDebug` and check that a corresponding dir
is presented in the final APK
 3) rename a qualifier of the dir to `font-de`
 4) re-build the app with the same command `assembleDebug`

Expected: the new APK will contain the new font dir
Actual: the new APK doesn't have the new font dir but has old one
'font-en'

The PR fixes that
pull/4482/head
Konstantin 8 months ago committed by GitHub
parent
commit
c43b64d43a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt
  2. 111
      gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt
  3. 11
      gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Font0.kt
  4. BIN
      gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/font-en/emptyFont.otf

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

@ -308,7 +308,7 @@ internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() {
@get:Inject
abstract val fileSystem: FileSystemOperations
@get:Input
@get:InputDirectory
abstract val from: Property<File>
@get:OutputDirectory

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

@ -292,21 +292,41 @@ class ResourcesTest : GradlePluginTestBase() {
check.taskSuccessful(":copyFullDebugFontsToAndroidAssets")
check.taskSuccessful(":copyFullReleaseFontsToAndroidAssets")
checkAndroidApk("demo", "debug", commonResourcesFiles)
checkAndroidApk("demo", "release", commonResourcesFiles)
checkAndroidApk("full", "debug", commonResourcesFiles)
checkAndroidApk("full", "release", commonResourcesFiles)
val desktopJar = file("build/libs/Resources-Test-desktop.jar")
assertTrue(desktopJar.exists())
ZipFile(desktopJar).use { zip ->
commonResourcesFiles.forEach { res ->
assertNotNull(zip.getEntry(res))
}
val platformTxt = zip.getEntry("files/platform.txt")
assertNotNull(platformTxt)
val text = zip.getInputStream(platformTxt).readBytes().decodeToString()
assertEquals("desktop", text)
getAndroidApk("demo", "debug", "Resources-Test").let { apk ->
checkResourcesInZip(apk, commonResourcesFiles, true)
assertEquals(
"android demo-debug",
readFileInZip(apk, "files/platform.txt").decodeToString()
)
}
getAndroidApk("demo", "release", "Resources-Test").let { apk ->
checkResourcesInZip(apk, commonResourcesFiles, true)
assertEquals(
"android demo-release",
readFileInZip(apk, "files/platform.txt").decodeToString()
)
}
getAndroidApk("full", "debug", "Resources-Test").let { apk ->
checkResourcesInZip(apk, commonResourcesFiles, true)
assertEquals(
"android full-debug",
readFileInZip(apk, "files/platform.txt").decodeToString()
)
}
getAndroidApk("full", "release", "Resources-Test").let { apk ->
checkResourcesInZip(apk, commonResourcesFiles, true)
assertEquals(
"android full-release",
readFileInZip(apk, "files/platform.txt").decodeToString()
)
}
file("build/libs/Resources-Test-desktop.jar").let { jar ->
checkResourcesInZip(jar, commonResourcesFiles, false)
assertEquals(
"desktop",
readFileInZip(jar, "files/platform.txt").decodeToString()
)
}
val jsBuildDir = file("build/dist/js/productionExecutable")
@ -317,32 +337,73 @@ class ResourcesTest : GradlePluginTestBase() {
}
}
@Test
fun testAndroidFonts(): Unit = with(testProject("misc/commonResources")) {
val commonResourcesDir = file("src/commonMain/composeResources")
val commonResourcesFiles = commonResourcesDir.walkTopDown()
.filter { !it.isDirectory && !it.isHidden }
.map { it.relativeTo(commonResourcesDir).invariantSeparatorsPath }
gradle("assembleDebug").checks {
check.taskSuccessful(":copyDebugFontsToAndroidAssets")
getAndroidApk("", "debug", "Resources-Test").let { apk ->
checkResourcesInZip(apk, commonResourcesFiles, true)
}
}
file("src/commonMain/composeResources/font-en").renameTo(
file("src/commonMain/composeResources/font-mdpi")
)
val newCommonResourcesFiles = commonResourcesDir.walkTopDown()
.filter { !it.isDirectory && !it.isHidden }
.map { it.relativeTo(commonResourcesDir).invariantSeparatorsPath }
gradle("assembleDebug").checks {
check.taskSuccessful(":copyDebugFontsToAndroidAssets")
getAndroidApk("", "debug", "Resources-Test").let { apk ->
checkResourcesInZip(apk, newCommonResourcesFiles, true)
}
}
}
private fun File.writeNewFile(text: String) {
parentFile.mkdirs()
createNewFile()
writeText(text)
}
private fun TestProject.checkAndroidApk(flavor: String, type: String, commonResourcesFiles: Sequence<String>) {
val apk = file("build/outputs/apk/$flavor/$type/Resources-Test-$flavor-$type.apk")
assertTrue(apk.exists())
ZipFile(apk).use { zip ->
private fun TestProject.getAndroidApk(flavor: String, type: String, name: String): File {
return if (flavor.isNotEmpty()) {
file("build/outputs/apk/$flavor/$type/$name-$flavor-$type.apk")
} else {
file("build/outputs/apk/$type/$name-$type.apk")
}
}
private fun checkResourcesInZip(file: File, commonResourcesFiles: Sequence<String>, isAndroid: Boolean) {
println("check ZIP: '${file.path}'")
assertTrue(file.exists())
ZipFile(file).use { zip ->
commonResourcesFiles.forEach { res ->
if (res == "font/emptyFont.otf") {
println("check '$res' file")
if (isAndroid && res.startsWith("font")) {
//android fonts should be only in assets
assertNull(zip.getEntry(res), "file = '$res'")
assertNotNull(zip.getEntry("assets/$res"), "file = 'assets/$res'")
} else {
assertNotNull(zip.getEntry(res), "file = '$res'")
}
}
assertNotNull(zip.getEntry("assets/font/emptyFont.otf"), "file = 'assets/font/emptyFont.otf'")
val platformTxt = zip.getEntry("files/platform.txt")
assertNotNull(platformTxt, "file = 'files/platform.txt'")
val text = zip.getInputStream(platformTxt).readBytes().decodeToString()
assertEquals("android $flavor-$type", text)
}
}
private fun readFileInZip(file: File, path: String): ByteArray = ZipFile(file).use { zip ->
val platformTxt = zip.getEntry(path)
assertNotNull(platformTxt, "file = '$path'")
zip.getInputStream(platformTxt).readBytes()
}
@Test
fun testUpToDateChecks(): Unit = with(testProject("misc/commonResources")) {
gradle("prepareKotlinIdeaImport").checks {

11
gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Font0.kt

@ -9,7 +9,7 @@ import org.jetbrains.compose.resources.FontResource
@ExperimentalResourceApi
private object Font0 {
public val emptyFont: FontResource by
lazy { init_emptyFont() }
lazy { init_emptyFont() }
}
@ExperimentalResourceApi
@ -19,7 +19,10 @@ internal val Res.font.emptyFont: FontResource
@ExperimentalResourceApi
private fun init_emptyFont(): FontResource = org.jetbrains.compose.resources.FontResource(
"font:emptyFont",
setOf(
org.jetbrains.compose.resources.ResourceItem(setOf(), "font/emptyFont.otf"),
)
setOf(
org.jetbrains.compose.resources.ResourceItem(setOf(org.jetbrains.compose.resources.LanguageQualifier("en"),
), "font-en/emptyFont.otf"),
org.jetbrains.compose.resources.ResourceItem(setOf(), "font/emptyFont.otf"),
)
)

BIN
gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/commonMain/composeResources/font-en/emptyFont.otf

Binary file not shown.
Loading…
Cancel
Save