Skip to content

Commit

Permalink
feat(GmsCore): add Custom branding name patch
Browse files Browse the repository at this point in the history
  • Loading branch information
ayushTNM committed Jun 17, 2024
1 parent fc50927 commit 788c001
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 3 deletions.
8 changes: 5 additions & 3 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dist
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package app.revanced.patches.gmscore.branding.name

import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.util.StringsElementsUtils.removeStringsElements
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.util.valueOrThrow

//@Suppress("DEPRECATION", "unused")
object CustomBrandingNamePatch : ResourcePatch(
name = "Custom branding name",
description = "Renames GmsCore to the name specified in options.json.",
compatiblePackages = setOf(
CompatiblePackage("app.revanced.android.gms")
)
) {
private const val APP_NAME = "MicroG"

private val AppName = stringPatchOption(
key = "AppName",
default = APP_NAME,
values = mapOf(
"MicroG" to APP_NAME,
"GmsCore" to "GmsCore"
),
title = "App name",
description = "The name of the app.",
required = true
)

override fun execute(context: ResourceContext) {

// Check patch options first.
val appName = AppName
.valueOrThrow()

context.removeStringsElements(
arrayOf("gms_app_name", "gms_settings_name")
)

context.xmlEditor["res/values/strings.xml"].use { editor ->
val document = editor.file

mapOf(
"gms_app_name" to appName,
"gms_settings_name" to appName
).forEach { (k, v) ->
val stringElement = document.createElement("string")

stringElement.setAttribute("name", k)
stringElement.textContent = v

document.getElementsByTagName("resources").item(0).appendChild(stringElement)
}
}
}
}
88 changes: 88 additions & 0 deletions src/main/kotlin/app/revanced/util/ResourceUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package app.revanced.util

import app.revanced.patcher.patch.options.PatchOption
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import java.io.File
import java.nio.file.Files
import java.io.InputStream
import java.nio.file.StandardCopyOption

private val classLoader = object {}.javaClass.classLoader


fun PatchOption<String>.valueOrThrow() = value
?: throw PatchException("Invalid patch option: $title.")

fun PatchOption<String>.lowerCaseOrThrow() = valueOrThrow()
.lowercase()

fun PatchOption<String>.underBarOrThrow() = lowerCaseOrThrow()
.replace(" ", "_")

/**
* Copy resources from the current class loader to the resource directory.
*
* @param sourceResourceDirectory The source resource directory name.
* @param resources The resources to copy.
*/
fun ResourceContext.copyResources(
sourceResourceDirectory: String,
vararg resources: ResourceGroup,
) {
val targetResourceDirectory = this.get("res")

for (resourceGroup in resources) {
resourceGroup.resources.forEach { resource ->
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
Files.copy(
inputStreamFromBundledResource(sourceResourceDirectory, resourceFile)!!,
targetResourceDirectory.resolve(resourceFile).toPath(),
StandardCopyOption.REPLACE_EXISTING,
)
}
}
}

internal fun inputStreamFromBundledResource(
sourceResourceDirectory: String,
resourceFile: String,
): InputStream? = classLoader.getResourceAsStream("$sourceResourceDirectory/$resourceFile")


/**
* Resource names mapped to their corresponding resource data.
* @param resourceDirectoryName The name of the directory of the resource.
* @param resources A list of resource names.
*/
class ResourceGroup(val resourceDirectoryName: String, vararg val resources: String)

fun ResourceContext.copyFile(
resourceGroup: List<ResourceGroup>,
path: String,
warning: String
): Boolean {
resourceGroup.let { resourceGroups ->
try {
val filePath = File(path)
val resourceDirectory = this["res"]

resourceGroups.forEach { group ->
val fromDirectory = filePath.resolve(group.resourceDirectoryName)
val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)

group.resources.forEach { iconFileName ->
Files.write(
toDirectory.resolve(iconFileName).toPath(),
fromDirectory.resolve(iconFileName).readBytes()
)
}
}

return true
} catch (_: Exception) {
println(warning)
}
}
return false
}
44 changes: 44 additions & 0 deletions src/main/kotlin/app/revanced/util/StringsElementsUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package app.revanced.util

import app.revanced.patcher.data.ResourceContext

@Suppress("DEPRECATION", "unused")
object StringsElementsUtils {

internal fun ResourceContext.removeStringsElements(
replacements: Array<String>
) {
var languageList = emptyArray<String>()
val resourceDirectory = this["res"]
val dir = resourceDirectory.listFiles()
for (file in dir!!) {
val path = file.name
if (path.startsWith("values")) {
val targetXml = resourceDirectory.resolve(path).resolve("strings.xml")
if (targetXml.exists()) languageList += path
}
}
removeStringsElements(languageList, replacements)
}

internal fun ResourceContext.removeStringsElements(
paths: Array<String>,
replacements: Array<String>
) {
paths.forEach { path ->
val targetXmlPath = this["res"].resolve(path).resolve("strings.xml")

if (targetXmlPath.exists()) {
val targetXml = this["res/$path/strings.xml"]

replacements.forEach replacementsLoop@{ replacement ->
targetXml.writeText(
targetXml.readText()
.replaceFirst(""" {4}<string name="$replacement".+""".toRegex(), "")
)
}
}
}
}
}

0 comments on commit 788c001

Please sign in to comment.