This guide is for Ubuntu and Ubuntu-based distros. Most concepts will remain the same on other distros, but when installing packages, you will have to use your own package manager instead of apt.
Waydroid, as its name suggests, only works on Wayland, not Xorg. If you're on Gnome, then on your login screen, click the cog icon on the bottom and make sure the Xorg option is NOT selected. To verify this, run:
echo $XDG_SESSION_TYPEIt should output Wayland.
See Section 6 for a method of running Waydroid on Xorg.
Install Waydroid on Ubuntu with its dependencies:
sudo apt install curl ca-certificates -y
curl https://repo.waydro.id | sudo bash
sudo apt install waydroid -ySee the Waydroid docs for instructions for other distros.
By default, Waydroid has no Google application functionality, and won't come with the Play Store. We need to include it when creating the container. Initialize the Waydroid container with GAPPs:
sudo waydroid init -s GAPPSWaydroid should be running now, with desktop entries for each Android application installed in the container. Open Waydroid to run the Android system, or open the app to run it standalone.
If you get a "failed to load binder module" error when trying to initialize the container, this means you don't have the needed Anbox kernel modules. We can install them ourselves.
Install the needed dependencies:
sudo apt install dkms linux-headers-genericGrab and install the modules:
git clone https://github.com/choff/anbox-modules.git
cd anbox-modules
sudo Now you can try initializing the container again.
We have the Play Store, but we won't be able to sign in and install apps without Google Play Certification. You will get an obnoxious notification every two seconds until you do this. First, we need to get our Waydroid Android ID:
echo 'ANDROID_RUNTIME_ROOT=/apex/com.android.runtime sqlite3 /data/data/com.google.android.gsf/databases/gservices.db "select * from main where name = \"android_id\";"' | sudo waydroid shellThe output will look something like:
android_id|large_string_of_numbersNow go here, paste in the large string of numbers, run the captcha, and register the device. This may take a few hours. Once done, you should be able to sign in and install Google Play apps.
You're running Waydroid on an x86 machine, but the vast majority of Android games require an ARM CPU. Therefore, we must install a translation layer. You have two choices: libhoudihi and libndk. It's generally accepted that libhoudini gives the best performance on Android 9 and 11, whereas libndk is best for Android 10 and perhaps systems with AMD CPUs. Either way, we can use Waydroid Extras Script to make things easier for us.
First, install its dependencies:
sudo apt install lzip python3.11-venvThen, grab the script and install its python requirements:
git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script
python3 -m venv venv
venv/bin/pip install -r requirements.txtFinally, in the same folder, install the translation layer of your choosing:
sudo venv/bin/python3 main.py install libndksudo venv/bin/python3 main.py install libhoudiniIf you want to uninstall anything, you can run main.py to run the interactive UI:
sudo venv/bin/python3 main.pyYes. Go to the Google Play Store, install the app of your choosing, and it should run. This was tested with Arknights. Any app that you install in the container will have a desktop entry created for you, so you can launch the app on its own without having to go through the Android home screen first.
I will add any game fixes or known bugs in the Appendix. Note that I likely won't be keeping this section updated.
Games will likely open in a windowed fullscreen mode. It will fit itself to your screen, avoiding your panel and dock. It cannot be resized without the command line. This does not seem to be the case with regular Android apps, which can be resized with the mouse.
Resizing fullscreen apps is buggy and not recommended. It requires setting container properties via command line and then restarting the session.
To resize:
waydroid prop set persist.waydroid.width 0-9999
waydroid prop set persist.waydroid.height 0-9999then restart the session:
waydroid session stopFor fullscreen games, this doesn't fix the game launching in fullscreen when launched via the desktop. But launching it via the newly-resized Android container does work.
Waydroid can't run on x11. The container will also automatically start in fullscreen on your monitor, with no way to resize the window or add a title bar. Setting the container properties can be annoying, and being forced to use Waydroid in fullscreen can be uncomfortable. We can remedy these issues using a Wayland compositor that supports a nested session such as Weston or Cage. Cage is annoying, can't be configured, and doesn't solve our issue of not wanting to set Waydroid container properties, so let's go with Weston.
sudo apt install westonWeston doesn't come with a desktop entry, but we can run Weston from the terminal by simply running weston. Alternatively, we can create a desktop entry for it so we can start it via the desktop. Here's a sample:
[Desktop Entry]
Type=Application
Name=Weston
Comment=Wayland compositor
Exec=weston
Categories=System;Utility;
Icon=wayland
NoDisplay=false
Name this weston.desktop and place it in ~/.local/share/applications/. Weston should now show up in your applications list.
By default, Weston will launch with a simple panel, a minimal flower-themed wallpaper, and a launcher in the panel for the terminal. This Weston window is a full Wayland compositor, and we can freely resize it as we please. From the terminal, we can launch a Waydroid session, which will automatically maximize itself to fit the Weston window.
waydroid show-full-uiFrom here, we can play around with Android as we please. Note that if we resize the Weston window after starting the container, the container won't resize with it.
Weston is decently configurable, and there are a few key changes we want to make for convenience. First, create a file named weston.ini in ~/.config/.
The first change we need to make is to set the shortcut bind to ctrl. By default, it's super, but this doesn't work because super is already being used by the desktop.
The next change is to set the default output to your desired resolution. You can resize the window normally, but setting a default size is convenient.
Then, we can add some launchers. A terminal, Waydroid, Arknights, and one to stop the Waydroid session. We need that last one because closing the Weston window won't actually stop whatever's currently running. We can just click this button when we want to close our container. Here's my config:
#To make my terminal less ugly and play nice with zsh
[terminal]
font=MesloLGS NF
font-size=16
#Changing binding to ctrl
[shell]
binding-modifier=ctrl
#Setting my default window size to 1080p
[output]
name=X1
mode=1920x1080
#Launch the weston terminal
[launcher]
icon=/usr/share/icons/gnome/32x32/apps/utilities-terminal.png
displayname=Terminal
path=/usr/bin/weston-terminal
#Launch waydroid
[launcher]
icon=/usr/share/icons/hicolor/32x32/apps/waydroid.png
displayname=Waydroid
path=/usr/bin/waydroid show-full-ui
#Launch Arknights
[launcher]
icon=/home/tsumuri/.local/share/waydroid/data/icons/ak32.png
displayname=Arknights
path=/usr/bin/waydroid app launch com.YoStarEN.Arknights
#Shortcut to stop the Waydroid container
[launcher]
icon=asdfasdf
displayname=Stop Waydroid
path=/usr/bin/waydroid session stop
Notes:
- My config has some icons. You'll need to source these yourself. If you replace the path with jibberish (see the Stop Waydroid launcher), it'll default to an X icon.
- The path NEEDS to be an absolute path. The program won't launch otherwise.
- I'm pretty sure the icon also needs to be 32x32
Blue Archive seems to crash on the loading screen at the start. Currently, there is a workaround which involves applying a patch to libhoudini or libndk (found here).
Here is the patch for libhoudini:
#!/bin/bash
function CheckHex {
#file path, Ghidra offset, Hex to check
commandoutput="$(od $1 --skip-bytes=$(($2-0x100000)) --read-bytes=$((${#3} / 2)) --endian=little -t x1 -An file | sed 's/ //g')"
if [ "$commandoutput" = "$3" ]; then
echo "1"
else
echo "0"
fi
}
function PatchHex {
#file path, ghidra offset, original hex, new hex
file_offset=$(($2-0x100000))
if [ $(CheckHex $1 $2 $3) = "1" ]; then
hexinbin=$(printf $4 | xxd -r -p)
echo -n $hexinbin | dd of=$1 seek=$file_offset bs=1 conv=notrunc;
tmp="Patched $1 at $file_offset with new hex $4"
echo $tmp
elif [ $(CheckHex $1 $2 $4) = "1" ]; then
echo "Already patched"
else
echo "Hex mismatch!"
fi
}
houdini_path="/var/lib/waydroid/overlay/system/lib64/libhoudini.so"
if [ -f $houdini_path ]; then
if [ -w houdini_path ] || [ "$EUID" = 0 ]; then
PatchHex $houdini_path 0x4062a5 48b8fbffffff 48b8ffffffff
PatchHex $houdini_path 0x4099d6 83e0fb 83e0ff
PatchHex $houdini_path 0x409b42 e8892feeff 9090909090
else
echo "Libhoudini is not writeable. Please run with sudo"
fi
else
echo "Libhoudini not found. Please install it first."
fiHere is the one for libndk:
#!/bin/bash
function CheckHex {
#file path, Ghidra offset, Hex to check
commandoutput="$(od $1 --skip-bytes=$(($2-0x101000)) --read-bytes=$((${#3} / 2)) --endian=little -t x1 -An file | sed 's/ //g')"
if [ "$commandoutput" = "$3" ]; then
echo "1"
else
echo "0"
fi
}
function PatchHex {
#file path, ghidra offset, original hex, new hex
file_offset=$(($2-0x101000))
if [ $(CheckHex $1 $2 $3) = "1" ]; then
hexinbin=$(printf $4 | xxd -r -p)
echo -n $hexinbin | dd of=$1 seek=$file_offset bs=1 conv=notrunc;
tmp="Patched $1 at $file_offset with new hex $4"
echo $tmp
elif [ $(CheckHex $1 $2 $4) = "1" ]; then
echo "Already patched"
else
echo "Hex mismatch!"
fi
}
ndk_path="/var/lib/waydroid/overlay/system/lib64/libndk_translation.so"
if [ -f $ndk_path ]; then
if [ -w ndk_path ] || [ "$EUID" = 0 ]; then
PatchHex $ndk_path 0x307dd1 83e2fa 83e2ff
PatchHex $ndk_path 0x307cd6 83e2fa 83e2ff
else
echo "libndk_translation is not writeable. Please run with sudo"
fi
else
echo "libndk_translation not found. Please install it first."
fiPaste the one for your translation layer into an empty .sh file (name it anything, the source calls it scripton).
Now open a terminal wherever you saved the file, set the script as executable and then run it:
chmod +x scripton.sh
sudo ./scripton.shNote: You really shouldn't run random scripts on your computer, especially with sudo. Make sure you check their contents to ensure that they don't try and run something malicious.
Once you run the patch, Blue Archive should run.