├── META-INF └── com │ └── google │ └── android │ ├── updater-script │ └── update-binary ├── uninstall.sh ├── update.json ├── changelog.md ├── service.sh ├── README.md ├── customize.sh └── .github └── workflows └── update.yml /META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | PKGNAME=com.google.android.youtube 4 | 5 | # Unmount ReVanced 6 | stock_path=$( pm path $PKGNAME | grep base | sed 's/package://g' ) 7 | if [[ '$stock_path' ]] ; then umount -l $stock_path; fi -------------------------------------------------------------------------------- /update.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v20.23.39", 3 | "versionCode": 20251026, 4 | "zipUrl": "https://github.com/Zy0x/YouTube-Revanced/releases/download/v20.23.39-R3/Youtube.RVX.v20.23.39-R3.zip", 5 | "changelog": "https://raw.githubusercontent.com/Zy0x/YouTube-Revanced/main/changelog.md", 6 | "releaseType": "beta" 7 | } 8 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## v20.23.39-R3 (2025-10-26) 2 | 3 | ### Update 4 | - Patched with Revancify Tools v2.7.2 5 | - Based on [Anddea Patch v3.14.0](https://github.com/anddea/revanced-patches/releases/tag/v3.14.0) (thanks to Anddea) 6 | - Added mini detach YouTube (exclude auto update from PlayStore) ~ Root User 7 | 8 | ### Fix & Problem 9 | - If YouTube is having problems (module not working) try to use the action button in magisk (root user). 10 | 11 | `Note: Read README.MD first!` 12 | 13 | -------------------------------------------------------------------------------- /service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | MODPATH=${0%/*} 4 | base="$MODPATH/ori/*.apk" 5 | 6 | # Wait till device boot process completes 7 | while [ "$(getprop sys.boot_completed)" != "1" ]; do 8 | sleep 1 9 | done 10 | 11 | # Device online functions 12 | wait_until_login() 13 | { 14 | # whether in lock screen, tested on Android 7.1 & 10.0 15 | # in case of other magisk module remounting /data as RW 16 | while [ "$(dumpsys window policy | grep mInputRestricted=true)" != "" ]; do 17 | sleep 2 18 | done 19 | # we doesn't have the permission to rw "/sdcard" before the user unlocks the screen 20 | while [ ! -d "/sdcard/Android" ]; do 21 | sleep 2 22 | done 23 | } 24 | #wait_until_login 25 | 26 | # Detect Root 27 | if [ -e /data/local/tmp/magisk ]; then 28 | sleep 60 29 | else 30 | sleep 3 31 | fi 32 | 33 | # Mounting 34 | PKGNAME=com.google.android.youtube 35 | STOCKAPPVER=$(dumpsys package $PKGNAME | grep versionName | cut -d "=" -f 2 | sed -n '1p') 36 | RVAPPVER=$(basename /data/adb/modules/YouTube-RVX/app/YouTube* .apk | cut -d "-" -f 2) 37 | 38 | if [ "$STOCKAPPVER" = "$RVAPPVER" ] 39 | then 40 | STOCKAPK=$(pm path $PKGNAME | grep base | cut -d ":" -f2) 41 | RVAPK="/data/adb/modules/YouTube-RVX/app/YouTubeRevanced-$RVAPPVER.apk" 42 | chcon u:object_r:apk_data_file:s0 "$RVAPK" 43 | mount -o bind "$RVAPK" "$STOCKAPK" 44 | am force-stop "$PKGNAME" 45 | elif [ "$STOCKAPPVER" != "$RVAPPVER" ] 46 | then 47 | pm install -r -d $base 48 | STOCKAPK=$(pm path $PKGNAME | grep base | cut -d ":" -f2) 49 | RVAPK="/data/adb/modules/YouTube-RVX/app/YouTubeRevanced-$RVAPPVER.apk" 50 | chcon u:object_r:apk_data_file:s0 "$RVAPK" 51 | mount -o bind "$RVAPK" "$STOCKAPK" 52 | am force-stop "$PKGNAME" 53 | fi 54 | 55 | su -lp 2000 -c "cmd notification post -S bigtext -t 'YouTube RVX' tag '✅ YouTube RVX already to use...'" >/dev/null 2>&1 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

📺 YouTube ReVanced Patch

2 | 3 |

4 | A patched version of YouTube with ad-free experience and premium features using Revancify Tools 5 |

6 | 7 | ‎ 8 | 9 | ## ⚠️ Disclaimer 10 | > **I only patch for personal use. Please use at your own risk!** 11 | ‎ 12 | ## 📌 About 13 | This project provides a **YouTube ReVanced** patch that enables an ad-free experience and premium features **without a subscription**. 14 | Supports both **ROOT** and **NON-ROOT** versions! 🚀 15 | ‎ 16 | ## 🔧 Requirements 17 | 18 |

🎭 Root Users 🎭

19 | 20 | ✅ **Required:** 21 | > - **KSU / Magisk / Apatch** 22 | > - ❌ Do not use **TWRP** or other Custom Recovery! 23 | 24 | 🛠️ **Minimum Supported Versions:** 25 | > - **Magisk**: `24200` 26 | > - **KSU**: `11425` 27 | --- 28 |

🌈 Non-Root Users 🌈

29 | 30 | ✅ **Required:** 31 | > - **GmsCore (MicroG)** → Required for logging into a Google Account 32 | > - **YouTube ReVanced (Non-Root Version)** 33 | 34 | ‎ 35 | 36 | ## 📥 Download GmsCore/MicroG 37 | 38 | | Source | Download Link | 39 | |--------|--------------| 40 | | **MicroG-RE (Better UI)** | 🔗 [Download](http://github.com/wstxda/microg-re/releases/latest) | 41 | | **GmsCore from ReVanced** | 🔗 [Download](http://github.com/revanced/gmscore/releases/latest) | 42 | | **GmsCore from YT-Advanced** | 🔗 [Download](http://github.com/yt-advanced/gmscore/releases/latest) | 43 | 44 | > [!NOTE] 45 | > Recommended to use MicroG-RE! 46 | 47 | ‎ 48 | 49 | ## 🚀 Installation Guide 50 | 51 |

🎭 Root

52 | 53 | 1. **Download** the module (**Root Version**) 54 | 2. **Install** via **Magisk** / **KSU** / **Apatch** 55 | 3. **Export settings** (Optional) 56 | 4. Enjoy ✨ 57 | 58 | --- 59 | 60 |

🌈 Non-Root

61 | 62 | 1. **Install GmsCore (MicroG)** 63 | 2. **Download & Install YouTube ReVanced (Non-Root Version)** 64 | 3. **Export settings** (Optional) 65 | 4. Enjoy ✨ 66 | 67 | ‎ 68 | 69 | ## 📜 Sources & References 70 | - 🔧 [Revancify Tools](https://github.com/decipher3114/Revancify) 71 | - 📺 [YouTube ReVanced Patches](https://github.com/revanced) 72 | - 🛠️ [Anddea Patch](https://github.com/anddea/revanced-patches) 73 | -------------------------------------------------------------------------------- /customize.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # Checking for installation environment 4 | # Abort TWRP installation with error message when user tries to install this module in TWRP 5 | 6 | if [ $BOOTMODE = false ]; then 7 | ui_print "- Installing through TWRP Not supported" 8 | ui_print "- Intsall this module via Magisk Manager" 9 | abort "- Aborting installation !!" 10 | fi 11 | 12 | 13 | PKGNAME=com.google.android.youtube 14 | APPNAME="YouTube" 15 | 16 | # Unmount Old ReVanced 17 | stock_path=$( pm path $PKGNAME | grep base | sed 's/package://g' ) 18 | if [[ '$stock_path' ]] ; then umount -l $stock_path; fi 19 | 20 | # Install YoutubeRVX 21 | ui_print "Installing Stock Youtube..." 22 | SESSION=$(pm install-create -d | grep -oE '[0-9]+') 23 | APKS="$(ls $MODPATH/youtube)" 24 | for APK in $APKS; do 25 | pm install-write $SESSION $APK $MODPATH/youtube/$APK > /dev/null 26 | done 27 | pm install-commit $SESSION 28 | mv $MODPATH/youtube $MODPATH/ori/ 29 | 30 | if ! dumpsys package $PKGNAME | grep path > /dev/null 2>&1 31 | then 32 | ui_print "- $APPNAME app is not installed" 33 | ui_print "- Install $APPNAME from PlayStore" 34 | abort "- Aborting installation !!" 35 | fi 36 | 37 | STOCKAPPVER=$(dumpsys package $PKGNAME | grep versionName | cut -d= -f 2 | sed -n '1p') 38 | RVAPPVER=$(grep version= module.prop | sed 's/version=v//') 39 | 40 | if [ "$STOCKAPPVER" != "$RVAPPVER" ] 41 | then 42 | ui_print "- Installed $APPNAME version = $STOCKAPPVER" 43 | ui_print "- $APPNAME Revanced version = $RVAPPVER" 44 | ui_print "- App Version Mismatch !!" 45 | ui_print "- Get the module matching the version number." 46 | abort "- Aborting installation !!" 47 | fi 48 | ui_print "- Patching RVX to YouTube subscriptions" 49 | ui_print "- Unmounting Previous Mounts" 50 | 51 | grep $PKGNAME /proc/mounts | while read -r LINE 52 | do 53 | echo "$LINE" | grep "$PKGNAME" | cut -d " " -f 2 | sed "s/apk.*/apk/" | xargs -r umount -l 54 | done 55 | 56 | ui_print "- Moving Files and setting permissions" 57 | mkdir -p "$MODPATH/app" 58 | rm $MODPATH/app/"$APPNAME"* 59 | mv $MODPATH/*.apk $MODPATH/app/"$APPNAME"Revanced-"$RVAPPVER".apk 60 | STOCKAPK=$(pm path $PKGNAME | grep base | cut -d ":" -f2) 61 | RVAPK=$MODPATH/app/"$APPNAME"Revanced-"$RVAPPVER".apk 62 | chmod 644 "$RVAPK" 63 | chown system:system "$RVAPK" 64 | chcon u:object_r:apk_data_file:s0 "$RVAPK" 65 | mount -o bind "$RVAPK" "$STOCKAPK" 66 | am force-stop "$PKGNAME" 67 | 68 | # Detect Root 69 | ui_print "- Detect FullRoot/TempRoot..." 70 | if [ -e /data/local/tmp/magisk ]; then 71 | ui_print "Temproot Detected!" 72 | ui_print "Make configuration..." 73 | sed -i '/#wait_until_login/s/.*/wait_until_login/' $MODPATH/service.sh 74 | else 75 | ui_print "Full Root Detected!" 76 | fi 77 | 78 | rm -rf /data/adb/revanced 79 | rm -rf /data/adb/service.d/*revanced*.sh 80 | rm -rf /data/adb/service.d/detach*.sh 81 | rm -rf /data/adb/service.d/*youtube*.sh 82 | rm -rf /data/adb/post-fs-data.d/*revanced*.sh 83 | rm -rf /data/adb/post-fs-data.d/detach*.sh 84 | rm -rf /data/adb/post-fs-data.d/*youtube*.sh 85 | rm -rf /data/local/tmp/revanced* 86 | 87 | ui_print "- Install Successful !!" 88 | 89 | ui_print "- You can use YouTube ReVanced-Extended without reboot as well." 90 | ui_print "- Try to open YouTube (in 3s)..." 91 | sleep 3 92 | am start -n com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity 93 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Auto-update update.json and changelog.md on Release 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | release: 9 | types: [published, prereleased, edited] 10 | 11 | jobs: 12 | update-json-and-changelog: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout main branch 16 | uses: actions/checkout@v3 17 | with: 18 | ref: main 19 | fetch-depth: 0 20 | persist-credentials: true 21 | token: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - name: Install jq 24 | run: sudo apt-get update && sudo apt-get install -y jq 25 | 26 | - name: Generate release_data.json 27 | uses: actions/github-script@v6 28 | with: 29 | script: | 30 | if (context.eventName !== 'release' || !context.payload.release?.tag_name) { 31 | throw new Error('This workflow requires a release event with a valid tag_name.'); 32 | } 33 | const tag = context.payload.release.tag_name; 34 | const versionMatch = tag.match(/^v\d+\.\d+\.\d+(-R\d+)?$/); 35 | if (!versionMatch) { 36 | throw new Error(`Invalid tag format: ${tag}. Expected format: vX.Y.Z or vX.Y.Z-Rn`); 37 | } 38 | const version = tag.replace(/-R\d+$/, ''); // Untuk v20.16.40, tetap v20.16.40 karena tidak ada -R* 39 | const releaseType = tag.includes('-R') ? 'beta' : 'stable'; // Untuk v20.16.40, akan menjadi 'stable' 40 | const d = new Date(context.payload.release.published_at); 41 | const versionCode = `${d.getFullYear()}${String(d.getMonth()+1).padStart(2,'0')}${String(d.getDate()).padStart(2,'0')}`; 42 | const zip = (context.payload.release.assets.find(a => a.name.endsWith('.zip')) || {}).browser_download_url || ''; 43 | require('fs').writeFileSync('release_data.json', 44 | JSON.stringify({ 45 | version, 46 | versionCode, 47 | zipUrl: zip, 48 | releaseType, 49 | releaseName: context.payload.release.name || 'No Release Name', 50 | releaseBody: context.payload.release.body || 'No Release Notes', 51 | published_at: context.payload.release.published_at 52 | }, null, 2) 53 | ); 54 | 55 | - name: Show release_data.json 56 | run: cat release_data.json 57 | 58 | - name: Update update.json 59 | run: | 60 | VERSION=$(jq -r '.version' release_data.json) 61 | VERSION_CODE=$(jq -r '.versionCode' release_data.json) 62 | ZIP_URL=$(jq -r '.zipUrl' release_data.json) 63 | RELEASE_TYPE=$(jq -r '.releaseType' release_data.json) 64 | jq \ 65 | --arg version "$VERSION" \ 66 | --argjson versionCode "$VERSION_CODE" \ 67 | --arg zipUrl "$ZIP_URL" \ 68 | --arg releaseType "$RELEASE_TYPE" \ 69 | '.version = $version | 70 | .versionCode = $versionCode | 71 | .zipUrl = $zipUrl | 72 | .releaseType = $releaseType' \ 73 | update.json > update.json.tmp && mv update.json.tmp update.json 74 | 75 | - name: Update changelog.md 76 | run: | 77 | RELEASE_NAME=$(jq -r '.releaseName' release_data.json) 78 | RELEASE_BODY=$(jq -r '.releaseBody' release_data.json) 79 | RELEASE_DATE=$(date -d "$(jq -r '.published_at' release_data.json)" +"%Y-%m-%d" || date +"%Y-%m-%d") 80 | # Pastikan changelog.md dihapus sepenuhnya 81 | rm -f changelog.md || echo "No changelog.md to remove" 82 | # Tulis ulang changelog.md dengan catatan rilis terbaru 83 | echo -e "## $RELEASE_NAME ($RELEASE_DATE)\n\n$RELEASE_BODY\n" > changelog.md 84 | # Verifikasi bahwa file ditulis dengan benar 85 | if [ ! -f changelog.md ]; then 86 | echo "Error: changelog.md was not created!" 87 | exit 1 88 | fi 89 | 90 | - name: Verify changelog.md 91 | run: | 92 | echo "Content of changelog.md after update:" 93 | cat changelog.md 94 | # Verifikasi bahwa changelog.md hanya berisi satu bagian rilis 95 | SECTION_COUNT=$(grep -c "^## " changelog.md) 96 | echo "Number of release sections: $SECTION_COUNT" 97 | if [ "$SECTION_COUNT" -ne 1 ]; then 98 | echo "Error: changelog.md contains more than one release section!" 99 | exit 1 100 | fi 101 | 102 | - name: Commit and push 103 | run: | 104 | git config user.name "github-actions[bot]" 105 | git config user.email "github-actions[bot]@users.noreply.github.com" 106 | git add update.json changelog.md 107 | git commit -m "Auto-update update.json and changelog.md for $RELEASE_NAME" || echo "No changes to commit" 108 | git push 109 | -------------------------------------------------------------------------------- /META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.0+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20000 ] && require_new_magisk 31 | 32 | if [ $MAGISK_VER_CODE -ge 20400 ]; then 33 | # New Magisk have complete installation logic within util_functions.sh 34 | install_module 35 | exit 0 36 | fi 37 | 38 | ################# 39 | # Legacy Support 40 | ################# 41 | 42 | TMPDIR=/dev/tmp 43 | PERSISTDIR=/sbin/.magisk/mirror/persist 44 | 45 | is_legacy_script() { 46 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh 47 | return $? 48 | } 49 | 50 | print_modname() { 51 | local authlen len namelen pounds 52 | namelen=`echo -n $MODNAME | wc -c` 53 | authlen=$((`echo -n $MODAUTH | wc -c` + 3)) 54 | [ $namelen -gt $authlen ] && len=$namelen || len=$authlen 55 | len=$((len + 2)) 56 | pounds=$(printf "%${len}s" | tr ' ' '*') 57 | ui_print "$pounds" 58 | ui_print " $MODNAME " 59 | ui_print " by $MODAUTH " 60 | ui_print "$pounds" 61 | ui_print "*******************" 62 | ui_print " Powered by Magisk " 63 | ui_print "*******************" 64 | } 65 | 66 | # Override abort as old scripts have some issues 67 | abort() { 68 | ui_print "$1" 69 | $BOOTMODE || recovery_cleanup 70 | [ -n $MODPATH ] && rm -rf $MODPATH 71 | rm -rf $TMPDIR 72 | exit 1 73 | } 74 | 75 | rm -rf $TMPDIR 2>/dev/null 76 | mkdir -p $TMPDIR 77 | 78 | # Preperation for flashable zips 79 | setup_flashable 80 | 81 | # Mount partitions 82 | mount_partitions 83 | 84 | # Detect version and architecture 85 | api_level_arch_detect 86 | 87 | # Setup busybox and binaries 88 | $BOOTMODE && boot_actions || recovery_actions 89 | 90 | ############## 91 | # Preparation 92 | ############## 93 | 94 | # Extract prop file 95 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 96 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" 97 | 98 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules 99 | MODULEROOT=$NVBASE/$MODDIRNAME 100 | MODID=`grep_prop id $TMPDIR/module.prop` 101 | MODNAME=`grep_prop name $TMPDIR/module.prop` 102 | MODAUTH=`grep_prop author $TMPDIR/module.prop` 103 | MODPATH=$MODULEROOT/$MODID 104 | 105 | # Create mod paths 106 | rm -rf $MODPATH 2>/dev/null 107 | mkdir -p $MODPATH 108 | 109 | ########## 110 | # Install 111 | ########## 112 | 113 | if is_legacy_script; then 114 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 115 | 116 | # Load install script 117 | . $TMPDIR/install.sh 118 | 119 | # Callbacks 120 | print_modname 121 | on_install 122 | # Custom uninstaller 123 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh 124 | 125 | # Skip mount 126 | $SKIPMOUNT && touch $MODPATH/skip_mount 127 | 128 | # prop file 129 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop 130 | 131 | # Module info 132 | cp -af $TMPDIR/module.prop $MODPATH/module.prop 133 | 134 | # post-fs-data scripts 135 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh 136 | 137 | # service scripts 138 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh 139 | 140 | ui_print "- Setting permissions" 141 | set_permissions 142 | else 143 | print_modname 144 | 145 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 146 | 147 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then 148 | sleep 1 149 | ui_print "- Extracting module files" 150 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 151 | 152 | # Default permissions 153 | set_perm_recursive $MODPATH 0 0 0755 0644 154 | fi 155 | 156 | # Load customization script 157 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh 158 | fi 159 | 160 | # Handle replace folders 161 | for TARGET in $REPLACE; do 162 | ui_print "- Replace target: $TARGET" 163 | mktouch $MODPATH$TARGET/.replace 164 | done 165 | 166 | if $BOOTMODE; then 167 | # Update info for Magisk Manager 168 | mktouch $NVBASE/modules/$MODID/update 169 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop 170 | fi 171 | 172 | # Copy over custom sepolicy rules 173 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then 174 | ui_print "- Installing custom sepolicy patch" 175 | # Remove old recovery logs (which may be filling partition) to make room 176 | rm -f $PERSISTDIR/cache/recovery/* 177 | PERSISTMOD=$PERSISTDIR/magisk/$MODID 178 | mkdir -p $PERSISTMOD 179 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule || abort "! Insufficient partition size" 180 | fi 181 | 182 | # Remove stuffs that don't belong to modules 183 | rm -rf \ 184 | $MODPATH/system/placeholder $MODPATH/customize.sh \ 185 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null 186 | 187 | ############# 188 | # Finalizing 189 | ############# 190 | 191 | cd / 192 | $BOOTMODE || recovery_cleanup 193 | rm -rf $TMPDIR 194 | sleep 1 195 | ui_print "- Done" 196 | exit 0 197 | --------------------------------------------------------------------------------