Compare commits
1 commit
65f77f516a
...
bdf39d741b
Author | SHA1 | Date | |
---|---|---|---|
bdf39d741b |
1 changed files with 33 additions and 86 deletions
|
@ -1,16 +1,15 @@
|
||||||
package im.angry.openeuicc.build
|
package im.angry.openeuicc.build
|
||||||
|
|
||||||
import com.android.build.api.dsl.ApplicationDefaultConfig
|
import com.android.build.api.dsl.ApplicationDefaultConfig
|
||||||
import groovy.json.JsonOutput
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.SortedMap
|
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.io.path.name
|
||||||
|
|
||||||
|
|
||||||
class MagiskModule : Plugin<Project> {
|
class MagiskModule : Plugin<Project> {
|
||||||
|
@ -19,131 +18,78 @@ class MagiskModule : Plugin<Project> {
|
||||||
group = "magisk"
|
group = "magisk"
|
||||||
description = "Assembles the Magisk Module"
|
description = "Assembles the Magisk Module"
|
||||||
|
|
||||||
val config = target.defaultConfig
|
|
||||||
val appFile = target.layout.buildDirectory
|
|
||||||
.file("outputs/apk/debug/app-debug.apk")
|
|
||||||
.get().asFile
|
|
||||||
|
|
||||||
val options = MagiskModuleOptions(
|
|
||||||
appId = config.applicationId!!,
|
|
||||||
appFile = appFile,
|
|
||||||
permissionFile = target.rootProject.file("privapp_whitelist_${config.applicationId}.xml"),
|
|
||||||
versionName = config.versionName!!,
|
|
||||||
versionCode = config.versionCode!!,
|
|
||||||
manifestUri = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
val manifest = MagiskModuleManifest(
|
|
||||||
versionName = options.versionName,
|
|
||||||
versionCode = options.versionCode,
|
|
||||||
releaseUri = "",
|
|
||||||
changelogUri = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
project.layout.buildDirectory
|
project.layout.buildDirectory
|
||||||
.file("outputs/magisk-module.zip")
|
.file("outputs/magisk-module.zip")
|
||||||
.get().asFile
|
.get().asFile
|
||||||
.writeBytes(buildMagiskModule(options))
|
.writeBytes(buildMagiskModule(target))
|
||||||
|
|
||||||
project.layout.buildDirectory
|
|
||||||
.file("outputs/magisk-module-manifest.json")
|
|
||||||
.get().asFile
|
|
||||||
.writeText(buildMagiskModuleManifestFile(manifest))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MagiskModuleOptions(
|
private fun buildMagiskModule(target: Project) = buildZipFile {
|
||||||
val appId: String,
|
val defaultConfig = target.defaultConfig
|
||||||
val appName: String = "OpenEUICC",
|
val appId = defaultConfig.applicationId
|
||||||
val appFile: File,
|
val apkPath = "system/system_ext/priv-app/OpenEUICC/OpenEUICC.apk"
|
||||||
val permissionFile: File,
|
|
||||||
val versionName: String,
|
|
||||||
val versionCode: Int,
|
|
||||||
val author: String = "Peter Cai",
|
|
||||||
val description: String = "OpenEUICC provides system-level eUICC integration",
|
|
||||||
val manifestUri: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class MagiskModuleManifest(
|
|
||||||
val versionName: String,
|
|
||||||
val versionCode: Int,
|
|
||||||
val releaseUri: String,
|
|
||||||
val changelogUri: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun buildMagiskModule(options: MagiskModuleOptions) = buildZipFile {
|
|
||||||
// https://topjohnwu.github.io/Magisk/guides.html
|
|
||||||
val systemExt = "system/system_ext"
|
|
||||||
val metaInfo = "META-INF/com/google/android"
|
|
||||||
val apkPath = "$systemExt/priv-app/${options.appName}/${options.appName}.apk"
|
|
||||||
put("module.prop") {
|
put("module.prop") {
|
||||||
val module = buildList {
|
val module = buildList {
|
||||||
add("id" to options.appId)
|
add("id" to appId.toString())
|
||||||
add("name" to options.appName)
|
add("name" to "OpenEUICC")
|
||||||
add("version" to options.versionName)
|
add("version" to defaultConfig.versionName + defaultConfig.versionNameSuffix.orEmpty())
|
||||||
add("versionCode" to options.versionCode)
|
add("versionCode" to defaultConfig.versionCode.toString())
|
||||||
add("author" to options.author)
|
add("author" to "Peter Cai")
|
||||||
add("description" to options.description)
|
add("description" to "OpenEUICC provides system-level eUICC integration")
|
||||||
if (options.manifestUri != null) add("updateJson" to options.manifestUri)
|
add("updateJson" to "")
|
||||||
}
|
}
|
||||||
module
|
module
|
||||||
.joinToString("\n") { (key, value) -> "${key}=${value}" }
|
.joinToString("\n") { (key, value) -> "${key}=${value}" }
|
||||||
.encodeToByteArray()
|
.encodeToByteArray()
|
||||||
}
|
}
|
||||||
put("customize.sh") {
|
put("customize.sh") {
|
||||||
val copiedApkPath = "\$TMPDIR/${options.appName}.apk"
|
val copiedApkPath = "\$TMPDIR/${Path(apkPath).name}"
|
||||||
val script = buildString {
|
val script = buildString {
|
||||||
appendLine("chmod u+x \"\$MODPATH/uninstall.sh\"")
|
appendLine("chmod u+x \"\$MODPATH/uninstall.sh\"")
|
||||||
appendLine()
|
|
||||||
appendLine("cp \"\$MODPATH/$apkPath\" \"$copiedApkPath\"")
|
appendLine("cp \"\$MODPATH/$apkPath\" \"$copiedApkPath\"")
|
||||||
appendLine("pm install -r \"$copiedApkPath\"")
|
appendLine("pm install -r \"$copiedApkPath\"")
|
||||||
appendLine("rm -f \"$copiedApkPath\"")
|
appendLine("rm -f \"$copiedApkPath\"")
|
||||||
appendLine()
|
|
||||||
appendLine("pm grant \"${options.appId}\" android.permission.READ_PHONE_STATE")
|
appendLine("pm grant \"${appId}\" android.permission.READ_PHONE_STATE")
|
||||||
}
|
}
|
||||||
script.encodeToByteArray()
|
script.encodeToByteArray()
|
||||||
}
|
}
|
||||||
put("uninstall.sh") {
|
put("uninstall.sh") {
|
||||||
"pm uninstall ${options.appId}\n".encodeToByteArray()
|
"pm uninstall ${appId}\n".encodeToByteArray()
|
||||||
}
|
}
|
||||||
put("$metaInfo/update-binary") {
|
put("META-INF/com/google/android/update-binary") {
|
||||||
val installerUri =
|
val installerUri =
|
||||||
URI("https://github.com/topjohnwu/Magisk/raw/bf4ed29/scripts/module_installer.sh")
|
URI("https://github.com/topjohnwu/Magisk/raw/bf4ed29/scripts/module_installer.sh")
|
||||||
val connection = URL.of(installerUri, null).openConnection()
|
val connection = URL.of(installerUri, null).openConnection()
|
||||||
connection.inputStream.readBytes()
|
connection.inputStream.readBytes()
|
||||||
}
|
}
|
||||||
put("$metaInfo/updater-script") {
|
put("META-INF/com/google/android/updater-script") {
|
||||||
"#MAGISK\n".encodeToByteArray()
|
"#MAGISK\n".encodeToByteArray()
|
||||||
}
|
}
|
||||||
put(apkPath) {
|
put(apkPath) {
|
||||||
options.appFile.readBytes()
|
target.layout.buildDirectory
|
||||||
|
.file("outputs/apk/debug/app-debug.apk")
|
||||||
|
.get().asFile
|
||||||
|
.readBytes()
|
||||||
}
|
}
|
||||||
put("$systemExt/etc/permissions/privapp_whitelist_${options.appId}.xml") {
|
put("system/system_ext/etc/permissions/privapp_whitelist_${appId}.xml") {
|
||||||
options.permissionFile.readBytes()
|
target.rootProject
|
||||||
|
.file("privapp_whitelist_${appId}.xml")
|
||||||
|
.readBytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildMagiskModuleManifestFile(manifest: MagiskModuleManifest): String {
|
private fun buildZipFile(builderAction: MutableMap<String, (ZipEntry) -> ByteArray>.() -> Unit): ByteArray {
|
||||||
val entries = buildMap {
|
|
||||||
put("version", manifest.versionName)
|
|
||||||
put("versionCode", manifest.versionCode)
|
|
||||||
put("zipUrl", manifest.releaseUri)
|
|
||||||
put("changelog", manifest.changelogUri)
|
|
||||||
}
|
|
||||||
val jsonPayload = JsonOutput.toJson(entries)
|
|
||||||
return JsonOutput.prettyPrint(jsonPayload)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildZipFile(builderAction: SortedMap<String, () -> ByteArray>.() -> Unit): ByteArray {
|
|
||||||
val out = ByteArrayOutputStream()
|
val out = ByteArrayOutputStream()
|
||||||
val zip = ZipOutputStream(out)
|
val zip = ZipOutputStream(out)
|
||||||
val entries = buildMap { builderAction(this.toSortedMap()) }
|
for ((name, invoke) in buildMap(builderAction)) {
|
||||||
for ((name, generate) in entries) {
|
|
||||||
val entry = ZipEntry(name)
|
val entry = ZipEntry(name)
|
||||||
entry.time = 0 // reproducible builds
|
entry.time = 0 // reproducible builds
|
||||||
zip.putNextEntry(entry)
|
zip.putNextEntry(entry)
|
||||||
zip.write(generate())
|
zip.write(invoke(entry))
|
||||||
zip.closeEntry()
|
zip.closeEntry()
|
||||||
}
|
}
|
||||||
zip.close()
|
zip.close()
|
||||||
|
@ -151,6 +97,7 @@ private fun buildZipFile(builderAction: SortedMap<String, () -> ByteArray>.() ->
|
||||||
return out.toByteArray()
|
return out.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val Project.defaultConfig: ApplicationDefaultConfig
|
private val Project.defaultConfig: ApplicationDefaultConfig
|
||||||
get() = when (val android = extensions.findByName("android")) {
|
get() = when (val android = extensions.findByName("android")) {
|
||||||
is com.android.build.gradle.AppExtension -> android.defaultConfig
|
is com.android.build.gradle.AppExtension -> android.defaultConfig
|
||||||
|
|
Loading…
Add table
Reference in a new issue