mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-01 23:24:28 +02:00
fix(YouTube): Unable to access Autoplay next video
setting https://github.com/inotia00/ReVanced_Extended/issues/2664
This commit is contained in:
parent
1f499d9c51
commit
06f1750bd1
@ -77,5 +77,6 @@ enum class ResourceType(val value: String) {
|
|||||||
INTEGER("integer"),
|
INTEGER("integer"),
|
||||||
LAYOUT("layout"),
|
LAYOUT("layout"),
|
||||||
STRING("string"),
|
STRING("string"),
|
||||||
STYLE("style")
|
STYLE("style"),
|
||||||
|
XML("xml")
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import app.revanced.patcher.util.smali.ExternalLabel
|
|||||||
import app.revanced.patches.shared.spoof.appversion.baseSpoofAppVersionPatch
|
import app.revanced.patches.shared.spoof.appversion.baseSpoofAppVersionPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||||
|
import app.revanced.patches.youtube.utils.fix.cairo.cairoFragmentPatch
|
||||||
import app.revanced.patches.youtube.utils.indexOfGetDrawableInstruction
|
import app.revanced.patches.youtube.utils.indexOfGetDrawableInstruction
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.SPOOF_APP_VERSION
|
import app.revanced.patches.youtube.utils.patch.PatchList.SPOOF_APP_VERSION
|
||||||
import app.revanced.patches.youtube.utils.playservice.is_18_34_or_greater
|
import app.revanced.patches.youtube.utils.playservice.is_18_34_or_greater
|
||||||
@ -30,6 +31,10 @@ import com.android.tools.smali.dexlib2.Opcode
|
|||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No longer needed due to [cairoFragmentPatch].
|
||||||
|
* TODO: Test sufficiently and remove the patch.
|
||||||
|
*/
|
||||||
private val spoofAppVersionBytecodePatch = bytecodePatch(
|
private val spoofAppVersionBytecodePatch = bytecodePatch(
|
||||||
description = "spoofAppVersionBytecodePatch"
|
description = "spoofAppVersionBytecodePatch"
|
||||||
) {
|
) {
|
||||||
|
@ -0,0 +1,120 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.cairo
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_19_34_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.settingsFragmentCairo
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
|
import app.revanced.util.fingerprint.methodCall
|
||||||
|
import app.revanced.util.fingerprint.methodOrThrow
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.getWalkerMethod
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||||
|
import app.revanced.util.insertNode
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
private val cairoFragmentResourcePatch = resourcePatch(
|
||||||
|
description = "cairoFragmentResourcePatch"
|
||||||
|
) {
|
||||||
|
dependsOn(versionCheckPatch)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
/**
|
||||||
|
* Cairo fragment have been widely rolled out in YouTube 19.34+.
|
||||||
|
*/
|
||||||
|
if (!is_19_34_or_greater) {
|
||||||
|
return@execute
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Preference key for 'Playback' is '@string/playback_key'.
|
||||||
|
* Copy the node to add the Preference 'Playback' to the legacy settings fragment.
|
||||||
|
*/
|
||||||
|
document("res/xml/settings_fragment.xml").use { document ->
|
||||||
|
val tags = document.getElementsByTagName("Preference")
|
||||||
|
List(tags.length) { tags.item(it) as Element }
|
||||||
|
.find { it.getAttribute("android:key") == "@string/auto_play_key" }
|
||||||
|
?.let { node ->
|
||||||
|
node.insertNode("Preference", node) {
|
||||||
|
for (index in 0 until node.attributes.length) {
|
||||||
|
with (node.attributes.item(index)) {
|
||||||
|
setAttribute(nodeName, nodeValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAttribute("android:key", "@string/playback_key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What [cairoFragmentPatch] does:
|
||||||
|
* 1. Disable Cairo fragment settings.
|
||||||
|
* 2. Fix - When spoofing the app version to 19.20 or earlier, the app crashes or the Notifications tab is inaccessible.
|
||||||
|
* 3. Fix - Preference 'Playback' is hidden.
|
||||||
|
* 4. Some settings that were in Preference 'General' are moved to Preference 'Playback'.
|
||||||
|
*/
|
||||||
|
val cairoFragmentPatch = bytecodePatch(
|
||||||
|
description = "cairoFragmentPatch"
|
||||||
|
) {
|
||||||
|
dependsOn(
|
||||||
|
cairoFragmentResourcePatch,
|
||||||
|
sharedResourceIdPatch,
|
||||||
|
versionCheckPatch
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
/**
|
||||||
|
* Cairo fragment have been widely rolled out in YouTube 19.34+.
|
||||||
|
*/
|
||||||
|
if (!is_19_34_or_greater) {
|
||||||
|
return@execute
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instead of disabling all Cairo fragment configs,
|
||||||
|
// Just disable 'Load Cairo fragment xml' and 'Set style to Cairo preference'.
|
||||||
|
val cairoFragmentConfigMethodCall = cairoFragmentConfigFingerprint
|
||||||
|
.methodCall()
|
||||||
|
|
||||||
|
fun MutableMethod.disableCairoFragmentConfig() {
|
||||||
|
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>()?.toString() == cairoFragmentConfigMethodCall
|
||||||
|
} + 2
|
||||||
|
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||||
|
|
||||||
|
addInstruction(insertIndex, "const/4 v$insertRegister, 0x0")
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsFragmentSyntheticFingerprint.methodOrThrow().apply {
|
||||||
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(settingsFragmentCairo)
|
||||||
|
val fragmentStyleIndex = indexOfFirstInstructionOrThrow(literalIndex) {
|
||||||
|
val reference = getReference<MethodReference>()
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL_RANGE &&
|
||||||
|
reference?.returnType == "V" &&
|
||||||
|
reference.parameterTypes.firstOrNull() == "Ljava/lang/String;"
|
||||||
|
}
|
||||||
|
val fragmentStyleMethod = getWalkerMethod(fragmentStyleIndex)
|
||||||
|
|
||||||
|
arrayOf(
|
||||||
|
// Load cairo fragment xml.
|
||||||
|
this,
|
||||||
|
// Set style to cairo preference.
|
||||||
|
fragmentStyleMethod
|
||||||
|
).forEach { method ->
|
||||||
|
method.disableCairoFragmentConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -2,31 +2,42 @@ package app.revanced.patches.youtube.utils.fix.cairo
|
|||||||
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.youtube.misc.backgroundplayback.backgroundPlaybackPatch
|
import app.revanced.patches.youtube.misc.backgroundplayback.backgroundPlaybackPatch
|
||||||
import app.revanced.patches.youtube.utils.playservice.is_19_04_or_greater
|
|
||||||
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
|
||||||
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As of 2025, responses to [Account/Get Setting](https://youtubei.googleapis.com/youtubei/v1/account/get_setting)
|
||||||
|
* requests no longer include the Preference 'Autoplay' (YouTube 19.34+).
|
||||||
|
*
|
||||||
|
* In YouTube 19.34+, the Preference 'Playback' of the Cairo fragment replaces the Preference 'Autoplay'.
|
||||||
|
*
|
||||||
|
* Since RVX disables the Cairo fragment,
|
||||||
|
* users who have newly installed RVX 19.34+ will no longer be able to turn 'Autoplay next video' on or off in YouTube settings.
|
||||||
|
*
|
||||||
|
* As a workaround, [cairoSettingsPatch] has been replaced by [cairoFragmentPatch].
|
||||||
|
*/
|
||||||
|
@Deprecated("Use 'cairoFragmentPatch' instead.")
|
||||||
|
@Suppress("unused")
|
||||||
val cairoSettingsPatch = bytecodePatch(
|
val cairoSettingsPatch = bytecodePatch(
|
||||||
description = "cairoSettingsPatch"
|
description = "cairoSettingsPatch"
|
||||||
) {
|
) {
|
||||||
dependsOn(versionCheckPatch)
|
dependsOn(cairoFragmentPatch)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
if (!is_19_04_or_greater) {
|
if (true) {
|
||||||
return@execute
|
return@execute
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cairo Fragment was added since YouTube v19.04.38.
|
* Cairo fragment was added since YouTube v19.04.38.
|
||||||
* Disable this for the following reasons:
|
* Disable this for the following reasons:
|
||||||
* 1. [backgroundPlaybackPatch] does not activate the Minimized playback setting of Cairo Fragment.
|
* 1. [backgroundPlaybackPatch] does not activate the Minimized playback setting of Cairo Fragment.
|
||||||
* 2. Some patches implemented in RVX do not yet support Cairo Fragments.
|
* 2. Some patches implemented in RVX do not yet support Cairo fragments.
|
||||||
*
|
*
|
||||||
* See <a href="https://github.com/inotia00/ReVanced_Extended/issues/2099">ReVanced_Extended#2099</a>
|
* See <a href="https://github.com/inotia00/ReVanced_Extended/issues/2099">ReVanced_Extended#2099</a>
|
||||||
* or <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>
|
* or <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>
|
||||||
* for screenshots of the Cairo Fragment.
|
* for screenshots of the Cairo fragment.
|
||||||
*/
|
*/
|
||||||
carioFragmentConfigFingerprint.injectLiteralInstructionBooleanCall(
|
cairoFragmentConfigFingerprint.injectLiteralInstructionBooleanCall(
|
||||||
CAIRO_FRAGMENT_FEATURE_FLAG,
|
CAIRO_FRAGMENT_FEATURE_FLAG,
|
||||||
"0x0"
|
"0x0"
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,9 @@ package app.revanced.patches.youtube.utils.fix.cairo
|
|||||||
import app.revanced.util.fingerprint.legacyFingerprint
|
import app.revanced.util.fingerprint.legacyFingerprint
|
||||||
import app.revanced.util.or
|
import app.revanced.util.or
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.settingsFragment
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.settingsFragmentCairo
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Added in YouTube v19.04.38
|
* Added in YouTube v19.04.38
|
||||||
@ -12,9 +15,17 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
|||||||
*/
|
*/
|
||||||
internal const val CAIRO_FRAGMENT_FEATURE_FLAG = 45532100L
|
internal const val CAIRO_FRAGMENT_FEATURE_FLAG = 45532100L
|
||||||
|
|
||||||
internal val carioFragmentConfigFingerprint = legacyFingerprint(
|
internal val cairoFragmentConfigFingerprint = legacyFingerprint(
|
||||||
name = "carioFragmentConfigFingerprint",
|
name = "cairoFragmentConfigFingerprint",
|
||||||
returnType = "Z",
|
returnType = "Z",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
literals = listOf(CAIRO_FRAGMENT_FEATURE_FLAG),
|
literals = listOf(CAIRO_FRAGMENT_FEATURE_FLAG),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val settingsFragmentSyntheticFingerprint = legacyFingerprint(
|
||||||
|
name = "settingsFragmentSyntheticFingerprint",
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
opcodes = listOf(Opcode.INVOKE_VIRTUAL_RANGE),
|
||||||
|
literals = listOf(settingsFragment, settingsFragmentCairo),
|
||||||
|
)
|
||||||
|
@ -10,6 +10,7 @@ import app.revanced.patches.shared.mapping.ResourceType.INTEGER
|
|||||||
import app.revanced.patches.shared.mapping.ResourceType.LAYOUT
|
import app.revanced.patches.shared.mapping.ResourceType.LAYOUT
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.STRING
|
import app.revanced.patches.shared.mapping.ResourceType.STRING
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.STYLE
|
import app.revanced.patches.shared.mapping.ResourceType.STYLE
|
||||||
|
import app.revanced.patches.shared.mapping.ResourceType.XML
|
||||||
import app.revanced.patches.shared.mapping.get
|
import app.revanced.patches.shared.mapping.get
|
||||||
import app.revanced.patches.shared.mapping.resourceMappingPatch
|
import app.revanced.patches.shared.mapping.resourceMappingPatch
|
||||||
import app.revanced.patches.shared.mapping.resourceMappings
|
import app.revanced.patches.shared.mapping.resourceMappings
|
||||||
@ -190,6 +191,10 @@ var seekEasyHorizontalTouchOffsetToStartScrubbing = -1L
|
|||||||
private set
|
private set
|
||||||
var seekUndoEduOverlayStub = -1L
|
var seekUndoEduOverlayStub = -1L
|
||||||
private set
|
private set
|
||||||
|
var settingsFragment = -1L
|
||||||
|
private set
|
||||||
|
var settingsFragmentCairo = -1L
|
||||||
|
private set
|
||||||
var slidingDialogAnimation = -1L
|
var slidingDialogAnimation = -1L
|
||||||
private set
|
private set
|
||||||
var subtitleMenuSettingsFooterInfo = -1L
|
var subtitleMenuSettingsFooterInfo = -1L
|
||||||
@ -594,6 +599,14 @@ internal val sharedResourceIdPatch = resourcePatch(
|
|||||||
ID,
|
ID,
|
||||||
"seek_undo_edu_overlay_stub"
|
"seek_undo_edu_overlay_stub"
|
||||||
]
|
]
|
||||||
|
settingsFragment = resourceMappings[
|
||||||
|
XML,
|
||||||
|
"settings_fragment"
|
||||||
|
]
|
||||||
|
settingsFragmentCairo = resourceMappings[
|
||||||
|
XML,
|
||||||
|
"settings_fragment_cairo"
|
||||||
|
]
|
||||||
slidingDialogAnimation = resourceMappings[
|
slidingDialogAnimation = resourceMappings[
|
||||||
STYLE,
|
STYLE,
|
||||||
"SlidingDialogAnimation"
|
"SlidingDialogAnimation"
|
||||||
|
@ -14,7 +14,7 @@ import app.revanced.patches.shared.mainactivity.injectOnCreateMethodCall
|
|||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
|
||||||
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.youtube.utils.fix.cairo.cairoSettingsPatch
|
import app.revanced.patches.youtube.utils.fix.cairo.cairoFragmentPatch
|
||||||
import app.revanced.patches.youtube.utils.fix.playbackspeed.playbackSpeedWhilePlayingPatch
|
import app.revanced.patches.youtube.utils.fix.playbackspeed.playbackSpeedWhilePlayingPatch
|
||||||
import app.revanced.patches.youtube.utils.fix.splash.darkModeSplashScreenPatch
|
import app.revanced.patches.youtube.utils.fix.splash.darkModeSplashScreenPatch
|
||||||
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
||||||
@ -122,7 +122,7 @@ val settingsPatch = resourcePatch(
|
|||||||
|
|
||||||
dependsOn(
|
dependsOn(
|
||||||
settingsBytecodePatch,
|
settingsBytecodePatch,
|
||||||
cairoSettingsPatch,
|
cairoFragmentPatch,
|
||||||
darkModeSplashScreenPatch,
|
darkModeSplashScreenPatch,
|
||||||
playbackSpeedWhilePlayingPatch,
|
playbackSpeedWhilePlayingPatch,
|
||||||
)
|
)
|
||||||
|
@ -730,7 +730,7 @@ Note:
|
|||||||
<string name="revanced_hide_suggested_video_end_screen_summary_on">"Suggested video end screen is hidden when autoplay is turned off.
|
<string name="revanced_hide_suggested_video_end_screen_summary_on">"Suggested video end screen is hidden when autoplay is turned off.
|
||||||
|
|
||||||
Autoplay can be changed in YouTube settings:
|
Autoplay can be changed in YouTube settings:
|
||||||
Settings → Autoplay → Autoplay next video"</string>
|
Settings → Autoplay / Playback → Autoplay next video"</string>
|
||||||
<string name="revanced_hide_suggested_video_end_screen_summary_off">Suggested video end screen is shown.</string>
|
<string name="revanced_hide_suggested_video_end_screen_summary_off">Suggested video end screen is shown.</string>
|
||||||
<string name="revanced_skip_autoplay_countdown_title">Skip autoplay countdown</string>
|
<string name="revanced_skip_autoplay_countdown_title">Skip autoplay countdown</string>
|
||||||
<string name="revanced_skip_autoplay_countdown_summary_on">If autoplay is enabled, the next video will play immediately.</string>
|
<string name="revanced_skip_autoplay_countdown_summary_on">If autoplay is enabled, the next video will play immediately.</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user