Skip to content

Instantly share code, notes, and snippets.

@Tsumuri-u
Last active December 4, 2025 14:13
Show Gist options
  • Select an option

  • Save Tsumuri-u/da187a511833633d68c4afcf2da4ddef to your computer and use it in GitHub Desktop.

Select an option

Save Tsumuri-u/da187a511833633d68c4afcf2da4ddef to your computer and use it in GitHub Desktop.
Waydroid for Gachashit

Waydroid sucks ass (for now...)

Preface

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.

0: Make sure you're running on Wayland

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_TYPE

It should output Wayland.

See Section 6 for a method of running Waydroid on Xorg.

1: Installing the Waydroid container

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 -y

See 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 GAPPS

Waydroid 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.

Potential Problems

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-generic

Grab 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.

2: Play Protect Certification

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 shell

The output will look something like:

android_id|large_string_of_numbers

Now 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.

3: ARM Translation

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-venv

Then, 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.txt

Finally, in the same folder, install the translation layer of your choosing:

sudo venv/bin/python3 main.py install libndk
sudo venv/bin/python3 main.py install libhoudini

If you want to uninstall anything, you can run main.py to run the interactive UI:

sudo venv/bin/python3 main.py

4: Can I play now?

Yes. 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.

5: Concessions

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-9999

then restart the session:

waydroid session stop

For 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.

6: Back from the dead

Alternatively: Running this thing with x11

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 weston

Weston 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-ui

From 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

Appendix

Blue Archive

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."
fi

Here 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."
fi

Paste 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.sh

Note: 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment