CCE

Waydroid on NixOS makes Android on Linux simple

Contents

It's pretty cool to be able to run Android apps on my laptop, though when I'm on X11 I need to use this startwaydroid wrapper that spawns a weston kiosk shell. In Wayland-native mode, the Android apps can exist as their own window outside the full Android UI, which is nice.

nix:tangle ~/nix/nixos/waydroid.nix
{ pkgs, ... }:

{
  virtualisation = {
    waydroid.enable = true;
    incus.enable = true;
  };
  networking.nftables.enable = true;

  environment.systemPackages = let
    # for x11
    waywes = pkgs.writeScriptBin "startwaydroid" ''
      set -x
      SIZE_ARGS="$(${pkgs.kdePackages.kscreen}/bin/kscreen-console json | tail +3 | \
                   jq -r '.screen.currentSize|"--width=\(.width) --height=\(.height - 40)"')"

      ${pkgs.waydroid}/bin/waydroid session stop && \
      ${pkgs.weston}/bin/weston $SIZE_ARGS --shell=kiosk-shell.so --socket=wayland-1 &

      sleep 5
      WAYLAND_DISPLAY=wayland-1 XDG_SESSION_TYPE=wayland ${pkgs.waydroid}/bin/waydroid show-full-ui
    '';
  in [
    pkgs.wl-clipboard
    waywes
    pkgs.waydroid-helper
    pkgs.bindfs
  ];

  systemd = {
    packages = [ pkgs.waydroid-helper pkgs.bindfs ];
    services.waydroid-mount.wantedBy = [ "multi-user.target" ];
  };
}

First Time Configuration of waydroid

In an shell:

shell
sudo waydroid init -s GAPPS
sudo systemctl start waydroid-container
waydroid session start

Download latest F-droid from https://f-droid.org/ and install it

shell
waydroid app install ~/Downloads/F-Droid.apk
shell
waydroid prop set persist.waydroid.multi_windows true
waydroid prop set persist.waydroid.width 1280
waydroid prop set persist.waydroid.height 760

Waydroid Passthrough Browser

passthroughbrowser is a simple solution to opening links from Android apps in the system browser by setting up a small localhost HTTP server. I'll use it in waydroid configurations in a custom derivation:

nix:tangle ~/nix/pkgs/passthroughbrowser.nix
# https://git.kj7rrv.com/kj7rrv/passthroughbrowser.git
{ lib, stdenv,
  makeDesktopItem,
  fetchFromGitea,
  buildPythonPackage,
  flask,
  ... }:

let
  
  desktopItem = makeDesktopItem {
    name = "passthroughbrowser";
    desktopName = "Waydroid Passthrough Browser";
    categories = ["Utility"];
    exec = "passthrough_browser";
  };
in buildPythonPackage {
  name = "passthroughbrowser";
  version = "0.0.1";
  format = "simple";

  src = fetchFromGitea {
    domain = "git.kj7rrv.com";
    owner = "kj7rrv";
    repo = "passthroughbrowser";
    rev = "11ab0f695b6dae4ebee06fa75d6e2796713add98";
    sha256 = "sha256-JSbGsWL3kEYw4uUIUgXi7XuXYFQ0Nxkz+fZbvxfpn1o=";
  };

  propagatedBuildInputs = [
    flask
  ];

  installPhase = ''
    mkdir -p $out/bin $out/share/passthroughbrowser
    cp $src/server.py $out/bin/passthrough_browser
    cp $src/PassThroughBrowser.apk $out/share/passthroughbrowser
    cp --recursive "${desktopItem}/share" "$out/"

    substituteInPlace $out/bin/passthrough_browser \
      --replace "app.run(host='192.168.250.1', port=8888)"  \
                "import os; app.run(host=os.environ.get('PASSTHROUGH_HOST', '192.168.240.1'), port=8888)" 
  '';
}
nix:tangle ~/nix/hm/waydroid-passthrough-browser.nix
{ pkgs, ... }:

{
  home.packages = [
    pkgs.passthroughbrowser
  ];
  home.sessionVariables = {
    PASSTHROUGH_HOST = "192.168.240.1";
  };
}