赞
踩
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服务框架,以达成最佳使用体验。
PS Windows和MacOS也可以跑Docker。
ReDroid在Github上有各大Linux发行版的安装说明。
由于我是Arch Linux,要先补齐Linux核心模组binderfs。
接着安装docker和docker-compose,用于执行容器
安装ADB和Scrcpy,连线到Android桌面:
- # archlinux
- sudo pacman -S android-tools
- sudo pacman -S scrcpy
*想要Scrcpy和Sndcpy二者整合和按键映射的,可以试试看QtScrcpy。
大部分电脑是x86架构,只能执行x86版的Android APP,然而很多手机游戏只有ARM版。所以跑ReDroid前建议先下载ARM转译器,不然能执行的APP会少很多。
ReDroid支援用QEMU或libndk转译,本文采用后者。libndk是Google开发的ARM → x86转译器,含在Android Studio的模拟器里。注意libndk是专有软体,使用上处于灰色地带。
- 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
所在的目录,修正权限后重新压缩档案:
- cd ~/Droid-NDK-Extractor/working/extracted/
-
- mkdir native-bridge
-
- cd native-bridge
-
- tar -xpf ../native-bridge.tar
-
- chmod 0644 system/etc/init/ndk_translation_arm64.rc
-
- chmod 0755 system/bin/arm
-
- chmod 0755 system/bin/arm64
-
- chmod 0755 system/lib/arm
-
- chmod 0755 system/lib64/arm64
-
- chmod 0644 system/etc/binfmt_misc/*
-
- tar -cpf native-bridge.tar system
-
- mv native-bridge.tar ..
-
- cd ..
-
- rm -r native-bridge
native-bridge.tar
准备完成。ReDroid目前提供Android 8 ~ Android 13的映像档。由于要使用libndk的关系,故以Android 11的映像档为基础下去建置。
新增一个空白目录android
,将刚刚制作的native-bridge.tar
放到此目录。
在android
目录新增一个名为dockerfile
的档案,填入以下内容:
- FROM redroid/redroid:11.0.0-amd64
-
- ADD native-bridge.tar /
android
目录开启终端机,开始建置含有libndk的ReDroid映像档:docker build . -t redroid-11-libndk
如果要用ReDroid玩手机游戏,建议电脑至少要有8GB以上RAM,因为有时ARM在转译成x86指令时会占用大量RAM。
--rm
是因为后续还要对系统做修改。- sudo docker run -itd --privileged \
-
- -v /home/user/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
如果要用docker-compose.yml
,内容如下:
- version: "3"
-
- services:
-
- redroid:
-
- image: redroid-11-libndk
-
- stdin_open: true
-
- tty: true
-
- privileged: true
-
- ports:
-
- - "5555:5555"
-
- volumes:
-
- - /home/user/data11-nb:/data
-
- command:
-
- - androidboot.redroid_gpu_mode=host
-
- - ro.product.cpu.abilist0=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 connect localhost:5555
-
-
- # 如果連不上,用以下指令看一下容器內部發生什麼問題
-
- sudo docker logs <容器ID>
-
- sudo docker exec <容器ID> logcat
scrcpy -s localhost:5555
这样就会看到Android的桌面了。
至于声音的话,切换到sndcpy
所在的目录,执行sndcpy
,开始串流音效:
./sndcpy localhost:5555
作者说Google服务框架是专有软体无法内建,那么就得自行安装了。第一个方法是重新编译映像档,第二个是手动安装OpenGApps。
不推荐第一个方法,耗时而且作者提供的GApps编译教学又有其他APP侦测不到的问题。
这里采用第二个方法:手动安装,过程参考自:Install GApps Manually - Google Groups
到OpenGapps下载x86_64架构的Android 11 GApps,选择最小化的pico版。
解压缩,会看到以下目录
- 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
下的目录结构应该会长这样:
- 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
- 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系统,并赋予权限:- 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
- docker ps
-
- docker restart <ReDroid的容器ID>
启动Scrcpy,开启系统设定→应用程式,点选右上角显示系统应用程式,将Google Play服务和Play商店的权限都开启。
执行以下指令取得Android装置ID,到Google网站注册装置,等个30分钟后重新启动Redroid容器,才能登入Google Play。
- 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安装:
adb -s localhost:5555 install "jp.naver.line.android.apk"
你也可以用ADB的pull
和push
指令传输档案。
关于萤幕解析度的调整,请参阅ReDroid和Scrcpy的使用说明。
如果要将ReDroid关机,将Scrcpy视窗关闭后,停止容器:
- sudo docker ps
-
- sudo docker stop <ReDroid的容器ID>
之后可以再用此指令启动ReDroid。ReDroid容器的/data
资料位于~/data11-nb
目录,可以用来备份多个系统的档案。
- docker ps --filter "status=exited"
-
-
- docker start <ReDroid的容器ID>
-
-
- adb connect localhost:5555
-
-
- scrcpy -s localhost:5555
目前来看,ReDroid的泛用性比Waydroid好,因为不只造福Linux使用者,连那些想摆脱专有模拟器、想自架云手机的用户都可以利用ReDroid达成目的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。