98 lines
2.9 KiB
Kotlin
98 lines
2.9 KiB
Kotlin
package xyz.nulldev.androidcompat.pm
|
|
|
|
import android.content.pm.PackageInfo
|
|
import android.content.pm.Signature
|
|
import android.os.Bundle
|
|
import com.android.apksig.ApkVerifier
|
|
import com.googlecode.d2j.dex.Dex2jar
|
|
import net.dongliu.apk.parser.ApkFile
|
|
import net.dongliu.apk.parser.ApkParsers
|
|
import org.w3c.dom.Element
|
|
import org.w3c.dom.Node
|
|
import org.w3c.dom.NodeList
|
|
import java.io.File
|
|
import javax.imageio.ImageIO
|
|
import javax.xml.parsers.DocumentBuilderFactory
|
|
|
|
data class InstalledPackage(val root: File) {
|
|
val apk = File(root, "package.apk")
|
|
val jar = File(root, "translated.jar")
|
|
val icon = File(root, "icon.png")
|
|
|
|
val info: PackageInfo
|
|
get() = ApkParsers.getMetaInfo(apk).toPackageInfo(apk).also {
|
|
val parsed = ApkFile(apk)
|
|
val dbFactory = DocumentBuilderFactory.newInstance()
|
|
val dBuilder = dbFactory.newDocumentBuilder()
|
|
val doc = parsed.manifestXml.byteInputStream().use {
|
|
dBuilder.parse(it)
|
|
}
|
|
|
|
it.applicationInfo.metaData = Bundle().apply {
|
|
val appTag = doc.getElementsByTagName("application").item(0)
|
|
|
|
appTag?.childNodes?.toList()?.filter {
|
|
it.nodeType == Node.ELEMENT_NODE
|
|
}?.map {
|
|
it as Element
|
|
}?.filter {
|
|
it.tagName == "meta-data"
|
|
}?.map {
|
|
putString(
|
|
it.attributes.getNamedItem("android:name").nodeValue,
|
|
it.attributes.getNamedItem("android:value").nodeValue
|
|
)
|
|
}
|
|
}
|
|
|
|
it.signatures = (
|
|
parsed.apkSingers.flatMap { it.certificateMetas }
|
|
/*+ parsed.apkV2Singers.flatMap { it.certificateMetas }*/
|
|
) // Blocked by: https://github.com/hsiafan/apk-parser/issues/72
|
|
.map { Signature(it.data) }.toTypedArray()
|
|
}
|
|
|
|
fun verify(): Boolean {
|
|
val res = ApkVerifier.Builder(apk)
|
|
.build()
|
|
.verify()
|
|
|
|
return res.isVerified
|
|
}
|
|
|
|
fun writeIcon() {
|
|
try {
|
|
val icons = ApkFile(apk).allIcons
|
|
|
|
val read = icons.filter { it.isFile }.map {
|
|
it.data.inputStream().use {
|
|
ImageIO.read(it)
|
|
}
|
|
}.sortedByDescending { it.width * it.height }.firstOrNull() ?: return
|
|
|
|
ImageIO.write(read, "png", icon)
|
|
} catch (e: Exception) {
|
|
icon.delete()
|
|
}
|
|
}
|
|
|
|
fun writeJar() {
|
|
try {
|
|
Dex2jar.from(apk).to(jar.toPath())
|
|
} catch (e: Exception) {
|
|
jar.delete()
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
fun NodeList.toList(): List<Node> {
|
|
val out = mutableListOf<Node>()
|
|
|
|
for (i in 0 until length)
|
|
out += item(i)
|
|
|
|
return out
|
|
}
|
|
}
|
|
}
|