feat: support '.apks' files (PR #2647)

This commit is contained in:
o0kam1
2025-09-30 01:26:17 +08:00
committed by GitHub
parent 3ee476c6b6
commit 2a574d45d5
8 changed files with 108 additions and 1 deletions
+1
View File
@@ -23,6 +23,7 @@ dependencies {
runtimeOnly(project(":jadx-plugins:jadx-xapk-input"))
runtimeOnly(project(":jadx-plugins:jadx-aab-input"))
runtimeOnly(project(":jadx-plugins:jadx-apkm-input"))
runtimeOnly(project(":jadx-plugins:jadx-apks-input"))
implementation("org.jcommander:jcommander:2.0")
implementation("ch.qos.logback:logback-classic:1.5.18")
@@ -17,7 +17,7 @@ import jadx.gui.utils.NLS;
public class FileDialogWrapper {
private static final List<String> OPEN_FILES_EXTS = Arrays.asList(
"apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc", "jadx.kts", "xapk", "apkm");
"apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc", "jadx.kts", "xapk", "apkm", "apks");
private final MainWindow mainWindow;
@@ -0,0 +1,10 @@
plugins {
id("jadx-library")
id("jadx-kotlin")
}
dependencies {
api(project(":jadx-core"))
implementation(project(":jadx-plugins:jadx-dex-input"))
}
@@ -0,0 +1,38 @@
package jadx.plugins.input.apks
import jadx.api.plugins.input.ICodeLoader
import jadx.api.plugins.input.JadxCodeInput
import jadx.api.plugins.utils.CommonFileUtils
import jadx.plugins.input.dex.DexInputPlugin
import jadx.zip.ZipReader
import java.io.File
import java.nio.file.Path
class ApksCustomCodeInput(
private val dexInputPlugin: DexInputPlugin,
private val zipReader: ZipReader,
) : JadxCodeInput {
override fun loadFiles(input: List<Path>): ICodeLoader {
val apkFiles = mutableListOf<File>()
for (file in input.map { it.toFile() }) {
if (!file.name.endsWith(".apks")) continue
// Load all files ending with .apk
zipReader.visitEntries<Any>(file) { entry ->
if (entry.name.endsWith(".apk")) {
val tmpFile = entry.inputStream.use {
CommonFileUtils.saveToTempFile(it, ".apk").toFile()
}
apkFiles.add(tmpFile)
}
null
}
}
val codeLoader = dexInputPlugin.loadFiles(apkFiles.map { it.toPath() })
apkFiles.forEach { CommonFileUtils.safeDeleteFile(it) }
return codeLoader
}
}
@@ -0,0 +1,36 @@
package jadx.plugins.input.apks
import jadx.api.ResourceFile
import jadx.api.ResourcesLoader
import jadx.api.plugins.CustomResourcesLoader
import jadx.api.plugins.utils.CommonFileUtils
import jadx.zip.ZipReader
import java.io.File
class ApksCustomResourcesLoader(
private val zipReader: ZipReader,
) : CustomResourcesLoader {
private val tmpFiles = mutableListOf<File>()
override fun load(loader: ResourcesLoader, list: MutableList<ResourceFile>, file: File): Boolean {
if (!file.name.endsWith(".apks")) return false
// Load all files ending with .apk
zipReader.visitEntries<Any>(file) { entry ->
if (entry.name.endsWith(".apk")) {
val tmpFile = entry.inputStream.use {
CommonFileUtils.saveToTempFile(it, ".apk").toFile()
}
loader.defaultLoadFile(list, tmpFile, entry.name + "/")
tmpFiles += tmpFile
}
null
}
return true
}
override fun close() {
tmpFiles.forEach(CommonFileUtils::safeDeleteFile)
tmpFiles.clear()
}
}
@@ -0,0 +1,20 @@
package jadx.plugins.input.apks
import jadx.api.plugins.JadxPlugin
import jadx.api.plugins.JadxPluginContext
import jadx.api.plugins.JadxPluginInfo
import jadx.plugins.input.dex.DexInputPlugin
class ApksInputPlugin : JadxPlugin {
override fun getPluginInfo() = JadxPluginInfo(
"apks-input",
"APKS Input",
"Load .apks files",
)
override fun init(context: JadxPluginContext) {
val dexInputPlugin = context.plugins().getInstance(DexInputPlugin::class.java)
context.addCodeInput(ApksCustomCodeInput(dexInputPlugin, context.zipReader))
context.decompiler.addCustomResourcesLoader(ApksCustomResourcesLoader(context.zipReader))
}
}
@@ -0,0 +1 @@
jadx.plugins.input.apks.ApksInputPlugin
+1
View File
@@ -29,6 +29,7 @@ include("jadx-plugins:jadx-kotlin-source-debug-extension")
include("jadx-plugins:jadx-xapk-input")
include("jadx-plugins:jadx-aab-input")
include("jadx-plugins:jadx-apkm-input")
include("jadx-plugins:jadx-apks-input")
include("jadx-plugins:jadx-script:jadx-script-plugin")
include("jadx-plugins:jadx-script:jadx-script-runtime")