Skip to content

Commit

Permalink
Merge pull request #99 from usefulness/add_manifest_placeholders_support
Browse files Browse the repository at this point in the history
Add manifest placeholders support
  • Loading branch information
mergify[bot] authored Nov 4, 2020
2 parents b5a7e4f + 91dceb3 commit d91b1e5
Show file tree
Hide file tree
Showing 19 changed files with 381 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ open class EasyLauncherTask : DefaultTask() {

private fun BaseExtension.getLauncherIconNames(variant: BaseVariant) =
getAndroidManifestFiles(variant)
.flatMap { manifestFile -> manifestFile.getLauncherIcons() }
.flatMap { manifestFile -> manifestFile.getLauncherIcons(variant.mergedFlavor.manifestPlaceholders) }

private fun BaseExtension.getAndroidManifestFiles(variant: BaseVariant): Iterable<File> {
return listOf("main", variant.name, variant.buildType.name, variant.flavorName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,31 @@ import groovy.util.XmlSlurper
import groovy.util.slurpersupport.GPathResult
import java.io.File

internal fun File.getLauncherIcons(): Set<String> {
internal fun File.getLauncherIcons(manifestPlaceholders: Map<String, Any> = emptyMap()): Set<String> {
val manifestXml = XmlSlurper().parse(this)
val applicationNode = manifestXml.getProperty("application") as GPathResult
val icon = applicationNode.getProperty("@android:icon")?.toString()
val roundIcon = applicationNode.getProperty("@android:roundIcon")?.toString()
val icon = applicationNode.getProperty("@android:icon")?.toString()?.applyPlaceholders(manifestPlaceholders)
val roundIcon = applicationNode.getProperty("@android:roundIcon")?.toString()?.applyPlaceholders(manifestPlaceholders)

return listOfNotNull(
icon?.takeIf { it.isNotBlank() },
roundIcon?.takeIf { it.isNotBlank() }
).toSet()
}

private val regex by lazy { "\\\$\\{([^{}]*)}".toRegex() }

private fun String.applyPlaceholders(manifestPlaceholders: Map<String, Any>): String =
replace(regex) { manifestPlaceholders[it.groups[1]?.value]?.toString() ?: it.value }

internal fun File.asAdaptiveIcon(): AdaptiveIcon? {
if (extension != "xml") {
return null
}

val iconXml = XmlSlurper().parse(this)
val foreground = iconXml.getProperty("foreground") as GPathResult
val background = iconXml.getProperty("foreground") as GPathResult
val background = iconXml.getProperty("background") as GPathResult
val backgroundDrawable = background.property("@android:drawable")
val foregroundDrawable = foreground.property("@android:drawable")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,101 @@ internal class XmlReaderTest {

assertThat(icon).containsExactly("@drawable/ic_launcher")
}

@Test
fun `getLauncherIcon with manifest placeholders`() {
val manifest = tempDir.resolve("AndroidManifest.xml")
manifest.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.akaita.android.easylauncher.example"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="${"$"}{has_placeholder}"
android:roundIcon="${"$"}{does_not_have_placeholder}"
android:label="@drawable/ic_launcher"
android:theme="@style/AppTheme" >
</application>
</manifest>
""".trimIndent()
)

val icon = manifest.getLauncherIcons(mapOf("has_placeholder" to "@mipmap/ic_launcher"))

assertThat(icon).containsExactly("@mipmap/ic_launcher", "\${does_not_have_placeholder}")
}

@Test
fun `getLauncherIcon with manifest placeholders with replacement`() {
val manifest = tempDir.resolve("AndroidManifest.xml")
manifest.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.akaita.android.easylauncher.example"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="@drawable/${"$"}{cat_image}"
android:roundIcon="@mipmap/${"$"}{dog_image}"
android:label="@drawable/ic_launcher"
android:theme="@style/AppTheme" />
</manifest>
""".trimIndent()
)

val icon = manifest.getLauncherIcons(mapOf("cat_image" to "cat", "dog_image" to "dog"))

assertThat(icon).containsExactly("@drawable/cat", "@mipmap/dog")
}

@Test
fun `parses adaptive icon`() {
val adaptiveIcon = tempDir.resolve("ic_launcher.xml")
adaptiveIcon.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon>
""".trimIndent()
)

val icon = adaptiveIcon.asAdaptiveIcon()

assertThat(icon?.background).isEqualTo("@drawable/ic_launcher_background")
assertThat(icon?.foreground).isEqualTo("@mipmap/ic_launcher_foreground")
assertThat(icon?.file?.path).isEqualTo(adaptiveIcon.path)
}

@Test
fun `does not parse txt file as adaptive icon`() {
val adaptiveIcon = tempDir.resolve("ic_launcher.txt")
adaptiveIcon.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
""".trimIndent()
)

val icon = adaptiveIcon.asAdaptiveIcon()

assertThat(icon).isNull()
}
}
4 changes: 2 additions & 2 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ subprojects {
applicationVariants.configureEach { variant ->
variant.mergedFlavor.applicationIdSuffix = variant.name
if (variant.flavorName == "") {
variant.mergedFlavor.manifestPlaceholders = [appName: "$project.name"]
variant.mergedFlavor.manifestPlaceholders += [appName: "$project.name"]
} else {
variant.mergedFlavor.manifestPlaceholders = [appName: "$variant.flavorName"]
variant.mergedFlavor.manifestPlaceholders += [appName: "$variant.flavorName"]
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions sample/example-library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ android {
libraryVariants.configureEach { variant ->
variant.mergedFlavor.applicationIdSuffix = variant.name
if (variant.flavorName == "") {
variant.mergedFlavor.manifestPlaceholders = [appName: "$project.name"]
variant.mergedFlavor.manifestPlaceholders += [appName: "$project.name"]
} else {
variant.mergedFlavor.manifestPlaceholders = [appName: "$variant.flavorName"]
variant.mergedFlavor.manifestPlaceholders += [appName: "$variant.flavorName"]
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions sample/example-manifest-placeholder/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apply plugin: 'com.starter.application.android'
apply plugin: 'com.starter.easylauncher'

android {
defaultConfig {
minSdkVersion 25

manifestPlaceholders += [
appIcon : "@mipmap/ic_launcher",
appRoundIcon: "@mipmap/ic_launcher_round"
]
}
buildTypes {
named("release") {
signingConfig signingConfigs.debug
}
}
}

dependencies {
implementation project(":adaptive-support")
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.starter.easylauncher.screenshot

import android.Manifest
import androidx.test.rule.GrantPermissionRule
import com.example.custom.adaptive.MainActivity
import com.example.manifestplaceholder.BuildConfig
import com.starter.easylauncher.recordScreenshot
import org.junit.Rule
import org.junit.Test

internal class IconsTest {

@get:Rule
val grantPermission = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)

@Test
fun doScreenshot() {
recordScreenshot<MainActivity>(BuildConfig.BUILD_TYPE)
}
}
13 changes: 13 additions & 0 deletions sample/example-manifest-placeholder/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.manifestplaceholder"
>

<application
android:allowBackup="true"
android:icon="${appIcon}"
android:label="${appName}"
android:roundIcon="${appRoundIcon}"
/>
</manifest>
Loading

0 comments on commit d91b1e5

Please sign in to comment.