You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-17 07:30:49 +02:00
Compare commits
18 Commits
arsclib-re
...
v12.1.0-de
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d6945677c4 | ||
![]() |
aedf4aea08 | ||
![]() |
dc28d414dc | ||
![]() |
9755bab298 | ||
![]() |
fae4029cfc | ||
![]() |
1790f0d706 | ||
![]() |
0ba2c51676 | ||
![]() |
03cd97b49c | ||
![]() |
16a162c1dd | ||
![]() |
c9bbcf2bf2 | ||
![]() |
86e1bf6078 | ||
![]() |
1bca84ef0b | ||
![]() |
e0f8e1b71a | ||
![]() |
416d69142f | ||
![]() |
426807aeaa | ||
![]() |
90cb075a97 | ||
![]() |
ac2ca8fbd3 | ||
![]() |
69e4a49065 |
@@ -7,7 +7,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@semantic-release/commit-analyzer",
|
[
|
||||||
|
"@semantic-release/commit-analyzer", {
|
||||||
|
"releaseRules": [
|
||||||
|
{ "type": "build", "scope": "Needs bump", "release": "patch" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
"gradle-semantic-release-plugin",
|
"gradle-semantic-release-plugin",
|
||||||
|
53
CHANGELOG.md
53
CHANGELOG.md
@@ -1,3 +1,56 @@
|
|||||||
|
# [12.1.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v12.1.0-dev.1...v12.1.0-dev.2) (2023-08-03)
|
||||||
|
|
||||||
|
# [12.1.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v12.0.0...v12.1.0-dev.1) (2023-08-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `MutableMethod.getInstructions` extension function ([fae4029](https://github.com/ReVanced/revanced-patcher/commit/fae4029cfccfad7aa3dd8f7fbef1c63ee26b85b3))
|
||||||
|
|
||||||
|
# [12.0.0](https://github.com/ReVanced/revanced-patcher/compare/v11.0.4...v12.0.0) (2023-07-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* correct access flags of `PackageMetadata` ([416d691](https://github.com/ReVanced/revanced-patcher/commit/416d69142f50dab49c9ea3f027e9d53e4777f257))
|
||||||
|
* set resource table via resource decoder ([e0f8e1b](https://github.com/ReVanced/revanced-patcher/commit/e0f8e1b71a295948b610029c89a48f52762396b6))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Deprecate `Version` annotation ([c9bbcf2](https://github.com/ReVanced/revanced-patcher/commit/c9bbcf2bf2b0f50ab9100380a3a66c6346ad42ac))
|
||||||
|
* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](https://github.com/ReVanced/revanced-patcher/commit/69e4a490659ebc4fb4bf46148634f4b064ef1713))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* This removes the previously available `Path` option
|
||||||
|
|
||||||
|
# [12.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v12.0.0-dev.1...v12.0.0-dev.2) (2023-07-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Deprecate `Version` annotation ([400442f](https://github.com/ReVanced/revanced-patcher/commit/400442f70ee56cafd4493b2ce64a294db9836509))
|
||||||
|
|
||||||
|
# [12.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v11.0.4...v12.0.0-dev.1) (2023-07-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* correct access flags of `PackageMetadata` ([416d691](https://github.com/ReVanced/revanced-patcher/commit/416d69142f50dab49c9ea3f027e9d53e4777f257))
|
||||||
|
* set resource table via resource decoder ([e0f8e1b](https://github.com/ReVanced/revanced-patcher/commit/e0f8e1b71a295948b610029c89a48f52762396b6))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](https://github.com/ReVanced/revanced-patcher/commit/69e4a490659ebc4fb4bf46148634f4b064ef1713))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* This removes the previously available `Path` option
|
||||||
|
|
||||||
## [11.0.4](https://github.com/revanced/revanced-patcher/compare/v11.0.3...v11.0.4) (2023-07-01)
|
## [11.0.4](https://github.com/revanced/revanced-patcher/compare/v11.0.3...v11.0.4) (2023-07-01)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -23,9 +23,9 @@ dependencies {
|
|||||||
implementation("xpp3:xpp3:1.1.4c")
|
implementation("xpp3:xpp3:1.1.4c")
|
||||||
implementation("app.revanced:smali:2.5.3-a3836654")
|
implementation("app.revanced:smali:2.5.3-a3836654")
|
||||||
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
|
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
|
||||||
implementation("app.revanced:apktool-lib:2.7.0")
|
implementation("app.revanced:apktool-lib:2.8.3")
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC")
|
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.22")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
|
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel=true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching=true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 11.0.4
|
version = 12.1.0-dev.2
|
||||||
|
@@ -7,15 +7,16 @@ import app.revanced.patcher.extensions.PatchExtensions.requiresIntegrations
|
|||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import app.revanced.patcher.util.VersionReader
|
import brut.androlib.AaptInvoker
|
||||||
import brut.androlib.Androlib
|
import brut.androlib.ApkDecoder
|
||||||
import brut.androlib.meta.UsesFramework
|
import brut.androlib.Config
|
||||||
import brut.androlib.options.BuildOptions
|
import brut.androlib.res.Framework
|
||||||
import brut.androlib.res.AndrolibResources
|
import brut.androlib.res.ResourcesDecoder
|
||||||
import brut.androlib.res.data.ResPackage
|
import brut.androlib.res.decoder.AndroidManifestResourceParser
|
||||||
import brut.androlib.res.decoder.AXmlResourceParser
|
|
||||||
import brut.androlib.res.decoder.ResAttrDecoder
|
import brut.androlib.res.decoder.ResAttrDecoder
|
||||||
import brut.androlib.res.decoder.XmlPullStreamDecoder
|
import brut.androlib.res.decoder.XmlPullStreamDecoder
|
||||||
|
import brut.androlib.res.util.ExtMXSerializer
|
||||||
|
import brut.androlib.res.util.ExtXmlSerializer
|
||||||
import brut.androlib.res.xml.ResXmlPatcher
|
import brut.androlib.res.xml.ResXmlPatcher
|
||||||
import brut.directory.ExtFile
|
import brut.directory.ExtFile
|
||||||
import lanchon.multidexlib2.BasicDexFileNamer
|
import lanchon.multidexlib2.BasicDexFileNamer
|
||||||
@@ -42,14 +43,9 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
private var mergeIntegrations = false
|
private var mergeIntegrations = false
|
||||||
val context: PatcherContext
|
val context: PatcherContext
|
||||||
|
|
||||||
companion object {
|
private val config = Config.getDefaultConfig().apply {
|
||||||
@JvmStatic
|
aaptPath = options.aaptPath
|
||||||
val version = VersionReader.read()
|
frameworkDirectory = options.frameworkDirectory
|
||||||
private fun BuildOptions.setBuildOptions(options: PatcherOptions) {
|
|
||||||
this.aaptPath = options.aaptPath
|
|
||||||
this.useAapt2 = true
|
|
||||||
this.frameworkFolderLocation = options.frameworkFolderLocation
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -86,55 +82,39 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
* Save the patched dex file.
|
* Save the patched dex file.
|
||||||
*/
|
*/
|
||||||
fun save(): PatcherResult {
|
fun save(): PatcherResult {
|
||||||
val packageMetadata = context.packageMetadata
|
|
||||||
val metaInfo = packageMetadata.metaInfo
|
|
||||||
var resourceFile: File? = null
|
var resourceFile: File? = null
|
||||||
|
|
||||||
when (resourceDecodingMode) {
|
when (resourceDecodingMode) {
|
||||||
ResourceDecodingMode.FULL -> {
|
ResourceDecodingMode.FULL -> {
|
||||||
|
logger.info("Compiling resources")
|
||||||
|
|
||||||
val cacheDirectory = ExtFile(options.resourceCacheDirectory)
|
val cacheDirectory = ExtFile(options.resourceCacheDirectory)
|
||||||
|
val aaptFile = cacheDirectory.resolve("aapt_temp_file").also {
|
||||||
|
Files.deleteIfExists(it.toPath())
|
||||||
|
}.also { resourceFile = it }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val androlibResources = AndrolibResources().also { resources ->
|
AaptInvoker(
|
||||||
resources.buildOptions = BuildOptions().also { buildOptions ->
|
config,
|
||||||
buildOptions.setBuildOptions(options)
|
context.packageMetadata.apkInfo
|
||||||
buildOptions.isFramework = metaInfo.isFrameworkApk
|
).invokeAapt(
|
||||||
buildOptions.resourcesAreCompressed = metaInfo.compressionType
|
aaptFile,
|
||||||
buildOptions.doNotCompress = metaInfo.doNotCompress
|
cacheDirectory.resolve("AndroidManifest.xml").also {
|
||||||
|
ResXmlPatcher.fixingPublicAttrsInProviderAttributes(it)
|
||||||
|
},
|
||||||
|
cacheDirectory.resolve("res"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
context.packageMetadata.apkInfo.usesFramework.let { usesFramework ->
|
||||||
|
usesFramework.ids.map { id ->
|
||||||
|
Framework(config).getFrameworkApk(id, usesFramework.tag)
|
||||||
|
}.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
resources.setSdkInfo(metaInfo.sdkInfo)
|
|
||||||
resources.setVersionInfo(metaInfo.versionInfo)
|
|
||||||
resources.setSharedLibrary(metaInfo.sharedLibrary)
|
|
||||||
resources.setSparseResources(metaInfo.sparseResources)
|
|
||||||
}
|
|
||||||
|
|
||||||
val manifestFile = cacheDirectory.resolve("AndroidManifest.xml")
|
|
||||||
|
|
||||||
ResXmlPatcher.fixingPublicAttrsInProviderAttributes(manifestFile)
|
|
||||||
|
|
||||||
val aaptFile = cacheDirectory.resolve("aapt_temp_file")
|
|
||||||
|
|
||||||
// delete if it exists
|
|
||||||
Files.deleteIfExists(aaptFile.toPath())
|
|
||||||
|
|
||||||
val resDirectory = cacheDirectory.resolve("res")
|
|
||||||
val includedFiles = metaInfo.usesFramework.ids.map { id ->
|
|
||||||
androlibResources.getFrameworkApk(
|
|
||||||
id, metaInfo.usesFramework.tag
|
|
||||||
)
|
|
||||||
}.toTypedArray()
|
|
||||||
|
|
||||||
logger.info("Compiling resources")
|
|
||||||
androlibResources.aaptPackage(
|
|
||||||
aaptFile, manifestFile, resDirectory, null, null, includedFiles
|
|
||||||
)
|
)
|
||||||
|
|
||||||
resourceFile = aaptFile
|
|
||||||
} finally {
|
} finally {
|
||||||
cacheDirectory.close()
|
cacheDirectory.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> logger.info("Not compiling resources because resource patching is not required")
|
else -> logger.info("Not compiling resources because resource patching is not required")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +136,7 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
dexFiles.map {
|
dexFiles.map {
|
||||||
app.revanced.patcher.util.dex.DexFile(it.key, it.value.readAt(0))
|
app.revanced.patcher.util.dex.DexFile(it.key, it.value.readAt(0))
|
||||||
},
|
},
|
||||||
metaInfo.doNotCompress?.toList(),
|
context.packageMetadata.apkInfo.doNotCompress?.toList(),
|
||||||
resourceFile
|
resourceFile
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -200,72 +180,68 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
private fun decodeResources(mode: ResourceDecodingMode) {
|
private fun decodeResources(mode: ResourceDecodingMode) {
|
||||||
val extInputFile = ExtFile(options.inputFile)
|
val extInputFile = ExtFile(options.inputFile)
|
||||||
try {
|
try {
|
||||||
val androlib = Androlib(BuildOptions().also { it.setBuildOptions(options) })
|
val resourcesDecoder = ResourcesDecoder(config, extInputFile)
|
||||||
val resourceTable = androlib.getResTable(extInputFile, true)
|
|
||||||
when (mode) {
|
when (mode) {
|
||||||
ResourceDecodingMode.FULL -> {
|
ResourceDecodingMode.FULL -> {
|
||||||
val outDir = File(options.resourceCacheDirectory)
|
val outDir = File(options.resourceCacheDirectory)
|
||||||
if (outDir.exists()) {
|
if (outDir.exists()) {
|
||||||
logger.info("Deleting existing resource cache directory")
|
logger.info("Deleting existing resource cache directory")
|
||||||
if (!outDir.deleteRecursively()) {
|
if (!outDir.deleteRecursively()) logger.error("Failed to delete existing resource cache directory")
|
||||||
logger.error("Failed to delete existing resource cache directory")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outDir.mkdirs()
|
outDir.mkdirs()
|
||||||
|
|
||||||
logger.info("Decoding resources")
|
logger.info("Decoding resources")
|
||||||
|
|
||||||
// decode resources to cache directory
|
resourcesDecoder.decodeManifest(outDir)
|
||||||
androlib.decodeManifestWithResources(extInputFile, outDir, resourceTable)
|
resourcesDecoder.decodeResources(outDir)
|
||||||
androlib.decodeResourcesFull(extInputFile, outDir, resourceTable)
|
|
||||||
|
|
||||||
// read additional metadata from the resource table
|
|
||||||
context.packageMetadata.let { metadata ->
|
|
||||||
metadata.metaInfo.usesFramework = UsesFramework().also { framework ->
|
|
||||||
framework.ids = resourceTable.listFramePackages().map { it.id }.sorted()
|
|
||||||
}
|
|
||||||
|
|
||||||
// read files to not compress
|
|
||||||
metadata.metaInfo.doNotCompress = buildList {
|
|
||||||
androlib.recordUncompressedFiles(extInputFile, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
context.packageMetadata.also {
|
||||||
|
it.apkInfo = resourcesDecoder.apkInfo
|
||||||
|
}.apkInfo.doNotCompress = ApkDecoder(config, extInputFile).recordUncompressedFiles(
|
||||||
|
context.packageMetadata.apkInfo, resourcesDecoder.resFileMapping
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDecodingMode.MANIFEST_ONLY -> {
|
ResourceDecodingMode.MANIFEST_ONLY -> {
|
||||||
logger.info("Decoding AndroidManifest.xml only, because resources are not needed")
|
logger.info("Decoding AndroidManifest.xml only, because resources are not needed")
|
||||||
|
|
||||||
// create decoder for the resource table
|
// Instead of using resourceDecoder.decodeManifest which decodes the whole file
|
||||||
val decoder = ResAttrDecoder()
|
// use the XmlPullStreamDecoder in order to get necessary information from the manifest
|
||||||
decoder.currentPackage = ResPackage(resourceTable, 0, null)
|
// used below.
|
||||||
|
XmlPullStreamDecoder(AndroidManifestResourceParser().apply {
|
||||||
// create xml parser with the decoder
|
attrDecoder = ResAttrDecoder().apply { this.resTable = resourcesDecoder.resTable }
|
||||||
val axmlParser = AXmlResourceParser()
|
}, ExtMXSerializer().apply {
|
||||||
axmlParser.attrDecoder = decoder
|
setProperty(
|
||||||
|
ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, " "
|
||||||
// parse package information with the decoder and parser which will set required values in the resource table
|
)
|
||||||
// instead of decodeManifest another more low level solution can be created to make it faster/better
|
setProperty(
|
||||||
XmlPullStreamDecoder(
|
ExtXmlSerializer.PROPERTY_SERIALIZER_LINE_SEPARATOR,
|
||||||
axmlParser, AndrolibResources().resXmlSerializer
|
System.getProperty("line.separator")
|
||||||
|
)
|
||||||
|
setProperty(
|
||||||
|
ExtXmlSerializer.PROPERTY_DEFAULT_ENCODING,
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
setDisabledAttrEscape(true)
|
||||||
|
}
|
||||||
).decodeManifest(
|
).decodeManifest(
|
||||||
extInputFile.directory.getFileInput("AndroidManifest.xml"),
|
extInputFile.directory.getFileInput("AndroidManifest.xml"),
|
||||||
// Older Android versions do not support OutputStream.nullOutputStream()
|
// Older Android versions do not support OutputStream.nullOutputStream()
|
||||||
object : OutputStream() {
|
object : OutputStream() { override fun write(b: Int) { /* do nothing */ } }
|
||||||
override fun write(b: Int) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read of the resourceTable which is created by reading the manifest file
|
// Get the package name and version from the manifest using the XmlPullStreamDecoder.
|
||||||
|
// XmlPullStreamDecoder.decodeManifest() sets metadata.apkInfo.
|
||||||
context.packageMetadata.let { metadata ->
|
context.packageMetadata.let { metadata ->
|
||||||
metadata.packageName = resourceTable.currentResPackage.name
|
metadata.apkInfo = resourcesDecoder.apkInfo
|
||||||
metadata.packageVersion = resourceTable.versionInfo.versionName ?: resourceTable.versionInfo.versionCode
|
|
||||||
metadata.metaInfo.versionInfo = resourceTable.versionInfo
|
metadata.packageName = resourcesDecoder.resTable.currentResPackage.name
|
||||||
metadata.metaInfo.sdkInfo = resourceTable.sdkInfo
|
resourcesDecoder.apkInfo.versionInfo.let {
|
||||||
|
metadata.packageVersion = it.versionName ?: it.versionCode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
extInputFile.close()
|
extInputFile.close()
|
||||||
|
@@ -9,13 +9,13 @@ import java.io.File
|
|||||||
* @param inputFile The input file (usually an apk file).
|
* @param inputFile The input file (usually an apk file).
|
||||||
* @param resourceCacheDirectory Directory to cache resources.
|
* @param resourceCacheDirectory Directory to cache resources.
|
||||||
* @param aaptPath Optional path to a custom aapt binary.
|
* @param aaptPath Optional path to a custom aapt binary.
|
||||||
* @param frameworkFolderLocation Optional path to a custom framework folder.
|
* @param frameworkDirectory Optional path to a custom framework directory.
|
||||||
* @param logger Custom logger implementation for the [Patcher].
|
* @param logger Custom logger implementation for the [Patcher].
|
||||||
*/
|
*/
|
||||||
data class PatcherOptions(
|
data class PatcherOptions(
|
||||||
internal val inputFile: File,
|
internal val inputFile: File,
|
||||||
internal val resourceCacheDirectory: String,
|
internal val resourceCacheDirectory: String,
|
||||||
internal val aaptPath: String? = null,
|
internal val aaptPath: String? = null,
|
||||||
internal val frameworkFolderLocation: String? = null,
|
internal val frameworkDirectory: String? = null,
|
||||||
internal val logger: Logger = NopLogger
|
internal val logger: Logger = NopLogger
|
||||||
)
|
)
|
||||||
|
@@ -26,6 +26,7 @@ annotation class Description(
|
|||||||
* @param version The version of a [Patch].
|
* @param version The version of a [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Deprecated("This annotation is deprecated and will be removed in a future release.")
|
||||||
annotation class Version(
|
annotation class Version(
|
||||||
val version: String,
|
val version: String,
|
||||||
)
|
)
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
package app.revanced.patcher.data
|
package app.revanced.patcher.data
|
||||||
|
|
||||||
import brut.androlib.meta.MetaInfo
|
import brut.androlib.apk.ApkInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata about a package.
|
* Metadata about a package.
|
||||||
*/
|
*/
|
||||||
class PackageMetadata {
|
class PackageMetadata {
|
||||||
lateinit var packageName: String
|
lateinit var packageName: String
|
||||||
|
internal set
|
||||||
lateinit var packageVersion: String
|
lateinit var packageVersion: String
|
||||||
|
internal set
|
||||||
|
|
||||||
internal val metaInfo: MetaInfo = MetaInfo()
|
internal lateinit var apkInfo: ApkInfo
|
||||||
}
|
}
|
||||||
|
@@ -321,6 +321,11 @@ object InstructionExtensions {
|
|||||||
* @param T The type of instruction to return.
|
* @param T The type of instruction to return.
|
||||||
* @return The instruction.
|
* @return The instruction.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun <T> MutableMethod.getInstruction(index: Int): T = implementation!!.getInstruction<T>(index)
|
fun <T> MutableMethod.getInstruction(index: Int): T = implementation!!.getInstruction<T>(index)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instructions of a method.
|
||||||
|
* @return The instructions.
|
||||||
|
*/
|
||||||
|
fun MutableMethod.getInstructions(): MutableList<BuilderInstruction> = implementation!!.instructions
|
||||||
}
|
}
|
@@ -25,6 +25,7 @@ object PatchExtensions {
|
|||||||
/**
|
/**
|
||||||
* The version of a [Patch].
|
* The version of a [Patch].
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("This property is deprecated and will be removed in a future release.")
|
||||||
val Class<out Patch<Context>>.version
|
val Class<out Patch<Context>>.version
|
||||||
get() = findAnnotationRecursively(Version::class)?.version
|
get() = findAnnotationRecursively(Version::class)?.version
|
||||||
|
|
||||||
|
@@ -229,20 +229,4 @@ sealed class PatchOption<T>(
|
|||||||
) : ListOption<Int>(
|
) : ListOption<Int>(
|
||||||
key, default, options, title, description, required, validator
|
key, default, options, title, description, required, validator
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Path], backed by a [String].
|
|
||||||
* The validator passes a [String], if you need a [Path] you will have to convert it yourself.
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class PathOption(
|
|
||||||
key: String,
|
|
||||||
default: Path?,
|
|
||||||
title: String,
|
|
||||||
description: String,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (String?) -> Boolean = { true }
|
|
||||||
) : PatchOption<String>(
|
|
||||||
key, default?.pathString, title, description, required, validator
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +0,0 @@
|
|||||||
package app.revanced.patcher.util
|
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
internal object VersionReader {
|
|
||||||
@JvmStatic
|
|
||||||
private val props = Properties().apply {
|
|
||||||
load(
|
|
||||||
VersionReader::class.java.getResourceAsStream("/revanced-patcher/version.properties")
|
|
||||||
?: throw IllegalStateException("Could not load version.properties")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun read(): String {
|
|
||||||
return props.getProperty("version") ?: throw IllegalStateException("Version not found")
|
|
||||||
}
|
|
||||||
}
|
|
@@ -3,8 +3,6 @@ package app.revanced.patcher.patch
|
|||||||
import app.revanced.patcher.usage.bytecode.ExampleBytecodePatch
|
import app.revanced.patcher.usage.bytecode.ExampleBytecodePatch
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import kotlin.io.path.Path
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
import kotlin.test.assertNotEquals
|
import kotlin.test.assertNotEquals
|
||||||
|
|
||||||
internal class PatchOptionsTest {
|
internal class PatchOptionsTest {
|
||||||
@@ -35,10 +33,6 @@ internal class PatchOptionsTest {
|
|||||||
println(choice)
|
println(choice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is PatchOption.PathOption -> {
|
|
||||||
option.value = Path("test.txt").pathString
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val option = options.get<String>("key1")
|
val option = options.get<String>("key1")
|
||||||
|
@@ -5,8 +5,8 @@ import app.revanced.patcher.annotation.Name
|
|||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
@@ -29,7 +29,6 @@ import org.jf.dexlib2.immutable.reference.ImmutableFieldReference
|
|||||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
||||||
import org.jf.dexlib2.immutable.value.ImmutableFieldEncodedValue
|
import org.jf.dexlib2.immutable.value.ImmutableFieldEncodedValue
|
||||||
import org.jf.dexlib2.util.Preconditions
|
import org.jf.dexlib2.util.Preconditions
|
||||||
import kotlin.io.path.Path
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("example-bytecode-patch")
|
@Name("example-bytecode-patch")
|
||||||
@@ -193,10 +192,5 @@ class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) {
|
|||||||
"key5", null, "title", "description", true
|
"key5", null, "title", "description", true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
private var key6 by option(
|
|
||||||
PatchOption.PathOption(
|
|
||||||
"key6", Path("test.txt"), "title", "description", true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user