├── 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 |
--------------------------------------------------------------------------------