mirror of
https://github.com/revanced/revanced-patcher
synced 2025-04-22 16:39:49 +02:00
chore: merge branch dev
to main
(#203)
This commit is contained in:
commit
03cd97b49c
.gitattributes.releasercCHANGELOG.mdbuild.gradle.ktsgradle.properties
gradle/wrapper
gradlewgradlew.batsrc
main/kotlin/app/revanced/patcher
test/kotlin/app/revanced/patcher
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# https://help.github.com/articles/dealing-with-line-endings/
|
||||||
|
#
|
||||||
|
# Linux start script should use lf
|
||||||
|
/gradlew text eol=lf
|
||||||
|
|
||||||
|
# These are Windows script files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
@ -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",
|
||||||
|
25
CHANGELOG.md
25
CHANGELOG.md
@ -1,3 +1,28 @@
|
|||||||
|
# [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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.8.10"
|
kotlin("jvm") version "1.8.20"
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ 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.2")
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC")
|
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
|
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
org.gradle.parallel = true
|
||||||
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 11.0.4
|
version = 12.0.0-dev.2
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
40
gradlew
vendored
40
gradlew
vendored
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright © 2015-2021 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -32,10 +32,10 @@
|
|||||||
# Busybox and similar reduced shells will NOT work, because this script
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
# requires all of these POSIX shell features:
|
# requires all of these POSIX shell features:
|
||||||
# * functions;
|
# * functions;
|
||||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
# * compound commands having a testable exit status, especially «case»;
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
# * various built-in commands including «command», «set», and «ulimit».
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
#
|
#
|
||||||
# Important for patching:
|
# Important for patching:
|
||||||
#
|
#
|
||||||
@ -55,7 +55,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@ -80,13 +80,10 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -133,22 +130,29 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -193,6 +197,10 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
# Collect all arguments for the java command;
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
@ -205,6 +213,12 @@ set -- \
|
|||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
15
gradlew.bat
vendored
15
gradlew.bat
vendored
@ -14,7 +14,7 @@
|
|||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@ -25,7 +25,8 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user