Skip to content

Instantly share code, notes, and snippets.

@tiiime
Last active November 11, 2021 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiiime/fa405fb688ee34c4773e8fca6af4e047 to your computer and use it in GitHub Desktop.
Save tiiime/fa405fb688ee34c4773e8fca6af4e047 to your computer and use it in GitHub Desktop.
批量修改 android:exported,适配 Android 12 行为变更
$ curl -s "https://get.sdkman.io" | bash

$ source "~/.sdkman/bin/sdkman-init.sh"

$ sdk install kotlin

$ cd /path/to/your/project

$ wget exported.main.kts

$ chmod a+x exported.main.kts

$ ./exported.main.kts
#!/usr/bin/env kotlin
@file:Repository("https://mvnrepository.com/")
@file:DependsOn("org.jsoup:jsoup:1.14.3")
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.parser.Parser
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
private val ANDROID_EXPORTED = "android:exported"
private val ANDROID_MANIFEST = "AndroidManifest.xml"
private val INTENT_FILTER = "intent-filter"
private val target = listOf("activity", "receiver", "provider", "service")
val path = Paths.get("").toAbsolutePath().toString()
File(path).walk().filter { it.path.endsWith(ANDROID_MANIFEST) }.forEach {
println("edit: ${it.path}")
editFile(it)
}
println("done")
fun editFile(file: File) {
val doc = Jsoup.parse(file.readText(), "", Parser.xmlParser());
target.flatMap { doc.select(it).toMutableList() }.forEach(::editAttr)
Files.write(Paths.get(file.path), doc.outerHtml().toByteArray())
}
fun editAttr(element: Element) {
if (element.hasExported()) {
return
}
val exported = element.hasIntentFilter()
element.attr(ANDROID_EXPORTED, "$exported")
}
fun Element.hasExported(): Boolean = attributes().any { it.key == ANDROID_EXPORTED }
fun Element.hasIntentFilter(): Boolean {
return children().any { it.tagName() == INTENT_FILTER }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment