You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-11-05 20:32:28 +01:00
Compare commits
9 Commits
v21.0.0-de
...
feat/kmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2e0f57579 | ||
|
|
242e244b18 | ||
|
|
f338ebff6c | ||
|
|
00e5950cf2 | ||
|
|
5a0e3841ff | ||
|
|
cfb459b832 | ||
|
|
2096306107 | ||
|
|
92eaba8081 | ||
|
|
7be0cd8548 |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,22 +1,3 @@
|
|||||||
# [21.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v20.0.2...v21.0.0-dev.1) (2024-10-27)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* Merge extension only when patch executes ([#315](https://github.com/ReVanced/revanced-patcher/issues/315)) ([aa472eb](https://github.com/ReVanced/revanced-patcher/commit/aa472eb9857145b53b49f843406a9764fbb7e5ce))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* Improve Fingerprint API ([#316](https://github.com/ReVanced/revanced-patcher/issues/316)) ([0abf1c6](https://github.com/ReVanced/revanced-patcher/commit/0abf1c6c0279708fdef5cb66b141d07d17682693))
|
|
||||||
* Improve various APIs ([#317](https://github.com/ReVanced/revanced-patcher/issues/317)) ([b824978](https://github.com/ReVanced/revanced-patcher/commit/b8249789df8b90129f7b7ad0e523a8d0ceaab848))
|
|
||||||
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
* Various APIs have been changed.
|
|
||||||
* Many APIs have been changed.
|
|
||||||
|
|
||||||
## [20.0.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1...v20.0.2) (2024-10-17)
|
## [20.0.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1...v20.0.2) (2024-10-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ val patcherResult = Patcher(PatcherConfig(apkFile = File("some.apk"))).use { pat
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
patcher().collect { patchResult ->
|
patcher().collect { patchResult ->
|
||||||
if (patchResult.exception != null)
|
if (patchResult.exception != null)
|
||||||
logger.info { "\"${patchResult.patch}\" failed:\n${patchResult.exception}" }
|
logger.info("\"${patchResult.patch}\" failed:\n${patchResult.exception}")
|
||||||
else
|
else
|
||||||
logger.info { "\"${patchResult.patch}\" succeeded" }
|
logger.info("\"${patchResult.patch}\" succeeded")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,11 +233,6 @@ The `classDef` and `method` properties can be used to make changes to the class
|
|||||||
They are lazy properties, so they are only computed
|
They are lazy properties, so they are only computed
|
||||||
and will effectively replace the original method or class definition when accessed.
|
and will effectively replace the original method or class definition when accessed.
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> If only read-only access to the class or method is needed,
|
|
||||||
> the `originalClassDef` and `originalMethod` properties can be used,
|
|
||||||
> to avoid making a mutable copy of the class or method.
|
|
||||||
|
|
||||||
## 🏹 Manually matching fingerprints
|
## 🏹 Manually matching fingerprints
|
||||||
|
|
||||||
By default, a fingerprint is matched automatically against all classes when the `match` property is accessed.
|
By default, a fingerprint is matched automatically against all classes when the `match` property is accessed.
|
||||||
@@ -266,15 +261,6 @@ you can match the fingerprint on the list of classes:
|
|||||||
val match = showAdsFingerprint.match(context, adsLoaderClass) ?: throw PatchException("No match found")
|
val match = showAdsFingerprint.match(context, adsLoaderClass) ?: throw PatchException("No match found")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Another common usecase is to use a fingerprint to reduce the search space of a method to a single class.
|
|
||||||
|
|
||||||
```kt
|
|
||||||
execute {
|
|
||||||
// Match showAdsFingerprint in the class of the ads loader found by adsLoaderClassFingerprint.
|
|
||||||
val match by showAdsFingerprint.match(adsLoaderClassFingerprint.match!!.classDef)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- Match a **single method**, to extract certain information about it
|
- Match a **single method**, to extract certain information about it
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
version = 21.0.0-dev.1
|
version = 20.0.2
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
bytecodePatch.extensionInputStream?.get()?.use { extensionStream ->
|
bytecodePatch.extensionInputStream?.get()?.use { extensionStream ->
|
||||||
RawDexIO.readRawDexFile(extensionStream, 0, null).classes.forEach { classDef ->
|
RawDexIO.readRawDexFile(extensionStream, 0, null).classes.forEach { classDef ->
|
||||||
val existingClass = lookupMaps.classesByType[classDef.type] ?: run {
|
val existingClass = lookupMaps.classesByType[classDef.type] ?: run {
|
||||||
logger.fine { "Adding class \"$classDef\"" }
|
logger.fine("Adding class \"$classDef\"")
|
||||||
|
|
||||||
classes += classDef
|
classes += classDef
|
||||||
lookupMaps.classesByType[classDef.type] = classDef
|
lookupMaps.classesByType[classDef.type] = classDef
|
||||||
@@ -106,7 +106,7 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.fine { "Class \"$classDef\" exists already. Adding missing methods and fields." }
|
logger.fine("Class \"$classDef\" exists already. Adding missing methods and fields.")
|
||||||
|
|
||||||
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
|
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
|
||||||
// If the class was merged, replace the original class with the merged class.
|
// If the class was merged, replace the original class with the merged class.
|
||||||
@@ -179,7 +179,7 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
|
|||||||
override fun getOpcodes() = this@BytecodePatchContext.opcodes
|
override fun getOpcodes() = this@BytecodePatchContext.opcodes
|
||||||
},
|
},
|
||||||
DexIO.DEFAULT_MAX_DEX_POOL_SIZE,
|
DexIO.DEFAULT_MAX_DEX_POOL_SIZE,
|
||||||
) { _, entryName, _ -> logger.info { "Compiled $entryName" } }
|
) { _, entryName, _ -> logger.info("Compiled $entryName") }
|
||||||
}.listFiles(FileFilter { it.isFile })!!.map {
|
}.listFiles(FileFilter { it.isFile })!!.map {
|
||||||
PatcherResult.PatchedDexFile(it.name, it.inputStream())
|
PatcherResult.PatchedDexFile(it.name, it.inputStream())
|
||||||
}.toSet()
|
}.toSet()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ internal object ClassMerger {
|
|||||||
|
|
||||||
if (missingMethods.isEmpty()) return this
|
if (missingMethods.isEmpty()) return this
|
||||||
|
|
||||||
logger.fine { "Found ${missingMethods.size} missing methods" }
|
logger.fine("Found ${missingMethods.size} missing methods")
|
||||||
|
|
||||||
return asMutableClass().apply {
|
return asMutableClass().apply {
|
||||||
methods.addAll(missingMethods.map { it.toMutable() })
|
methods.addAll(missingMethods.map { it.toMutable() })
|
||||||
@@ -80,7 +80,7 @@ internal object ClassMerger {
|
|||||||
|
|
||||||
if (missingFields.isEmpty()) return this
|
if (missingFields.isEmpty()) return this
|
||||||
|
|
||||||
logger.fine { "Found ${missingFields.size} missing fields" }
|
logger.fine("Found ${missingFields.size} missing fields")
|
||||||
|
|
||||||
return asMutableClass().apply {
|
return asMutableClass().apply {
|
||||||
fields.addAll(missingFields.map { it.toMutable() })
|
fields.addAll(missingFields.map { it.toMutable() })
|
||||||
@@ -100,7 +100,7 @@ internal object ClassMerger {
|
|||||||
context.traverseClassHierarchy(this) {
|
context.traverseClassHierarchy(this) {
|
||||||
if (accessFlags.isPublic()) return@traverseClassHierarchy
|
if (accessFlags.isPublic()) return@traverseClassHierarchy
|
||||||
|
|
||||||
logger.fine { "Publicizing ${this.type}" }
|
logger.fine("Publicizing ${this.type}")
|
||||||
|
|
||||||
accessFlags = accessFlags.toPublic()
|
accessFlags = accessFlags.toPublic()
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ internal object ClassMerger {
|
|||||||
|
|
||||||
if (brokenFields.isEmpty()) return this
|
if (brokenFields.isEmpty()) return this
|
||||||
|
|
||||||
logger.fine { "Found ${brokenFields.size} broken fields" }
|
logger.fine("Found ${brokenFields.size} broken fields")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a field public.
|
* Make a field public.
|
||||||
@@ -153,7 +153,7 @@ internal object ClassMerger {
|
|||||||
|
|
||||||
if (brokenMethods.isEmpty()) return this
|
if (brokenMethods.isEmpty()) return this
|
||||||
|
|
||||||
logger.fine { "Found ${brokenMethods.size} methods" }
|
logger.fine("Found ${brokenMethods.size} methods")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a method public.
|
* Make a method public.
|
||||||
|
|||||||
Reference in New Issue
Block a user