ReDroid (Remote anDroid) 是自架「雲手機」的方案,透過docker在電腦上跑Android系統容器,再利用Scrcpy的鏡射螢幕功能連線到Android桌面。

ReDroid也是在電腦上用開源軟體跑Android APP的解決方案。因為別說雲手機了,很多Android手遊模擬器都是閉源軟體哪。相較之下,ReDroid除了ARM轉譯器以外都是開源的。更棒的是ReDroid支援GPU加速+ARM轉x86的轉譯器,這樣就可以玩大多數手機3D遊戲了。
對Linux用戶來說,這更是除了Waydroid以外,在Linux電腦高效率跑Android APP的方法。
本文將討論如何在x86架構的Linux電腦,用ReDroid玩ARM架構的手機遊戲。我們會在ReDroid映像檔加入ARM轉譯器+Google服務框架,以達成最佳使用體驗。
P.S. Windows和MacOS也可以跑Docker。
ReDroid在Github上有各大Linux發行版的安裝說明。
由於我是Arch Linux,因此Linux核心要先換成linux-zen以支援binderfs。
接著安裝docker和docker-compose,用於執行容器:
1
2
| sudo pacman -S docker docker-compose
sudo systemctl enable --now docker
|
- 安裝ADB和Scrcpy,連線到Android桌面:
1
2
| sudo pacman -S android-tools
sudo pacman -S scrcpy
|
- 下載用於傳輸音效的sndcpy,將其解壓縮。
*想要Scrcpy和Sndcpy二者整合和按鍵映射的,可以試試看QtScrcpy。
大部分電腦是x86架構,只能執行x86版的Android APP,然而很多手機遊戲只有ARM版。所以跑ReDroid前建議先下載ARM轉譯器,不然能執行的APP會少很多。
ReDroid支援用QEMU或libndk轉譯,本文採用後者。libndk是Google開發的ARM → x86轉譯器,含在Android Studio的模擬器裡。注意libndk是專有軟體,使用上處於灰色地帶。
- 你可以用Droid-NDK-Extractor指令稿從Android 11模擬器映像檔抽取libndk:
1
2
3
4
5
6
7
| sudo pacman -S sleuthkit p7zip binwalk git
cd ~
git clone https://github.com/sickcodes/Droid-NDK-Extractor.git
cd Droid-NDK-Extractor
chmod +x android-extract-ndk.sh
./android-extract-ndk.sh x86_64
|
之後會在工作目錄的/working/extracted/
下找到native-bridge.tar
,大約30MB。
切換到native-bridge.tar
所在的目錄,修正權限後重新壓縮檔案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| cd ~/Droid-NDK-Extractor/working/extracted/
mkdir native-bridge
cd native-bridge
sudo tar -xpf ../native-bridge.tar
sudo chmod 0644 system/etc/init/ndk_translation_arm64.rc
sudo chmod 0755 system/bin/arm
sudo chmod 0755 system/bin/arm64
sudo chmod 0755 system/lib/arm
sudo chmod 0755 system/lib64/arm64
sudo chmod 0644 system/etc/binfmt_misc/*
sudo tar -cpf native-bridge.tar system
mv native-bridge.tar ..
cd ..
rm -r native-bridge
|
- 至此ARM轉譯器
native-bridge.tar
準備完成。
ReDroid目前提供Android 8 ~ Android 13的映像檔。由於要使用libndk的關係,故以Android 11的映像檔為基礎下去建置。
新增一個空白目錄android
,將剛剛製作的native-bridge.tar
放到此目錄。
在android
目錄新增一個名為dockerfile
的檔案,填入以下內容:
1
2
3
| FROM redroid/redroid:11.0.0-amd64
ADD native-bridge.tar /
|
- 在
android
目錄開啟終端機,開始建置含有libndk的ReDroid映像檔:
1
| sudo docker build . -t redroid-11-libndk
|
如果要用ReDroid玩手機遊戲,建議電腦至少要有8GB以上RAM,因為有時ARM在轉譯成x86指令時會佔用大量RAM。
- 部署ReDroid。沒加
--rm
是因為後續還要對系統做修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
| sudo docker run -itd --privileged \
-v ~/data11-nb:/data \
-p 5555:5555 \
redroid-11-libndk \
androidboot.redroid_gpu_mode=host \
ro.product.cpu.abilist=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi \
ro.product.cpu.abilist64=x86_64,arm64-v8a \
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi \
ro.dalvik.vm.isa.arm=x86 \
ro.dalvik.vm.isa.arm64=x86_64 \
ro.enable.native.bridge.exec=1 \
ro.dalvik.vm.native.bridge=libndk_translation.so \
ro.ndk_translation.version=0.2.2
|
- 用ADB連線至本機的ReDroid:
1
2
3
4
5
| adb connect localhost:5555
# 如果連不上,用以下指令看一下容器內部發生什麼問題
sudo docker logs <容器ID>
sudo docker exec <容器ID> logcat
|
- 執行Scrcpy,連線到Android桌面:
1
| scrcpy -s localhost:5555
|
這樣就會看到Android的桌面了。

至於聲音的話,切換到sndcpy
所在的目錄,執行sndcpy
,開始串流音效:
1
| ./sndcpy localhost:5555
|
作者說Google服務框架是專有軟體無法內建,那麼就得自行安裝了。第一個方法是重新編譯映像檔,第二個是手動安裝OpenGApps。
不推薦第一個方法,耗時而且作者提供的GApps編譯教學又有其他APP偵測不到的問題。
這裡採用第二個方法:手動安裝,過程參考自:Install GApps Manually - Google Groups
到OpenGapps下載x86_64架構的Android 11 GApps,選擇最小化的pico版。
解壓縮,會看到以下目錄
1
2
3
4
5
| open_gapps-x86_64-11.0-pico-20220503
├── Core
├── GApps
├── META-INF
├── Optional
|
在解壓縮的目錄新增system
目錄。
接著,將Core
和GApps
目錄裡面的.lz
檔案都解壓縮,並將裡面的APK目錄按照對應的安裝目錄放到system
目錄。例如GApps/googletts-x86_64/nodpi/app/
下的GoogleTTS
目錄要放到/system/app
。
放好之後,system
下的目錄結構應該會長這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| system
├── app
│ ├── GoogleCalendarSyncAdapter
│ │ └── GoogleCalendarSyncAdapter.apk
│ ├── GoogleContactsSyncAdapter
│ │ └── GoogleContactsSyncAdapter.apk
│ ├── GoogleExtShared
│ │ └── GoogleExtShared.apk
│ └── GoogleTTS
│ └── GoogleTTS.apk
├── etc
│ ├── default-permissions
│ │ ├── default-permissions.xml
│ │ └── opengapps-permissions-q.xml
│ ├── permissions
│ │ ├── com.google.android.dialer.support.xml
│ │ ├── com.google.android.maps.xml
│ │ ├── com.google.android.media.effects.xml
│ │ ├── privapp-permissions-google.xml
│ │ └── split-permissions-google.xml
│ ├── preferred-apps
│ │ └── google.xml
│ └── sysconfig
│ ├── dialer_experience.xml
│ ├── google_build.xml
│ ├── google_exclusives_enable.xml
│ ├── google-hiddenapi-package-whitelist.xml
│ └── google.xml
├── framework
│ ├── com.google.android.dialer.support.jar
│ ├── com.google.android.maps.jar
│ └── com.google.android.media.effects.jar
├── priv-app
│ ├── AndroidAutoPrebuiltStub
│ │ └── AndroidAutoPrebuiltStub.apk
│ ├── AndroidMigratePrebuilt
│ │ └── AndroidMigratePrebuilt.apk
│ ├── CarrierSetup
│ │ └── CarrierSetup.apk
│ ├── ConfigUpdater
│ │ └── ConfigUpdater.apk
│ ├── GoogleBackupTransport
│ │ └── GoogleBackupTransport.apk
│ ├── GoogleExtServices
│ │ └── GoogleExtServices.apk
│ ├── GoogleFeedback
│ │ └── GoogleFeedback.apk
│ ├── GoogleOneTimeInitializer
│ │ └── GoogleOneTimeInitializer.apk
│ ├── GooglePackageInstaller
│ │ └── GooglePackageInstaller.apk
│ ├── GooglePartnerSetup
│ │ └── GooglePartnerSetup.apk
│ ├── GoogleRestore
│ │ └── GoogleRestore.apk
│ ├── GoogleServicesFramework
│ │ └── GoogleServicesFramework.apk
│ ├── Phonesky
│ │ └── Phonesky.apk
│ ├── PrebuiltGmsCore
│ │ └── PrebuiltGmsCore.apk
│ └── SetupWizard
│ └── SetupWizard.apk
└── product
└── overlay
└── PlayStoreOverlay.apk
|
- 執行以下指令取得root權限:
1
2
3
4
| adb connect localhost:5555
adb -s localhost:5555 root
adb -s localhost:5555 remount
adb -s localhost:5555 shell "rm -rf system/priv-app/PackageInstaller"
|
- 接著將
system
目錄推送到ReDroid系統,並賦予權限:
1
2
3
4
5
6
| adb -s localhost:5555 push system /
adb -s localhost:5555 shell "pm grant com.google.android.gms android.permission.ACCESS_COARSE_LOCATION"
adb -s localhost:5555 shell "pm grant com.google.android.gms android.permission.ACCESS_FINE_LOCATION"
adb -s localhost:5555 shell "pm grant com.google.android.setupwizard android.permission.READ_PHONE_STATE"
adb -s localhost:5555 shell "pm grant com.google.android.setupwizard android.permission.READ_CONTACTS"
adb reboot
|
- 重新啟動ReDroid容器:
1
2
3
| sudo docker ps
sudo docker restart <ReDroid的容器ID>
|
啟動Scrcpy,開啟系統設定→應用程式,點選右上角顯示系統應用程式,將Google Play服務和Play商店的權限都開啟。
執行以下指令取得Android裝置ID,到Google網站註冊裝置,等個30分鐘後重新啟動Redroid容器,才能登入Google Play。
1
2
3
| adb -s localhost:5555 root
adb -s localhost:5555 shell 'sqlite3 /data/data/com.google.android.gsf/databases/gservices.db \
"select * from main where name = \"android_id\";"'
|
目前即使有安裝libndk,Android 11的Play商店還是不給下載ARM架構的APP,請配合APKPure之類的應用程式商店安裝APP。
除了用容器內部的瀏覽器下載APK外,你還可以用ADB安裝APK至ReDroid容器。比方說到ApkMirror下載Line的APK,接著用ADB安裝:
1
| adb -s localhost:5555 install "jp.naver.line.android.apk"
|
你也可以用ADB的pull
和push
指令傳輸檔案。
關於螢幕解析度的調整,請參閱ReDroid和Scrcpy的使用說明。
如果要將ReDroid關機,將Scrcpy視窗關閉後,停止容器:
1
2
| sudo docker ps
sudo docker stop <ReDroid的容器ID>
|
之後可以再用此指令啟動ReDroid。ReDroid容器的/data
資料位於~/data11-nb
目錄,可以用來備份多個系統的檔案。
1
2
3
4
5
6
7
| sudo docker ps --filter "status=exited"
sudo docker start <ReDroid的容器ID>
adb connect localhost:5555
scrcpy -s localhost:5555
|
目前來看,ReDroid的泛用性比Waydroid好,因為不只造福Linux使用者,連那些想擺脫專有模擬器、想自架雲手機的用戶都可以利用ReDroid達成目的。