Android: Difference between revisions

From NixOS Wiki
imported>Ajs124
m add nixdroid
Almino (talk | contribs)
m Making it easier to list USB devices for beginners.
 
(44 intermediate revisions by 27 users not shown)
Line 1: Line 1:
=== Connecting Android device ===
== Using the Android SDK ==
<syntaxhighlight lang=console>
NixOS uses the androidenv package for building android SDKs and manually creating emulators without the use of Android Studio. Example android sdk is <code>androidenv.androidPkgs_9_0.androidsdk</code>. They also include all of the SDK tools such as sdkmanager and avdmanager needed to create emulators.
$ nix-shell -p androidenv.platformTools
{{Note|<code><small>androidenv.androidPkgs_9_0</small></code> has been replaced with <code><u><small>androidenv.androidPkgs</small></u></code> in nixos 24.11, see [https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2411.section.md#backward-incompatibilities-sec-release-2411-incompatibilities backward-incompatibilities-sec-release-2411-incompatibilities], so all the <code><small>androidPkgs_9_0</small></code> references below need be changed after 24.11 gets released.}}
% adb connect 192.168.1.10
The first link provides a guide for creating a custom android SDK, using a predefined SDK, and how to nixify an emulator. The second link is an extra guide that might have some helpful tips for improving your workflow.
% adb shell
# [https://nixos.org/manual/nixpkgs/unstable/#android Official Android SDK guide from NixOS.org]
# [https://sandervanderburg.blogspot.de/2014/02/reproducing-android-app-deployments-or.html  Reproducing Android app deployments]
 
When creating emulators with Nix's emulateApp function as mentioned in the first link, your IDE should now be able to recognize the emulator but you won't be able to run the code. To run it, view the first link on how to run the apk file in the emulator.
 
To run emulateApp, build it with <code>nix-build fileName.nix</code>. It'll build in the folder <code>result</code>. run it with <code>./result/bin/run-test-emulator</code>
 
== Creating emulators without Nix ==
If you don't want to nixify your emulators, you can use Android Studio and set up emulators there like a regular system.
 
Using <code>sdkmanager</code> and <code>avdmanager</code> from the Android SDK may not work given how Nix stores its files. You can use them from the Android Studio GUI.
 
When using machine images from the SDK, you will need to run them with <code>steam-run</code>, and possibly pass extra flags, e.g.:
 
<code>steam-run ~/Android/Sdk/emulator/emulator -feature -Vulkan @Pixel_5_API_33</code>
 
=== hardware acceleration ===
 
NOTE: Whether this here is effective needs more research and confirmation. My colleague and I have seen the emulator using around 800% CPU. So far, the following has improved that on my side.
 
See also the [https://github.com/NixOS/nixpkgs/issues/41703 nixpkgs issue] where people tried to trace issues.
 
Add your user to the <code>kvm</code> group:
 
<syntaxhighlight lang=nix>
{
  users.users.<your-user>.extraGroups = [ "kvm" ];
}
</syntaxhighlight>
</syntaxhighlight>


Add these lines to your <code>configuration.nix</code> for enabling adb in NixOS for unprivileged users
== adb setup ==
 
To enable <code>adb</code> in NixOS for unprivileged users
add these lines to your <code>configuration.nix</code>.
This is mandatory for all further interactions with your android device.
 
<syntaxhighlight lang=nix>
<syntaxhighlight lang=nix>
{
{
  ...
   programs.adb.enable = true;
   programs.adb.enable = true;
   users.users.<your-user>.extraGroups = ["adbusers"];
   users.users.<your-user>.extraGroups = [ "adbusers" ];
}
}
</syntaxhighlight>
</syntaxhighlight>


=== Transfering files from/to an Android device ===
This will add [https://github.com/M0Rf30/android-udev-rules additional udev rules] for unprivileged access as well as add adb to your <code>$PATH</code>.
 
Alternatively, if you don't want to install adb globally but do want to configure the udev rules, you can:
 
<syntaxhighlight lang=nix>
{
  services.udev.packages = [
    pkgs.android-udev-rules
  ];
}
</syntaxhighlight>
 
=== Use Older Platform Version ===
If you would like to get older platform version, you can write the following.
 
<syntaxhighlight lang=nix>
{ pkgs ? import <nixpkgs> {
  config.android_sdk.accept_license = true;
  overlays = [
    (self: super: {
      androidPkgs_8_0 = super.androidenv.composeAndroidPackages {
        platformVersions = [ "26" ];
        abiVersions = [ "x86" "x86_64"];
      };
    })
  ];
} }:
 
(pkgs.buildFHSUserEnv {
  name = "android-sdk-env";
  targetPkgs = pkgs: (with pkgs;
    [
      androidPkgs_8_0.androidsdk
      glibc
    ]);
  runScript = "bash";
}).env
 
</syntaxhighlight>
 
== Interaction with your Android device ==
 
=== adb shell on device ===
 
First open a nix-shell with the platform tools and connect your device:
 
<syntaxhighlight lang=console>
$ nix-shell -p androidenv.androidPkgs.platform-tools
% adb devices
List of devices attached
* daemon not running; starting now at tcp:5037
* daemon started successfully
BH90272JCU unauthorized
</syntaxhighlight>
 
Troubleshooting: [https://stackoverflow.com/a/28211161 no device is listed]
 
A popup appears on your phone to allow your computer access to it. After allowing, you can:
 
<syntaxhighlight lang=console>
% adb devices
List of devices attached
BH90272JCU device
% adb shell
</syntaxhighlight>
 
You can also connect to an already-running adb server:
 
<syntaxhighlight lang=console>
$ # For nixos < 19.03
$ # nix-shell -p androidenv.platformTools
$ nix-shell -p androidenv.androidPkgs_9_0.platform-tools
% adb connect 192.168.1.10
% adb shell
</syntaxhighlight>
 
=== Transferring files from/to an Android device ===
 
There are two main methods for newer devices:
There are two main methods for newer devices:
* <code>adb push</code> and <code>adb pull</code>: see above.
* <code>adb push</code> and <code>adb pull</code>: see above.
* via [[MTP]], see [[MTP|the corresponding page]]
* via [[MTP]], see [[MTP|the corresponding page]]


=== Building Android apps using Nix ===
== Android Development ==
 
=== Android Studio ===
 
To develop apps using [https://developer.android.com/studio/ Android Studio], install it to your system.


Some software (for example Tinc VPN) have Android client which can be built together with the NixOS version, in the same derivation, sharing the same configuration options.
<syntaxhighlight lang="nix">
environment.systemPackages = [
  pkgs.android-studio
]
</syntaxhighlight>


...
By default, Android Studio has a FHS environment and by using <code>pkgs.android-studio-full</code> you get the predefined Android SDK composition including (as of nixos-unstable on 2024-11-02) platforms 28-34, an emulator, many system images and the NDK.


=== Android Studio on NixOS ===
Notice: to install Android Studio, you have to indicate accepting the EULA. If you don't, the rebuild fails and prints the EULA. The simplest way to acknowledge it is to add this line to your config: <syntaxhighlight lang="nix">
<syntaxhighlight lang=console>
nixpkgs.config.android_sdk.accept_license = true;
$ nix-shell -p android-studio --run android-studio
</syntaxhighlight>
 
=== gradlew ===
 
It's possible to create a build environment (shell.nix) to use with gradlew as a FHS environment:
 
<syntaxhighlight lang=nix>
{ pkgs ? import <nixpkgs> {config.android_sdk.accept_license = true;} }:
 
(pkgs.buildFHSUserEnv {
  name = "android-sdk-env";
  targetPkgs = pkgs: (with pkgs;
    [
      androidenv.androidPkgs_9_0.androidsdk
      glibc
    ]);
  runScript = "bash";
}).env
</syntaxhighlight>
 
As an alternative, it's often enough to override just the aapt2 binary for the gradle build process:
 
<syntaxhighlight lang=nix>
{ pkgs ? import <nixpkgs> {config.android_sdk.accept_license = true;} }:
 
let
  androidSdk = pkgs.androidenv.androidPkgs_9_0.androidsdk;
in
pkgs.mkShell {
  buildInputs = with pkgs; [
    androidSdk
    glibc
  ];
  # override the aapt2 that gradle uses with the nix-shipped version
  GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${androidSdk}/libexec/android-sdk/build-tools/28.0.3/aapt2";
}
</syntaxhighlight>
</syntaxhighlight>
See the [https://nixos.org/manual/nixpkgs/unstable/#android  androidenv documentation] for full examples.


=== Building Android on NixOS ===
=== Building Android on NixOS ===
Line 40: Line 193:
   name = "android-env";
   name = "android-env";
   targetPkgs = pkgs: with pkgs;
   targetPkgs = pkgs: with pkgs;
     [ git
     [
      git
       gitRepo
       gitRepo
       gnupg
       gnupg
Line 49: Line 203:
       gnumake
       gnumake
       nettools
       nettools
       androidenv.platformTools
       androidenv.androidPkgs_9_0.platform-tools
       jdk
       jdk
       schedtool
       schedtool
       utillinux
       util-linux
       m4
       m4
       gperf
       gperf
Line 62: Line 216:
       flex
       flex
       lzop
       lzop
      python3
     ];
     ];
   multiPkgs = pkgs: with pkgs;
   multiPkgs = pkgs: with pkgs;
     [ zlib
     [ zlib
      ncurses5
     ];
     ];
   runScript = "bash";
   runScript = "bash";
   profile = ''
   profile = ''
    export ALLOW_NINJA_ENV=true
     export USE_CCACHE=1
     export USE_CCACHE=1
     export ANDROID_JAVA_HOME=${pkgs.jdk.home}
     export ANDROID_JAVA_HOME=${pkgs.jdk.home}sdkmanager install avd
    export LD_LIBRARY_PATH=/usr/lib:/usr/lib32
   '';
   '';
};
};
Line 80: Line 238:
</syntaxhighlight>
</syntaxhighlight>


[https://nixos.org/nix-dev/2015-April/016881.html Source]
=== Android Debug Bridge ===


[https://gist.github.com/Nadrieril/d006c0d9784ba7eff0b092796d78eb2a More complete example with instructions, for LineageOS]
Run <code>nix-shell -p usbutils --run "lsusb"</code> on your terminal to get the list of USB devices connected to your computer. Sample output ([https://stackoverflow.com/a/58594229/437459 source]):<pre>
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubBus 001 Device 009: ID 138a:0010 Validity Sensors, Inc. VFS Fingerprint sensor
Bus 001 Device 008: ID 13d3:3491 IMC Networks
</pre>


There is also [https://github.com/ajs124/NixDroid NixDroid], to build Android completely with nix. It is however not very well documented and requires patches to nix, etc.
<code>ID 1d6b:0003</code> can be seen as: <code>idVendor = 1d6b</code> and <code>idProduct = 0003</code>.
 
<syntaxhighlight lang="nix">
{
  programs.adb.enable = true;
  services.udev.extraRules =
    let
      # nix-shell -p usbutils --run "lsusb"
      idVendor = "1d6b"; # Change according to the guide above
      idProduct = "0003"; # Change according to the guide above
    in
    ''
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", MODE="[]", GROUP="adbusers", TAG+="uaccess"
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", ATTR{idProduct}=="${idProduct}", SYMLINK+="android_adb"
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", ATTR{idProduct}=="${idProduct}", SYMLINK+="android_fastboot"
    '';
 
  # add user to adbusers group
  users.users.myUser = {
  isNormalUser = true;
  extraGroups = [ "adbusers" ];
  };
}
</syntaxhighlight>


== Using the nixpkgs androidenv ==
# [https://nixos.org/nix-dev/2015-April/016881.html more information on that snippet]
User Sander van der Burg created two awesome blog posts as well as a number of test cases usable as examples on how to use the nixpkgs androidenv and the emulator provideded:
# [https://gist.github.com/Nadrieril/d006c0d9784ba7eff0b092796d78eb2a A shell.nix to build LineageOS]
# [https://sandervanderburg.blogspot.de/2012/11/building-android-applications-with-nix.html Building Android applications with the Nix package manager ]
# [https://github.com/danielfullmer/robotnix robotnix], building aosp roms (e.g. LineageOS) with nix.
# [https://sandervanderburg.blogspot.de/2014/02/reproducing-android-app-deployments-or.html  Reproducing Android app deployments (or playing Angry Birds on NixOS)]
# [https://github.com/mrVanDalo/LineagoOS-build LineageOS build setup using terranix and hcloud], based on the [https://gist.github.com/Nadrieril/d006c0d9784ba7eff0b092796d78eb2a shell.nix to build LineageOS]. Useful if you are in a rush and don't have to much CPU power on your hand.
# [https://github.com/svanderburg/nix-androidenvtests A set of androidenv test cases]
# [https://wiki.archlinux.org/title/Android_Debug_Bridge Archlinux Wiki to Android_Debug_Bridge]

Latest revision as of 15:01, 20 December 2024

Using the Android SDK

NixOS uses the androidenv package for building android SDKs and manually creating emulators without the use of Android Studio. Example android sdk is androidenv.androidPkgs_9_0.androidsdk. They also include all of the SDK tools such as sdkmanager and avdmanager needed to create emulators.

Note: androidenv.androidPkgs_9_0 has been replaced with androidenv.androidPkgs in nixos 24.11, see backward-incompatibilities-sec-release-2411-incompatibilities, so all the androidPkgs_9_0 references below need be changed after 24.11 gets released.

The first link provides a guide for creating a custom android SDK, using a predefined SDK, and how to nixify an emulator. The second link is an extra guide that might have some helpful tips for improving your workflow.

  1. Official Android SDK guide from NixOS.org
  2. Reproducing Android app deployments

When creating emulators with Nix's emulateApp function as mentioned in the first link, your IDE should now be able to recognize the emulator but you won't be able to run the code. To run it, view the first link on how to run the apk file in the emulator.

To run emulateApp, build it with nix-build fileName.nix. It'll build in the folder result. run it with ./result/bin/run-test-emulator

Creating emulators without Nix

If you don't want to nixify your emulators, you can use Android Studio and set up emulators there like a regular system.

Using sdkmanager and avdmanager from the Android SDK may not work given how Nix stores its files. You can use them from the Android Studio GUI.

When using machine images from the SDK, you will need to run them with steam-run, and possibly pass extra flags, e.g.:

steam-run ~/Android/Sdk/emulator/emulator -feature -Vulkan @Pixel_5_API_33

hardware acceleration

NOTE: Whether this here is effective needs more research and confirmation. My colleague and I have seen the emulator using around 800% CPU. So far, the following has improved that on my side.

See also the nixpkgs issue where people tried to trace issues.

Add your user to the kvm group:

{
  users.users.<your-user>.extraGroups = [ "kvm" ];
}

adb setup

To enable adb in NixOS for unprivileged users add these lines to your configuration.nix. This is mandatory for all further interactions with your android device.

{
  programs.adb.enable = true;
  users.users.<your-user>.extraGroups = [ "adbusers" ];
}

This will add additional udev rules for unprivileged access as well as add adb to your $PATH.

Alternatively, if you don't want to install adb globally but do want to configure the udev rules, you can:

{
  services.udev.packages = [
    pkgs.android-udev-rules
  ];
}

Use Older Platform Version

If you would like to get older platform version, you can write the following.

{ pkgs ? import <nixpkgs> { 
  config.android_sdk.accept_license = true;
  overlays = [
    (self: super: {
      androidPkgs_8_0 = super.androidenv.composeAndroidPackages {
        platformVersions = [ "26" ];
        abiVersions = [ "x86" "x86_64"];
      };
    })
  ];
} }:

(pkgs.buildFHSUserEnv {
  name = "android-sdk-env";
  targetPkgs = pkgs: (with pkgs;
    [
      androidPkgs_8_0.androidsdk
      glibc
    ]);
  runScript = "bash";
}).env

Interaction with your Android device

adb shell on device

First open a nix-shell with the platform tools and connect your device:

$ nix-shell -p androidenv.androidPkgs.platform-tools
% adb devices
List of devices attached
* daemon not running; starting now at tcp:5037
* daemon started successfully
BH90272JCU	unauthorized

Troubleshooting: no device is listed

A popup appears on your phone to allow your computer access to it. After allowing, you can:

% adb devices
List of devices attached
BH90272JCU	device
% adb shell

You can also connect to an already-running adb server:

$ # For nixos < 19.03
$ # nix-shell -p androidenv.platformTools
$ nix-shell -p androidenv.androidPkgs_9_0.platform-tools
% adb connect 192.168.1.10
% adb shell

Transferring files from/to an Android device

There are two main methods for newer devices:

Android Development

Android Studio

To develop apps using Android Studio, install it to your system.

environment.systemPackages = [
  pkgs.android-studio
]

By default, Android Studio has a FHS environment and by using pkgs.android-studio-full you get the predefined Android SDK composition including (as of nixos-unstable on 2024-11-02) platforms 28-34, an emulator, many system images and the NDK.

Notice: to install Android Studio, you have to indicate accepting the EULA. If you don't, the rebuild fails and prints the EULA. The simplest way to acknowledge it is to add this line to your config:

nixpkgs.config.android_sdk.accept_license = true;

gradlew

It's possible to create a build environment (shell.nix) to use with gradlew as a FHS environment:

{ pkgs ? import <nixpkgs> {config.android_sdk.accept_license = true;} }:

(pkgs.buildFHSUserEnv {
  name = "android-sdk-env";
  targetPkgs = pkgs: (with pkgs;
    [
      androidenv.androidPkgs_9_0.androidsdk
      glibc
    ]);
  runScript = "bash";
}).env

As an alternative, it's often enough to override just the aapt2 binary for the gradle build process:

{ pkgs ? import <nixpkgs> {config.android_sdk.accept_license = true;} }:

let
  androidSdk = pkgs.androidenv.androidPkgs_9_0.androidsdk;
in
pkgs.mkShell {
  buildInputs = with pkgs; [
    androidSdk
    glibc
  ];
  # override the aapt2 that gradle uses with the nix-shipped version
  GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${androidSdk}/libexec/android-sdk/build-tools/28.0.3/aapt2";
}

See the androidenv documentation for full examples.

Building Android on NixOS

It's possible to use nix-shell with buildFHSUserEnv to set up an environment in which it's viable to build Android without huge amounts of editing. This is an example shell.nix file.

{ pkgs ? import <nixpkgs> {} }:
 
let fhs = pkgs.buildFHSUserEnv {
  name = "android-env";
  targetPkgs = pkgs: with pkgs;
    [
      git
      gitRepo
      gnupg
      python2
      curl
      procps
      openssl
      gnumake
      nettools
      androidenv.androidPkgs_9_0.platform-tools
      jdk
      schedtool
      util-linux
      m4
      gperf
      perl
      libxml2
      zip
      unzip
      bison
      flex
      lzop
      python3
    ];
  multiPkgs = pkgs: with pkgs;
    [ zlib
      ncurses5
    ];
  runScript = "bash";
  profile = ''
    export ALLOW_NINJA_ENV=true
    export USE_CCACHE=1
    export ANDROID_JAVA_HOME=${pkgs.jdk.home}sdkmanager install avd
    export LD_LIBRARY_PATH=/usr/lib:/usr/lib32
  '';
};
in pkgs.stdenv.mkDerivation {
  name = "android-env-shell";
  nativeBuildInputs = [ fhs ];
  shellHook = "exec android-env";

}

Android Debug Bridge

Run nix-shell -p usbutils --run "lsusb" on your terminal to get the list of USB devices connected to your computer. Sample output (source):

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubBus 001 Device 009: ID 138a:0010 Validity Sensors, Inc. VFS Fingerprint sensor
Bus 001 Device 008: ID 13d3:3491 IMC Networks

ID 1d6b:0003 can be seen as: idVendor = 1d6b and idProduct = 0003.

{
  programs.adb.enable = true;
  services.udev.extraRules =
    let
      # nix-shell -p usbutils --run "lsusb"
      idVendor = "1d6b"; # Change according to the guide above
      idProduct = "0003"; # Change according to the guide above
    in
    ''
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", MODE="[]", GROUP="adbusers", TAG+="uaccess"
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", ATTR{idProduct}=="${idProduct}", SYMLINK+="android_adb"
      SUBSYSTEM=="usb", ATTR{idVendor}=="${idVendor}", ATTR{idProduct}=="${idProduct}", SYMLINK+="android_fastboot"
    '';

  # add user to adbusers group
  users.users.myUser = {
   isNormalUser = true;
   extraGroups = [ "adbusers" ];
  };
}
  1. more information on that snippet
  2. A shell.nix to build LineageOS
  3. robotnix, building aosp roms (e.g. LineageOS) with nix.
  4. LineageOS build setup using terranix and hcloud, based on the shell.nix to build LineageOS. Useful if you are in a rush and don't have to much CPU power on your hand.
  5. Archlinux Wiki to Android_Debug_Bridge