mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2026-01-25 12:11:03 +00:00
refactor: move stuff around and improve memory profile/performance
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
package app.revanced.arsc
|
||||
|
||||
/**
|
||||
* An exception thrown when working with [Apk]s.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
// TODO: this probably needs a better name but idk what to call it.
|
||||
sealed class ApkException(message: String, throwable: Throwable? = null) : Exception(message, throwable) {
|
||||
/**
|
||||
* An exception when decoding resources.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class Decode(message: String, throwable: Throwable? = null) : ApkException(message, throwable)
|
||||
|
||||
/**
|
||||
* An exception when encoding resources.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class Encode(message: String, throwable: Throwable? = null) : ApkException(message, throwable)
|
||||
|
||||
/**
|
||||
* An exception thrown when a reference could not be resolved.
|
||||
*
|
||||
* @param ref The invalid reference.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class InvalidReference(ref: String, throwable: Throwable? = null) :
|
||||
ApkException("Failed to resolve: $ref", throwable) {
|
||||
constructor(type: String, name: String, throwable: Throwable? = null) : this("@$type/$name", throwable)
|
||||
}
|
||||
|
||||
/**
|
||||
* An exception thrown when the [Apk] does not have a resource table, but was expected to have one.
|
||||
*/
|
||||
object MissingResourceTable : ApkException("Apk does not have a resource table.")
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package app.revanced.arsc
|
||||
|
||||
/**
|
||||
* An exception thrown when there is an error with APK resources.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
sealed class ApkResourceException(message: String, throwable: Throwable? = null) : Exception(message, throwable) {
|
||||
/**
|
||||
* An exception when decoding resources.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class Decode(message: String, throwable: Throwable? = null) : ApkResourceException(message, throwable)
|
||||
|
||||
/**
|
||||
* An exception when encoding resources.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class Encode(message: String, throwable: Throwable? = null) : ApkResourceException(message, throwable)
|
||||
|
||||
/**
|
||||
* An exception thrown when a reference could not be resolved.
|
||||
*
|
||||
* @param reference The invalid reference.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
class InvalidReference(reference: String, throwable: Throwable? = null) :
|
||||
ApkResourceException("Failed to resolve: $reference", throwable) {
|
||||
|
||||
/**
|
||||
* An exception thrown when a reference could not be resolved.
|
||||
*
|
||||
* @param type The type of the reference.
|
||||
* @param name The name of the reference.
|
||||
* @param throwable The corresponding [Throwable].
|
||||
*/
|
||||
constructor(type: String, name: String, throwable: Throwable? = null) : this("@$type/$name", throwable)
|
||||
}
|
||||
|
||||
/**
|
||||
* An exception thrown when the Apk file not have a resource table, but was expected to have one.
|
||||
*/
|
||||
object MissingResourceTable : ApkResourceException("Apk does not have a resource table.")
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package app.revanced.arsc.archive
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import app.revanced.arsc.logging.Logger
|
||||
import app.revanced.arsc.resource.ResourceContainer
|
||||
import app.revanced.arsc.resource.ResourceFile
|
||||
import app.revanced.arsc.xml.LazyXMLInputSource
|
||||
import com.reandroid.apk.ApkModule
|
||||
import com.reandroid.archive.ByteInputSource
|
||||
import com.reandroid.archive.InputSource
|
||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock
|
||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument
|
||||
import com.reandroid.xml.XMLDocument
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
|
||||
private fun isResXml(inputSource: InputSource) = inputSource.openStream().use { ResXmlDocument.isResXmlBlock(it) }
|
||||
|
||||
/**
|
||||
* A class for reading/writing files in an [ApkModule].
|
||||
*
|
||||
@@ -23,14 +23,6 @@ private fun isResXml(inputSource: InputSource) = inputSource.openStream().use {
|
||||
class Archive(private val module: ApkModule) {
|
||||
lateinit var resources: ResourceContainer
|
||||
|
||||
/**
|
||||
* The result of a [read] operation.
|
||||
*
|
||||
* @param xml Whether the contents were decoded from a [ResXmlDocument].
|
||||
* @param data The contents of the file.
|
||||
*/
|
||||
class ReadResult(val xml: Boolean, val data: ByteArray)
|
||||
|
||||
/**
|
||||
* The zip archive.
|
||||
*/
|
||||
@@ -44,7 +36,7 @@ class Archive(private val module: ApkModule) {
|
||||
fun lock(file: ResourceFile) {
|
||||
val path = file.handle.archivePath
|
||||
if (lockedFiles.contains(path)) {
|
||||
throw ApkException.Decode("${file.handle.virtualPath} is locked. If you are a patch developer, make sure you always close files.")
|
||||
throw ApkResourceException.Decode("${file.handle.virtualPath} is locked. If you are a patch developer, make sure you always close files.")
|
||||
}
|
||||
lockedFiles[path] = file
|
||||
}
|
||||
@@ -82,23 +74,21 @@ class Archive(private val module: ApkModule) {
|
||||
* Read an entry from the archive.
|
||||
*
|
||||
* @param path The archive path to read from.
|
||||
* @return A [ReadResult] containing the contents of the entry.
|
||||
* @return A [ArchiveResource] containing the contents of the entry.
|
||||
*/
|
||||
fun read(path: String) =
|
||||
archive.getInputSource(path)?.let { inputSource ->
|
||||
val xml = when {
|
||||
inputSource is LazyXMLInputSource -> inputSource.document
|
||||
isResXml(inputSource) -> module.loadResXmlDocument(
|
||||
inputSource
|
||||
).decodeToXml(resources.resourceTable.entryStore, resources.packageBlock?.id ?: 0)
|
||||
fun read(path: String) = archive.getInputSource(path)?.let { inputSource ->
|
||||
when {
|
||||
inputSource is LazyXMLInputSource -> ArchiveResource.XmlResource(inputSource.document)
|
||||
|
||||
else -> null
|
||||
}
|
||||
ResXmlDocument.isResXmlBlock(inputSource.openStream()) -> ArchiveResource.XmlResource(
|
||||
module
|
||||
.loadResXmlDocument(inputSource)
|
||||
.decodeToXml(resources.resourceTable.entryStore, resources.packageBlock?.id ?: 0)
|
||||
)
|
||||
|
||||
ReadResult(
|
||||
xml != null,
|
||||
xml?.toText()?.toByteArray() ?: inputSource.openStream().use { it.readAllBytes() })
|
||||
else -> ArchiveResource.RawResource(inputSource.openStream().use { it.readAllBytes() })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the manifest from the archive as an [AndroidManifestBlock].
|
||||
@@ -113,7 +103,7 @@ class Archive(private val module: ApkModule) {
|
||||
*
|
||||
* @return A [Map] containing all the dex files.
|
||||
*/
|
||||
fun readDexFiles() = module.listDexFiles().associate { file -> file.name to file.openStream().use { it.readAllBytes() } }
|
||||
fun readDexFiles() = module.listDexFiles().associate { file -> file.name to file.openStream() }
|
||||
|
||||
/**
|
||||
* Write the byte array to the archive entry.
|
||||
@@ -137,4 +127,36 @@ class Archive(private val module: ApkModule) {
|
||||
resources,
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* A resource file of an [Archive].
|
||||
*/
|
||||
abstract class ArchiveResource() : Closeable {
|
||||
private var pendingWrite = false
|
||||
|
||||
override fun close() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
/**
|
||||
* An [ResXmlDocument] resource file.
|
||||
*
|
||||
* @param xmlResource The [XMLDocument] of the file.
|
||||
*/
|
||||
class XmlResource(val xmlResource: XMLDocument, archive: Archive) : ArchiveResource()
|
||||
|
||||
/**
|
||||
* A raw resource file.
|
||||
*
|
||||
* @param data The raw data of the file.
|
||||
*/
|
||||
class RawResource(val data: ByteArray, archive: Archive) : ArchiveResource()
|
||||
|
||||
/**
|
||||
* @param virtualPath The resource file path. Example: /res/drawable-hdpi/icon.png.
|
||||
* @param archivePath The actual file path in the archive. Example: res/4a.png.
|
||||
* @param onClose An action to perform when the file associated with this handle is closed
|
||||
*/
|
||||
data class Handle(val virtualPath: String, val archivePath: String, val onClose: () -> Unit)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.revanced.arsc.resource
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import com.reandroid.arsc.coder.ValueDecoder
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import com.reandroid.arsc.coder.EncodeResult
|
||||
import com.reandroid.arsc.coder.ValueDecoder
|
||||
import com.reandroid.arsc.value.Entry
|
||||
import com.reandroid.arsc.value.ValueType
|
||||
import com.reandroid.arsc.value.array.ArrayBag
|
||||
@@ -45,7 +45,7 @@ open class Scalar internal constructor(private val valueType: ValueType, private
|
||||
sealed class Complex : Resource()
|
||||
|
||||
private fun encoded(encodeResult: EncodeResult?) = encodeResult?.let { Scalar(it.valueType, it.value) }
|
||||
?: throw ApkException.Encode("Failed to encode value")
|
||||
?: throw ApkResourceException.Encode("Failed to encode value")
|
||||
|
||||
/**
|
||||
* Encode a color.
|
||||
@@ -147,7 +147,7 @@ class Plurals(private val elements: Map<String, String>) : Complex() {
|
||||
val plurals = PluralsBag.create(entry)
|
||||
|
||||
plurals.putAll(elements.asIterable().associate { (k, v) ->
|
||||
PluralsQuantity.value(k) to PluralsBagItem.string(resources.getOrCreateTableString(v))
|
||||
PluralsQuantity.value(k) to PluralsBagItem.string(resources.getOrCreateString(v))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ class Plurals(private val elements: Map<String, String>) : Complex() {
|
||||
* @param value The string value.
|
||||
*/
|
||||
class StringResource(val value: String) : Scalar(ValueType.STRING, 0) {
|
||||
private fun tableString(resources: ResourceContainer) = resources.getOrCreateTableString(value)
|
||||
private fun tableString(resources: ResourceContainer) = resources.getOrCreateString(value)
|
||||
|
||||
override fun data(resources: ResourceContainer) = tableString(resources).index
|
||||
override fun toArrayItem(resources: ResourceContainer) = ArrayBagItem.string(tableString(resources))
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package app.revanced.arsc.resource
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import app.revanced.arsc.archive.Archive
|
||||
import com.reandroid.apk.xmlencoder.EncodeUtil
|
||||
import com.reandroid.arsc.chunk.PackageBlock
|
||||
import com.reandroid.arsc.chunk.TableBlock
|
||||
import com.reandroid.arsc.value.Entry
|
||||
import com.reandroid.arsc.value.ResConfig
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* A high-level API for modifying the resources contained in an Apk.
|
||||
* A high-level API for modifying the resources contained in an APK file.
|
||||
*
|
||||
* @param tableBlock The resources.arsc file of this Apk.
|
||||
* @param archive The [Archive] containing this resource table.
|
||||
* @param tableBlock The resources file of this APK file. Typically named "resources.arsc".
|
||||
*/
|
||||
class ResourceContainer(private val archive: Archive, internal val tableBlock: TableBlock?) {
|
||||
internal val packageBlock = tableBlock?.pickOne() // Pick the main PackageBlock.
|
||||
@@ -22,10 +24,18 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
archive.resources = this
|
||||
}
|
||||
|
||||
private fun expectPackageBlock() = packageBlock ?: throw ApkException.MissingResourceTable
|
||||
/**
|
||||
* Open a resource file, creating it if the file does not exist.
|
||||
*
|
||||
* @param path The resource file path.
|
||||
* @return The corresponding [ResourceFile],
|
||||
*/
|
||||
fun openFile(path: String) = ResourceFile(createHandle(path), archive)
|
||||
|
||||
internal fun getOrCreateTableString(value: String) =
|
||||
tableBlock?.stringPool?.getOrCreate(value) ?: throw ApkException.MissingResourceTable
|
||||
private fun getPackageBlock() = packageBlock ?: throw ApkResourceException.MissingResourceTable
|
||||
|
||||
internal fun getOrCreateString(value: String) =
|
||||
tableBlock?.stringPool?.getOrCreate(value) ?: throw ApkResourceException.MissingResourceTable
|
||||
|
||||
/**
|
||||
* Set the value of the [Entry] to the one specified.
|
||||
@@ -54,7 +64,7 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
private fun getEntry(type: String, name: String, qualifiers: String?): Entry? {
|
||||
val resourceId = try {
|
||||
resourceTable.resolve("@$type/$name")
|
||||
} catch (_: ApkException.InvalidReference) {
|
||||
} catch (_: ApkResourceException.InvalidReference) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -69,9 +79,9 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
* @param resPath The path of the resource.
|
||||
*/
|
||||
private fun createHandle(resPath: String): ResourceFile.Handle {
|
||||
if (resPath.startsWith("res/values")) throw ApkException.Decode("Decoding the resource table as a file is not supported")
|
||||
if (resPath.startsWith("res/values")) throw ApkResourceException.Decode("Decoding the resource table as a file is not supported")
|
||||
|
||||
var callback = {}
|
||||
var onClose = {}
|
||||
var archivePath = resPath
|
||||
|
||||
if (tableBlock != null && resPath.startsWith("res/") && resPath.count { it == '/' } == 2) {
|
||||
@@ -89,11 +99,11 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
archivePath = resolvedPath
|
||||
} else {
|
||||
// An entry for this specific resource file was not found in the resource table, so we have to register it after we save.
|
||||
callback = { set(type, name, StringResource(archivePath), qualifiers) }
|
||||
onClose = { set(type, name, StringResource(archivePath), qualifiers) }
|
||||
}
|
||||
}
|
||||
|
||||
return ResourceFile.Handle(resPath, archivePath, callback)
|
||||
return ResourceFile.Handle(resPath, archivePath, onClose)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +115,7 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
* @param configuration The resource configuration.
|
||||
*/
|
||||
fun set(type: String, name: String, value: Resource, configuration: String? = null) =
|
||||
expectPackageBlock().getOrCreate(configuration, type, name).also { it.setTo(value) }.resourceId
|
||||
getPackageBlock().getOrCreate(configuration, type, name).also { it.setTo(value) }.resourceId
|
||||
|
||||
/**
|
||||
* Create or update multiple resources in an ARSC type block.
|
||||
@@ -115,21 +125,11 @@ class ResourceContainer(private val archive: Archive, internal val tableBlock: T
|
||||
* @param configuration The resource configuration.
|
||||
*/
|
||||
fun setGroup(type: String, map: Map<String, Resource>, configuration: String? = null) {
|
||||
expectPackageBlock().getOrCreateSpecTypePair(type).getOrCreateTypeBlock(configuration).apply {
|
||||
getPackageBlock().getOrCreateSpecTypePair(type).getOrCreateTypeBlock(configuration).apply {
|
||||
map.forEach { (name, value) -> getOrCreateEntry(name).setTo(value) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a resource file, creating it if the file does not exist.
|
||||
*
|
||||
* @param path The resource file path.
|
||||
* @return The corresponding [ResourceFile],
|
||||
*/
|
||||
fun openFile(path: String) = ResourceFile(
|
||||
createHandle(path), archive
|
||||
)
|
||||
|
||||
/**
|
||||
* Update the [PackageBlock] name to match the manifest.
|
||||
*/
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
package app.revanced.arsc.resource
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import app.revanced.arsc.archive.Archive
|
||||
import app.revanced.arsc.resource.ResourceFile.Handle
|
||||
import com.reandroid.xml.XMLDocument
|
||||
import com.reandroid.xml.XMLException
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.*
|
||||
|
||||
/**
|
||||
* A resource file inside an [Apk].
|
||||
* Instantiate a [ResourceFile] and lock the file which [handle] is associated with.
|
||||
*
|
||||
* @param handle The [Handle] associated with this file.
|
||||
* @param archive The [Archive] that the file resides in.
|
||||
*/
|
||||
class ResourceFile private constructor(
|
||||
internal val handle: Handle,
|
||||
private val archive: Archive,
|
||||
readResult: Archive.ReadResult?
|
||||
) :
|
||||
Closeable {
|
||||
readResult: Archive.ArchiveResource?
|
||||
) : Closeable {
|
||||
private var pendingWrite = false
|
||||
private val isXmlResource = readResult is Archive.ArchiveResource.XmlResource
|
||||
|
||||
init {
|
||||
archive.lock(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param virtualPath The resource file path (res/drawable-hdpi/icon.png)
|
||||
* @param archivePath The actual file path in the archive (res/4a.png)
|
||||
* @param close An action to perform when the file associated with this handle is closed
|
||||
*/
|
||||
internal data class Handle(val virtualPath: String, val archivePath: String, val close: () -> Unit)
|
||||
|
||||
private var changed = false
|
||||
private val xml = readResult?.xml ?: handle.virtualPath.endsWith(".xml")
|
||||
|
||||
/**
|
||||
* @param handle The [Handle] associated with this file
|
||||
* @param archive The [Archive] that the file resides in
|
||||
* Instantiate a [ResourceFile].
|
||||
*
|
||||
* @param handle The [Handle] associated with this file.
|
||||
* @param archive The [Archive] that the file resides in.
|
||||
*/
|
||||
internal constructor(handle: Handle, archive: Archive) : this(
|
||||
handle,
|
||||
@@ -41,15 +37,15 @@ class ResourceFile private constructor(
|
||||
try {
|
||||
archive.read(handle.archivePath)
|
||||
} catch (e: XMLException) {
|
||||
throw ApkException.Decode("Failed to decode XML while reading ${handle.virtualPath}", e)
|
||||
throw ApkResourceException.Decode("Failed to decode XML while reading ${handle.virtualPath}", e)
|
||||
} catch (e: IOException) {
|
||||
throw ApkException.Decode("Could not read ${handle.virtualPath}", e)
|
||||
throw ApkResourceException.Decode("Could not read ${handle.virtualPath}", e)
|
||||
}
|
||||
)
|
||||
|
||||
var contents = readResult?.data ?: ByteArray(0)
|
||||
set(value) {
|
||||
changed = true
|
||||
pendingWrite = true
|
||||
field = value
|
||||
}
|
||||
|
||||
@@ -57,36 +53,34 @@ class ResourceFile private constructor(
|
||||
|
||||
override fun toString() = handle.virtualPath
|
||||
|
||||
init {
|
||||
archive.lock(this)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
if (changed) {
|
||||
if (pendingWrite) {
|
||||
val path = handle.archivePath
|
||||
if (xml) archive.writeXml(
|
||||
|
||||
if (isXmlResource) archive.writeXml(
|
||||
path,
|
||||
try {
|
||||
XMLDocument.load(String(contents))
|
||||
XMLDocument.load(inputStream())
|
||||
} catch (e: XMLException) {
|
||||
throw ApkException.Encode("Failed to parse XML while writing ${handle.virtualPath}", e)
|
||||
throw ApkResourceException.Encode("Failed to parse XML while writing ${handle.virtualPath}", e)
|
||||
}
|
||||
|
||||
) else archive.writeRaw(path, contents)
|
||||
}
|
||||
handle.close()
|
||||
|
||||
handle.onClose()
|
||||
|
||||
|
||||
archive.unlock(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_BUFFER_SIZE = 4096
|
||||
}
|
||||
|
||||
fun inputStream(): InputStream = ByteArrayInputStream(contents)
|
||||
fun outputStream(bufferSize: Int = DEFAULT_BUFFER_SIZE): OutputStream =
|
||||
object : ByteArrayOutputStream(bufferSize) {
|
||||
override fun close() {
|
||||
this@ResourceFile.contents = if (buf.size > count) buf.copyOf(count) else buf
|
||||
super.close()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param virtualPath The resource file path. Example: /res/drawable-hdpi/icon.png.
|
||||
* @param archivePath The actual file path in the archive. Example: res/4a.png.
|
||||
* @param onClose An action to perform when the file associated with this handle is closed
|
||||
*/
|
||||
internal data class Handle(val virtualPath: String, val archivePath: String, val onClose: () -> Unit)
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.arsc.resource
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import com.reandroid.apk.xmlencoder.EncodeException
|
||||
import com.reandroid.apk.xmlencoder.EncodeMaterials
|
||||
import com.reandroid.arsc.util.FrameworkTable
|
||||
@@ -8,7 +8,7 @@ import com.reandroid.arsc.value.Entry
|
||||
import com.reandroid.common.TableEntryStore
|
||||
|
||||
/**
|
||||
* A high-level API for resolving resources in the resource table, which spans the entire [ApkBundle].
|
||||
* A high-level API for resolving resources in the resource table, which spans the entire ApkBundle.
|
||||
*/
|
||||
class ResourceTable(base: ResourceContainer, all: Sequence<ResourceContainer>) {
|
||||
private val packageName = base.packageBlock!!.name
|
||||
@@ -31,7 +31,7 @@ class ResourceTable(base: ResourceContainer, all: Sequence<ResourceContainer>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource mappings which are generated when the [ApkBundle] is created.
|
||||
* The resource mappings which are generated when the ApkBundle is created.
|
||||
*/
|
||||
private val tableIdentifier = encodeMaterials.tableIdentifier
|
||||
|
||||
@@ -52,7 +52,7 @@ class ResourceTable(base: ResourceContainer, all: Sequence<ResourceContainer>) {
|
||||
fun resolveLocal(type: String, name: String) =
|
||||
modifiedResources[type]?.get(name)
|
||||
?: tableIdentifier.get(packageName, type, name)?.resourceId
|
||||
?: throw ApkException.InvalidReference(
|
||||
?: throw ApkResourceException.InvalidReference(
|
||||
type,
|
||||
name
|
||||
)
|
||||
@@ -66,7 +66,7 @@ class ResourceTable(base: ResourceContainer, all: Sequence<ResourceContainer>) {
|
||||
fun resolve(reference: String) = try {
|
||||
encodeMaterials.resolveReference(reference)
|
||||
} catch (e: EncodeException) {
|
||||
throw ApkException.InvalidReference(reference, e)
|
||||
throw ApkResourceException.InvalidReference(reference, e)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.arsc.xml
|
||||
|
||||
import app.revanced.arsc.ApkException
|
||||
import app.revanced.arsc.ApkResourceException
|
||||
import app.revanced.arsc.resource.ResourceContainer
|
||||
import app.revanced.arsc.resource.boolean
|
||||
import com.reandroid.apk.xmlencoder.EncodeException
|
||||
@@ -11,7 +11,7 @@ import com.reandroid.xml.XMLElement
|
||||
import com.reandroid.xml.source.XMLDocumentSource
|
||||
|
||||
/**
|
||||
* Archive input source that lazily encodes the [XMLDocument] when you read from it.
|
||||
* Archive input source to lazily encode an [XMLDocument] after it has been modified.
|
||||
*
|
||||
* @param name The file name of this input source.
|
||||
* @param document The [XMLDocument] to encode.
|
||||
@@ -38,7 +38,7 @@ internal class LazyXMLInputSource(
|
||||
|
||||
override fun getResXmlBlock(): ResXmlDocument {
|
||||
if (!ready) {
|
||||
throw ApkException.Encode("$name has not been encoded yet")
|
||||
throw ApkResourceException.Encode("$name has not been encoded yet")
|
||||
}
|
||||
|
||||
return super.getResXmlBlock()
|
||||
|
||||
Reference in New Issue
Block a user