mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-19 17:13:59 +00:00
Compare commits
9 Commits
v5.43.2-de
...
v5.44.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2aa9cac27 | ||
|
|
08baa19b4a | ||
|
|
7283b93cea | ||
|
|
754b71959a | ||
|
|
c64e29ec57 | ||
|
|
b2dd008aee | ||
|
|
de97562c5d | ||
|
|
6373829fd6 | ||
|
|
cfd244b408 |
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,3 +1,31 @@
|
|||||||
|
# [5.44.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.44.0-dev.2...v5.44.0-dev.3) (2025-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Duolingo - Enable debug menu:** Support latest app target ([#6163](https://github.com/ReVanced/revanced-patches/issues/6163)) ([08baa19](https://github.com/ReVanced/revanced-patches/commit/08baa19b4a62e62bd103d177c3f4454de199cf16))
|
||||||
|
|
||||||
|
# [5.44.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.44.0-dev.1...v5.44.0-dev.2) (2025-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Google Photos - Spoof features:** Add support for Pixel 10 devices ([#6161](https://github.com/ReVanced/revanced-patches/issues/6161)) ([754b719](https://github.com/ReVanced/revanced-patches/commit/754b71959a0155413eb33cf1bdc2c8976eaca634))
|
||||||
|
|
||||||
|
# [5.44.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.43.2-dev.3...v5.44.0-dev.1) (2025-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Samsung Radio:** Add `Disable device checks` patch ([#6145](https://github.com/ReVanced/revanced-patches/issues/6145)) ([de97562](https://github.com/ReVanced/revanced-patches/commit/de97562c5ddc8ec707761c1e04e74c4e18f9c158))
|
||||||
|
|
||||||
|
## [5.43.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.43.2-dev.2...v5.43.2-dev.3) (2025-10-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Hide layout components:** Hide new kind of community post ([#6146](https://github.com/ReVanced/revanced-patches/issues/6146)) ([cfd244b](https://github.com/ReVanced/revanced-patches/commit/cfd244b4088daacd2788ec38357ac521e4b296d5))
|
||||||
|
|
||||||
## [5.43.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.43.2-dev.1...v5.43.2-dev.2) (2025-10-17)
|
## [5.43.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.43.2-dev.1...v5.43.2-dev.2) (2025-10-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
extensions/samsung/radio/build.gradle.kts
Normal file
4
extensions/samsung/radio/build.gradle.kts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
dependencies {
|
||||||
|
compileOnly(project(":extensions:shared:library"))
|
||||||
|
compileOnly(project(":extensions:samsung:radio:stub"))
|
||||||
|
}
|
||||||
1
extensions/samsung/radio/src/main/AndroidManifest.xml
Normal file
1
extensions/samsung/radio/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package app.revanced.extension.samsung.radio.misc.fix.crash;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class FixCrashPatch {
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
* <p>
|
||||||
|
* Add the required permissions to the request list to avoid crashes on API 34+.
|
||||||
|
**/
|
||||||
|
public static final String[] fixPermissionRequestList(String[] perms) {
|
||||||
|
List<String> permsList = new ArrayList<>(Arrays.asList(perms));
|
||||||
|
if (permsList.contains("android.permission.POST_NOTIFICATIONS")) {
|
||||||
|
permsList.addAll(Arrays.asList("android.permission.RECORD_AUDIO", "android.permission.READ_PHONE_STATE", "android.permission.FOREGROUND_SERVICE_MICROPHONE"));
|
||||||
|
}
|
||||||
|
if (permsList.contains("android.permission.RECORD_AUDIO")) {
|
||||||
|
permsList.add("android.permission.FOREGROUND_SERVICE_MICROPHONE");
|
||||||
|
}
|
||||||
|
return permsList.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package app.revanced.extension.samsung.radio.restrictions.device;
|
||||||
|
|
||||||
|
import android.os.SemSystemProperties;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class BypassDeviceChecksPatch {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
* <p>
|
||||||
|
* Check if the device has the required hardware
|
||||||
|
**/
|
||||||
|
public static final boolean checkIfDeviceIsIncompatible(String[] deviceList) {
|
||||||
|
String currentDevice = SemSystemProperties.getSalesCode();
|
||||||
|
return Arrays.asList(deviceList).contains(currentDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
extensions/samsung/radio/stub/build.gradle.kts
Normal file
17
extensions/samsung/radio/stub/build.gradle.kts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
plugins {
|
||||||
|
alias(libs.plugins.android.library)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "app.revanced.extension"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 24
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package android.os;
|
||||||
|
|
||||||
|
public class SemSystemProperties {
|
||||||
|
public static String getSalesCode() {
|
||||||
|
throw new UnsupportedOperationException("Stub");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -87,7 +87,8 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
"post_shelf_slim.e",
|
"post_shelf_slim.e",
|
||||||
"videos_post_responsive_root.e",
|
"videos_post_responsive_root.e",
|
||||||
"text_post_responsive_root.e",
|
"text_post_responsive_root.e",
|
||||||
"poll_post_responsive_root.e"
|
"poll_post_responsive_root.e",
|
||||||
|
"shared_post_root.e"
|
||||||
);
|
);
|
||||||
|
|
||||||
final var subscribersCommunityGuidelines = new StringFilterGroup(
|
final var subscribersCommunityGuidelines = new StringFilterGroup(
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.patches.theme;
|
|
||||||
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.ColorFilter;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import app.revanced.extension.youtube.patches.HideSeekbarPatch;
|
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by {@link SeekbarColorPatch} change the color of the seekbar.
|
|
||||||
* and {@link HideSeekbarPatch} to hide the seekbar of the feed and watch history.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ProgressBarDrawable extends Drawable {
|
|
||||||
|
|
||||||
private final Paint paint = new Paint();
|
|
||||||
{
|
|
||||||
paint.setColor(SeekbarColorPatch.getSeekbarColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(@NonNull Canvas canvas) {
|
|
||||||
if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.drawRect(getBounds(), paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAlpha(int alpha) {
|
|
||||||
paint.setAlpha(alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
||||||
paint.setColorFilter(colorFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOpacity() {
|
|
||||||
return PixelFormat.TRANSLUCENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,7 @@ import static app.revanced.extension.shared.StringRef.str;
|
|||||||
import static app.revanced.extension.shared.Utils.clamp;
|
import static app.revanced.extension.shared.Utils.clamp;
|
||||||
import static app.revanced.extension.youtube.patches.theme.ThemePatch.SplashScreenAnimationStyle;
|
import static app.revanced.extension.youtube.patches.theme.ThemePatch.SplashScreenAnimationStyle;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
|
||||||
|
|
||||||
import com.airbnb.lottie.LottieAnimationView;
|
import com.airbnb.lottie.LottieAnimationView;
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
@@ -104,27 +101,6 @@ public final class SeekbarColorPatch {
|
|||||||
return customSeekbarColor;
|
return customSeekbarColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int colorChannelTo3Bits(int channel8Bits) {
|
|
||||||
final float channel3Bits = channel8Bits * 7 / 255f;
|
|
||||||
|
|
||||||
// If a color channel is near zero, then allow rounding up so values between
|
|
||||||
// 0x12 and 0x23 will show as 0x24. But always round down when the channel is
|
|
||||||
// near full saturation, otherwise rounding to nearest will cause all values
|
|
||||||
// between 0xEC and 0xFE to always show as full saturation (0xFF).
|
|
||||||
return channel3Bits < 6
|
|
||||||
? Math.round(channel3Bits)
|
|
||||||
: (int) channel3Bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
|
||||||
private static String get9BitStyleIdentifier(int color24Bit) {
|
|
||||||
final int r3 = colorChannelTo3Bits(Color.red(color24Bit));
|
|
||||||
final int g3 = colorChannelTo3Bits(Color.green(color24Bit));
|
|
||||||
final int b3 = colorChannelTo3Bits(Color.blue(color24Bit));
|
|
||||||
|
|
||||||
return String.format(Locale.US, "splash_seekbar_color_style_%d_%d_%d", r3, g3, b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point.
|
* injection point.
|
||||||
*/
|
*/
|
||||||
@@ -135,36 +111,6 @@ public final class SeekbarColorPatch {
|
|||||||
return original; // false = drawable style, true = lottie style.
|
return original; // false = drawable style, true = lottie style.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Injection point.
|
|
||||||
* Old drawable style launch screen.
|
|
||||||
*/
|
|
||||||
public static void setSplashAnimationDrawableTheme(AnimatedVectorDrawable vectorDrawable) {
|
|
||||||
// Alternatively a ColorMatrixColorFilter can be used to change the color of the drawable
|
|
||||||
// without using any styles, but a color filter cannot selectively change the seekbar
|
|
||||||
// while keeping the red YT logo untouched.
|
|
||||||
// Even if the seekbar color xml value is changed to a completely different color (such as green),
|
|
||||||
// a color filter still cannot be selectively applied when the drawable has more than 1 color.
|
|
||||||
try {
|
|
||||||
// Must set the color even if custom seekbar is off,
|
|
||||||
// because the xml color was replaced with a themed value.
|
|
||||||
String seekbarStyle = get9BitStyleIdentifier(customSeekbarColor);
|
|
||||||
Logger.printDebug(() -> "Using splash seekbar style: " + seekbarStyle);
|
|
||||||
|
|
||||||
final int styleIdentifierDefault = Utils.getResourceIdentifierOrThrow(
|
|
||||||
seekbarStyle,
|
|
||||||
"style"
|
|
||||||
);
|
|
||||||
|
|
||||||
Resources.Theme theme = Utils.getContext().getResources().newTheme();
|
|
||||||
theme.applyStyle(styleIdentifierDefault, true);
|
|
||||||
|
|
||||||
vectorDrawable.applyTheme(theme);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "setSplashAnimationDrawableTheme failure", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
* Modern Lottie style animation.
|
* Modern Lottie style animation.
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 5.43.2-dev.2
|
version = 5.44.0-dev.3
|
||||||
|
|||||||
@@ -764,6 +764,14 @@ public final class app/revanced/patches/reddit/misc/tracking/url/SanitizeUrlQuer
|
|||||||
public static final fun getSanitizeUrlQueryPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSanitizeUrlQueryPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/samsung/radio/misc/fix/crash/FixCrashPatchKt {
|
||||||
|
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/samsung/radio/restrictions/device/BypassDeviceChecksPatchKt {
|
||||||
|
public static final fun getBypassDeviceChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/serviceportalbund/detection/root/RootDetectionPatchKt {
|
public final class app/revanced/patches/serviceportalbund/detection/root/RootDetectionPatchKt {
|
||||||
public static final fun getRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,35 @@
|
|||||||
package app.revanced.patches.duolingo.debug
|
package app.revanced.patches.duolingo.debug
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import app.revanced.util.returnEarly
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val enableDebugMenuPatch = bytecodePatch(
|
val enableDebugMenuPatch = bytecodePatch(
|
||||||
name = "Enable debug menu",
|
name = "Enable debug menu",
|
||||||
use = false,
|
use = false
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.duolingo"("5.158.4"))
|
compatibleWith("com.duolingo")
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
initializeBuildConfigProviderFingerprint.method.apply {
|
// It seems all categories are allowed on release. Force this on anyway.
|
||||||
val insertIndex = initializeBuildConfigProviderFingerprint.patternMatch!!.startIndex
|
debugCategoryAllowOnReleaseBuildsFingerprint.method.returnEarly(true)
|
||||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
// Change build config debug build flag.
|
||||||
insertIndex,
|
buildConfigProviderConstructorFingerprint.match(
|
||||||
"const/4 v$register, 0x1",
|
buildConfigProviderToStringFingerprint.classDef
|
||||||
)
|
).let {
|
||||||
|
val index = it.patternMatch!!.startIndex
|
||||||
|
|
||||||
|
it.method.apply {
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
|
addInstruction(
|
||||||
|
index + 1,
|
||||||
|
"const/4 v$register, 0x1"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,16 +4,25 @@ import app.revanced.patcher.fingerprint
|
|||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
/**
|
internal val debugCategoryAllowOnReleaseBuildsFingerprint = fingerprint {
|
||||||
* The `BuildConfigProvider` class has two booleans:
|
returns("Z")
|
||||||
*
|
parameters()
|
||||||
* - `isChina`: (usually) compares "play" with "china"...except for builds in China
|
custom { method, classDef ->
|
||||||
* - `isDebug`: compares "release" with "debug" <-- we want to force this to `true`
|
method.name == "getAllowOnReleaseBuilds" && classDef.type == "Lcom/duolingo/debug/DebugCategory;"
|
||||||
*/
|
}
|
||||||
|
}
|
||||||
internal val initializeBuildConfigProviderFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
internal val buildConfigProviderConstructorFingerprint = fingerprint {
|
||||||
returns("V")
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
opcodes(Opcode.IPUT_BOOLEAN)
|
parameters()
|
||||||
strings("debug", "release", "china")
|
opcodes(Opcode.CONST_4)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val buildConfigProviderToStringFingerprint = fingerprint {
|
||||||
|
parameters()
|
||||||
|
returns("Ljava/lang/String;")
|
||||||
|
strings("BuildConfigProvider(") // Partial string match.
|
||||||
|
custom { method, _ ->
|
||||||
|
method.name == "toString"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ val spoofFeaturesPatch = bytecodePatch(
|
|||||||
"com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE",
|
"com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE",
|
||||||
"com.google.android.feature.PIXEL_2024_EXPERIENCE",
|
"com.google.android.feature.PIXEL_2024_EXPERIENCE",
|
||||||
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
|
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
|
||||||
|
"com.google.android.feature.PIXEL_2025_EXPERIENCE",
|
||||||
),
|
),
|
||||||
title = "Features to disable",
|
title = "Features to disable",
|
||||||
description = "Google Pixel exclusive features to disable." +
|
description = "Google Pixel exclusive features to disable." +
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.patches.samsung.radio.misc.fix.crash
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
|
import app.revanced.util.asSequence
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
internal val addManifestPermissionsPatch = resourcePatch {
|
||||||
|
|
||||||
|
val requiredPermissions = listOf(
|
||||||
|
"android.permission.READ_PHONE_STATE",
|
||||||
|
"android.permission.FOREGROUND_SERVICE_MICROPHONE",
|
||||||
|
"android.permission.RECORD_AUDIO",
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
document("AndroidManifest.xml").use { document ->
|
||||||
|
document.getElementsByTagName("manifest").item(0).let { manifestEl ->
|
||||||
|
|
||||||
|
// Check which permissions are missing
|
||||||
|
val existingPermissionNames = document.getElementsByTagName("uses-permission").asSequence()
|
||||||
|
.mapNotNull { (it as? Element)?.getAttribute("android:name") }.toSet()
|
||||||
|
val missingPermissions = requiredPermissions.filterNot { it in existingPermissionNames }
|
||||||
|
|
||||||
|
// Then add them
|
||||||
|
for (permission in missingPermissions) {
|
||||||
|
val element = document.createElement("uses-permission")
|
||||||
|
element.setAttribute("android:name", permission)
|
||||||
|
manifestEl.appendChild(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package app.revanced.patches.samsung.radio.misc.fix.crash
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||||
|
import app.revanced.patches.all.misc.transformation.fromMethodReference
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
internal val permissionRequestListFingerprint = fingerprint {
|
||||||
|
strings(
|
||||||
|
"android.permission.POST_NOTIFICATIONS",
|
||||||
|
"android.permission.READ_MEDIA_AUDIO",
|
||||||
|
"android.permission.RECORD_AUDIO"
|
||||||
|
)
|
||||||
|
custom { method, _ -> method.name == "<clinit>" }
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package app.revanced.patches.samsung.radio.misc.fix.crash
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.samsung.radio.restrictions.device.bypassDeviceChecksPatch
|
||||||
|
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
|
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/samsung/radio/misc/fix/crash/FixCrashPatch;"
|
||||||
|
|
||||||
|
val fixCrashPatch = bytecodePatch(
|
||||||
|
name = "Fix crashes", description = "Prevents the app from crashing because of missing system permissions."
|
||||||
|
) {
|
||||||
|
dependsOn(addManifestPermissionsPatch, bypassDeviceChecksPatch)
|
||||||
|
extendWith("extensions/samsung/radio.rve")
|
||||||
|
compatibleWith("com.sec.android.app.fm"("12.4.00.7", "12.3.00.13", "12.3.00.11"))
|
||||||
|
|
||||||
|
execute {
|
||||||
|
permissionRequestListFingerprint.method.apply {
|
||||||
|
findInstructionIndicesReversedOrThrow(Opcode.FILLED_NEW_ARRAY).forEach { filledNewArrayIndex ->
|
||||||
|
val moveResultIndex = indexOfFirstInstruction(filledNewArrayIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||||
|
if (moveResultIndex < 0) return@forEach // No move-result-object found after the filled-new-array
|
||||||
|
|
||||||
|
// Get the register where the array is saved
|
||||||
|
val arrayRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
|
||||||
|
|
||||||
|
// Invoke the method from the extension
|
||||||
|
addInstructions(
|
||||||
|
moveResultIndex + 1, """
|
||||||
|
invoke-static { v$arrayRegister }, ${EXTENSION_CLASS_DESCRIPTOR}->fixPermissionRequestList([Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
move-result-object v$arrayRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package app.revanced.patches.samsung.radio.restrictions.device
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.util.findFreeRegister
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||||
|
|
||||||
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
|
"Lapp/revanced/extension/samsung/radio/restrictions/device/BypassDeviceChecksPatch;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val bypassDeviceChecksPatch = bytecodePatch(
|
||||||
|
name = "Bypass device checks",
|
||||||
|
description = "Removes firmware and region blacklisting. " +
|
||||||
|
"This patch will still not allow the app to run on devices that do not have the required hardware.",
|
||||||
|
) {
|
||||||
|
extendWith("extensions/samsung/radio.rve")
|
||||||
|
compatibleWith("com.sec.android.app.fm"("12.4.00.7", "12.3.00.13", "12.3.00.11"))
|
||||||
|
|
||||||
|
execute {
|
||||||
|
// Return false = The device is not blacklisted
|
||||||
|
checkDeviceFingerprint.method.apply {
|
||||||
|
// Find the first string that start with "SM-", that's the list of incompatible devices
|
||||||
|
val firstStringIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
opcode == Opcode.CONST_STRING &&
|
||||||
|
getReference<StringReference>()?.string?.startsWith("SM-") == true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the following filled-new-array (or filled-new-array/range) instruction
|
||||||
|
val filledNewArrayIndex = indexOfFirstInstructionOrThrow(firstStringIndex + 1) {
|
||||||
|
opcode == Opcode.FILLED_NEW_ARRAY || opcode == Opcode.FILLED_NEW_ARRAY_RANGE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find an available register for our use
|
||||||
|
val resultRegister = findFreeRegister(filledNewArrayIndex + 1)
|
||||||
|
|
||||||
|
// Store the array there and invoke the method that we added to the class earlier
|
||||||
|
addInstructions(
|
||||||
|
filledNewArrayIndex + 1, """
|
||||||
|
move-result-object v$resultRegister
|
||||||
|
invoke-static { v$resultRegister }, $EXTENSION_CLASS_DESCRIPTOR->checkIfDeviceIsIncompatible([Ljava/lang/String;)Z
|
||||||
|
move-result v$resultRegister
|
||||||
|
return v$resultRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
// Remove the instructions before our strings
|
||||||
|
removeInstructions(0, firstStringIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package app.revanced.patches.samsung.radio.restrictions.device
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||||
|
import app.revanced.patches.all.misc.transformation.fromMethodReference
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
internal val checkDeviceFingerprint = fingerprint {
|
||||||
|
returns("Z")
|
||||||
|
custom { method, _ ->
|
||||||
|
/* Check for methods call to:
|
||||||
|
- Landroid/os/SemSystemProperties;->getSalesCode()Ljava/lang/String;
|
||||||
|
- Landroid/os/SemSystemProperties;->getCountryIso()Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
|
||||||
|
val impl = method.implementation ?: return@custom false
|
||||||
|
|
||||||
|
// Track which target methods we've found
|
||||||
|
val foundMethods = mutableSetOf<MethodCall>()
|
||||||
|
|
||||||
|
// Scan method instructions for calls to our target methods
|
||||||
|
for (instr in impl.instructions) {
|
||||||
|
val ref = instr.getReference<MethodReference>() ?: continue
|
||||||
|
val mc = fromMethodReference<MethodCall>(ref) ?: continue
|
||||||
|
|
||||||
|
if (mc == MethodCall.GetSalesCode || mc == MethodCall.GetCountryIso) {
|
||||||
|
foundMethods.add(mc)
|
||||||
|
|
||||||
|
// If we found both methods, return success
|
||||||
|
if (foundMethods.size == 2) {
|
||||||
|
return@custom true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only match if both methods are present
|
||||||
|
return@custom false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Information about method calls we want to replace
|
||||||
|
private enum class MethodCall(
|
||||||
|
override val definedClassName: String,
|
||||||
|
override val methodName: String,
|
||||||
|
override val methodParams: Array<String>,
|
||||||
|
override val returnType: String,
|
||||||
|
) : IMethodCall {
|
||||||
|
GetSalesCode(
|
||||||
|
"Landroid/os/SemSystemProperties;",
|
||||||
|
"getSalesCode",
|
||||||
|
arrayOf(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
GetCountryIso(
|
||||||
|
"Landroid/os/SemSystemProperties;",
|
||||||
|
"getCountryIso",
|
||||||
|
arrayOf(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
),
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package app.revanced.patches.youtube.layout.seekbar
|
package app.revanced.patches.youtube.layout.seekbar
|
||||||
|
|
||||||
import app.revanced.patcher.Fingerprint
|
import app.revanced.patcher.Fingerprint
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.patch.resourcePatch
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
@@ -17,17 +15,13 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
|||||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
|
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
|
import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
|
||||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||||
import app.revanced.util.copyXmlNode
|
|
||||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
|
||||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.inputStreamFromBundledResource
|
|
||||||
import app.revanced.util.insertLiteralOverride
|
import app.revanced.util.insertLiteralOverride
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@@ -38,9 +32,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
|||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
import org.w3c.dom.Element
|
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import kotlin.use
|
|
||||||
|
|
||||||
internal var reelTimeBarPlayedColorId = -1L
|
internal var reelTimeBarPlayedColorId = -1L
|
||||||
private set
|
private set
|
||||||
@@ -57,8 +48,6 @@ internal var ytTextSecondaryId = -1L
|
|||||||
internal var inlineTimeBarLiveSeekableRangeId = -1L
|
internal var inlineTimeBarLiveSeekableRangeId = -1L
|
||||||
private set
|
private set
|
||||||
|
|
||||||
internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color"
|
|
||||||
|
|
||||||
private val seekbarColorResourcePatch = resourcePatch {
|
private val seekbarColorResourcePatch = resourcePatch {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
@@ -92,21 +81,6 @@ private val seekbarColorResourcePatch = resourcePatch {
|
|||||||
"inline_time_bar_live_seekable_range"
|
"inline_time_bar_live_seekable_range"
|
||||||
]
|
]
|
||||||
|
|
||||||
// Modify the resume playback drawable and replace the progress bar with a custom drawable.
|
|
||||||
document("res/drawable/resume_playback_progressbar_drawable.xml").use { document ->
|
|
||||||
val layerList = document.getElementsByTagName("layer-list").item(0) as Element
|
|
||||||
val progressNode = layerList.getElementsByTagName("item").item(1) as Element
|
|
||||||
if (!progressNode.getAttributeNode("android:id").value.endsWith("progress")) {
|
|
||||||
throw PatchException("Could not find progress bar")
|
|
||||||
}
|
|
||||||
val scaleNode = progressNode.getElementsByTagName("scale").item(0) as Element
|
|
||||||
val shapeNode = scaleNode.getElementsByTagName("shape").item(0) as Element
|
|
||||||
val replacementNode = document.createElement(
|
|
||||||
"app.revanced.extension.youtube.patches.theme.ProgressBarDrawable",
|
|
||||||
)
|
|
||||||
scaleNode.replaceChild(replacementNode, shapeNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
ytYoutubeMagentaColorId = resourceMappings[
|
ytYoutubeMagentaColorId = resourceMappings[
|
||||||
"color",
|
"color",
|
||||||
"yt_youtube_magenta",
|
"yt_youtube_magenta",
|
||||||
@@ -115,99 +89,9 @@ private val seekbarColorResourcePatch = resourcePatch {
|
|||||||
"attr",
|
"attr",
|
||||||
"ytStaticBrandRed",
|
"ytStaticBrandRed",
|
||||||
]
|
]
|
||||||
|
|
||||||
// Add attribute and styles for splash screen custom color.
|
|
||||||
// Using a style is the only way to selectively change just the seekbar fill color.
|
|
||||||
//
|
|
||||||
// Because the style colors must be hard coded for all color possibilities,
|
|
||||||
// instead of allowing 24 bit color the style is restricted to 9-bit (3 bits per color channel)
|
|
||||||
// and the style color closest to the users custom color is used for the splash screen.
|
|
||||||
arrayOf(
|
|
||||||
inputStreamFromBundledResource("seekbar/values", "attrs.xml")!! to "res/values/attrs.xml",
|
|
||||||
ByteArrayInputStream(create9BitSeekbarColorStyles().toByteArray()) to "res/values/styles.xml"
|
|
||||||
).forEach { (source, destination) ->
|
|
||||||
"resources".copyXmlNode(
|
|
||||||
document(source),
|
|
||||||
document(destination),
|
|
||||||
).close()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSplashDrawablePathFillColor(xmlFileNames: Iterable<String>, vararg resourceNames: String) {
|
|
||||||
xmlFileNames.forEach { xmlFileName ->
|
|
||||||
document(xmlFileName).use { document ->
|
|
||||||
val childNodes = document.childNodes
|
|
||||||
|
|
||||||
resourceNames.forEach { elementId ->
|
|
||||||
val element = childNodes.findElementByAttributeValueOrThrow(
|
|
||||||
"android:name",
|
|
||||||
elementId
|
|
||||||
)
|
|
||||||
|
|
||||||
val attribute = "android:fillColor"
|
|
||||||
if (!element.hasAttribute(attribute)) {
|
|
||||||
throw PatchException("Could not find $attribute for $elementId")
|
|
||||||
}
|
|
||||||
|
|
||||||
element.setAttribute(attribute, "?attr/$splashSeekbarColorAttributeName")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setSplashDrawablePathFillColor(
|
|
||||||
listOf(
|
|
||||||
"res/drawable/\$startup_animation_light__0.xml",
|
|
||||||
"res/drawable/\$startup_animation_dark__0.xml"
|
|
||||||
),
|
|
||||||
"_R_G_L_10_G_D_0_P_0"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!is_19_46_or_greater) {
|
|
||||||
// Resources removed in 19.46+
|
|
||||||
setSplashDrawablePathFillColor(
|
|
||||||
listOf(
|
|
||||||
"res/drawable/\$buenos_aires_animation_light__0.xml",
|
|
||||||
"res/drawable/\$buenos_aires_animation_dark__0.xml"
|
|
||||||
),
|
|
||||||
"_R_G_L_8_G_D_0_P_0"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a style xml with all combinations of 9-bit colors.
|
|
||||||
*/
|
|
||||||
private fun create9BitSeekbarColorStyles(): String = StringBuilder().apply {
|
|
||||||
append("<?xml version=\"1.0\" encoding=\"utf-8\"?>")
|
|
||||||
append("<resources>\n")
|
|
||||||
|
|
||||||
for (red in 0..7) {
|
|
||||||
for (green in 0..7) {
|
|
||||||
for (blue in 0..7) {
|
|
||||||
val name = "${red}_${green}_${blue}"
|
|
||||||
|
|
||||||
fun roundTo3BitHex(channel8Bits: Int) =
|
|
||||||
(channel8Bits * 255 / 7).toString(16).padStart(2, '0')
|
|
||||||
val r = roundTo3BitHex(red)
|
|
||||||
val g = roundTo3BitHex(green)
|
|
||||||
val b = roundTo3BitHex(blue)
|
|
||||||
val color = "#ff$r$g$b"
|
|
||||||
|
|
||||||
append(
|
|
||||||
"""
|
|
||||||
<style name="splash_seekbar_color_style_$name">
|
|
||||||
<item name="$splashSeekbarColorAttributeName">$color</item>
|
|
||||||
</style>
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
append("</resources>")
|
|
||||||
}.toString()
|
|
||||||
|
|
||||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/theme/SeekbarColorPatch;"
|
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/theme/SeekbarColorPatch;"
|
||||||
|
|
||||||
val seekbarColorPatch = bytecodePatch(
|
val seekbarColorPatch = bytecodePatch(
|
||||||
@@ -344,21 +228,6 @@ val seekbarColorPatch = bytecodePatch(
|
|||||||
|
|
||||||
// Hook the splash animation to set the a seekbar color.
|
// Hook the splash animation to set the a seekbar color.
|
||||||
mainActivityOnCreateFingerprint.method.apply {
|
mainActivityOnCreateFingerprint.method.apply {
|
||||||
val drawableIndex = indexOfFirstInstructionOrThrow {
|
|
||||||
val reference = getReference<MethodReference>()
|
|
||||||
reference?.definingClass == "Landroid/widget/ImageView;"
|
|
||||||
&& reference.name == "getDrawable"
|
|
||||||
}
|
|
||||||
val checkCastIndex = indexOfFirstInstructionOrThrow(drawableIndex, Opcode.CHECK_CAST)
|
|
||||||
val drawableRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
checkCastIndex + 1,
|
|
||||||
"invoke-static { v$drawableRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
|
||||||
"setSplashAnimationDrawableTheme(Landroid/graphics/drawable/AnimatedVectorDrawable;)V"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Replace the Lottie animation view setAnimation(int) call.
|
|
||||||
val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name
|
val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name
|
||||||
|
|
||||||
findInstructionIndicesReversedOrThrow {
|
findInstructionIndicesReversedOrThrow {
|
||||||
@@ -371,13 +240,11 @@ val seekbarColorPatch = bytecodePatch(
|
|||||||
replaceInstruction(
|
replaceInstruction(
|
||||||
index,
|
index,
|
||||||
"invoke-static { v${instruction.registerC}, v${instruction.registerD} }, " +
|
"invoke-static { v${instruction.registerC}, v${instruction.registerD} }, " +
|
||||||
"$EXTENSION_CLASS_DESCRIPTOR->setSplashAnimationLottie" +
|
"$EXTENSION_CLASS_DESCRIPTOR->setSplashAnimationLottie(Lcom/airbnb/lottie/LottieAnimationView;I)V"
|
||||||
"(Lcom/airbnb/lottie/LottieAnimationView;I)V"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add non obfuscated method aliases for `setAnimation(int)`
|
// Add non obfuscated method aliases for `setAnimation(int)`
|
||||||
// and `setAnimation(InputStream, String)` so extension code can call them.
|
// and `setAnimation(InputStream, String)` so extension code can call them.
|
||||||
lottieAnimationViewSetAnimationIntFingerprint.classDef.methods.apply {
|
lottieAnimationViewSetAnimationIntFingerprint.classDef.methods.apply {
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<attr format="reference|color" name="splash_custom_seekbar_color"/>
|
|
||||||
</resources>
|
|
||||||
Reference in New Issue
Block a user