Merge pull request #66747 from erikarvstedt/androidenv-fixes

Androidenv fixes

authored by Matthew Bauer and committed by GitHub 5be571ee e04a39d5

+61 -66
+4 -5
doc/languages-frameworks/android.section.md
··· 185 186 androidenv.emulateApp { 187 name = "emulate-MyAndroidApp"; 188 - platformVersion = "24"; 189 - abiVersion = "armeabi-v7a"; # mips, x86 or x86_64 190 - systemImageType = "default"; 191 - useGoogleAPIs = false; 192 } 193 ``` 194 ··· 201 androidenv.emulateApp { 202 name = "emulate-MyAndroidApp"; 203 platformVersion = "24"; 204 - abiVersion = "armeabi-v7a"; # mips, x86 or x86_64 205 systemImageType = "default"; 206 useGoogleAPIs = false; 207 app = ./MyApp.apk;
··· 185 186 androidenv.emulateApp { 187 name = "emulate-MyAndroidApp"; 188 + platformVersion = "28"; 189 + abiVersion = "x86_64"; # armeabi-v7a, mips, x86 190 + systemImageType = "google_apis_playstore"; 191 } 192 ``` 193 ··· 200 androidenv.emulateApp { 201 name = "emulate-MyAndroidApp"; 202 platformVersion = "24"; 203 + abiVersion = "armeabi-v7a"; # mips, x86, x86_64 204 systemImageType = "default"; 205 useGoogleAPIs = false; 206 app = ./MyApp.apk;
+4 -4
pkgs/development/mobile/androidenv/build-app.nix
··· 1 - { composeAndroidPackages, stdenv, ant, jdk, gnumake, gawk }: 2 3 { name 4 , release ? false, keyStore ? null, keyAlias ? null, keyStorePassword ? null, keyAliasPassword ? null ··· 16 extraArgs = removeAttrs args ([ "name" ] ++ builtins.attrNames androidSdkFormalArgs); 17 in 18 stdenv.mkDerivation ({ 19 - name = stdenv.lib.replaceChars [" "] [""] name; # Android APKs may contain white spaces in their names, but Nix store paths cannot 20 ANDROID_HOME = "${androidsdk}/libexec/android-sdk"; 21 buildInputs = [ jdk ant ]; 22 buildPhase = '' 23 - ${stdenv.lib.optionalString release '' 24 # Provide key singing attributes 25 ( echo "key.store=${keyStore}" 26 echo "key.alias=${keyAlias}" ··· 31 32 export ANDROID_SDK_HOME=`pwd` # Key files cannot be stored in the user's home directory. This overrides it. 33 34 - ${stdenv.lib.optionalString (args ? includeNDK && args.includeNDK) '' 35 export GNUMAKE=${gnumake}/bin/make 36 export NDK_HOST_AWK=${gawk}/bin/gawk 37 ${androidsdk}/libexec/android-sdk/ndk-bundle/ndk-build
··· 1 + { composeAndroidPackages, stdenv, lib, ant, jdk, gnumake, gawk }: 2 3 { name 4 , release ? false, keyStore ? null, keyAlias ? null, keyStorePassword ? null, keyAliasPassword ? null ··· 16 extraArgs = removeAttrs args ([ "name" ] ++ builtins.attrNames androidSdkFormalArgs); 17 in 18 stdenv.mkDerivation ({ 19 + name = lib.replaceChars [" "] [""] name; # Android APKs may contain white spaces in their names, but Nix store paths cannot 20 ANDROID_HOME = "${androidsdk}/libexec/android-sdk"; 21 buildInputs = [ jdk ant ]; 22 buildPhase = '' 23 + ${lib.optionalString release '' 24 # Provide key singing attributes 25 ( echo "key.store=${keyStore}" 26 echo "key.alias=${keyAlias}" ··· 31 32 export ANDROID_SDK_HOME=`pwd` # Key files cannot be stored in the user's home directory. This overrides it. 33 34 + ${lib.optionalString (args ? includeNDK && args.includeNDK) '' 35 export GNUMAKE=${gnumake}/bin/make 36 export NDK_HOST_AWK=${gawk}/bin/gawk 37 ${androidsdk}/libexec/android-sdk/ndk-bundle/ndk-build
+28 -29
pkgs/development/mobile/androidenv/compose-android-packages.nix
··· 21 }: 22 23 let 24 - inherit (pkgs) stdenv fetchurl makeWrapper unzip; 25 26 # Determine the Android os identifier from Nix's system identifier 27 os = if stdenv.system == "x86_64-linux" then "linux" ··· 59 }; 60 61 system-images-packages = 62 - stdenv.lib.recursiveUpdate 63 system-images-packages-android 64 - (stdenv.lib.recursiveUpdate system-images-packages-android-tv 65 - (stdenv.lib.recursiveUpdate system-images-packages-android-wear 66 - (stdenv.lib.recursiveUpdate system-images-packages-android-wear-cn 67 - (stdenv.lib.recursiveUpdate system-images-packages-google_apis system-images-packages-google_apis_playstore)))); 68 69 # Generated addons 70 addons = import ./generated/addons.nix { ··· 77 }; 78 79 platform-tools = import ./platform-tools.nix { 80 - inherit deployAndroidPackage os autoPatchelfHook pkgs; 81 - inherit (stdenv) lib; 82 package = packages.platform-tools."${platformToolsVersion}"; 83 }; 84 85 build-tools = map (version: 86 import ./build-tools.nix { 87 - inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686; 88 - inherit (stdenv) lib; 89 package = packages.build-tools."${version}"; 90 } 91 ) buildToolsVersions; ··· 96 }; 97 98 emulator = import ./emulator.nix { 99 - inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686; 100 - inherit (stdenv) lib; 101 package = packages.emulator."${emulatorVersion}"."${os}"; 102 }; 103 ··· 115 } 116 ) platformVersions; 117 118 - system-images = stdenv.lib.flatten (map (apiVersion: 119 map (type: 120 map (abiVersion: 121 deployAndroidPackage { 122 inherit os; 123 package = system-images-packages.${apiVersion}.${type}.${abiVersion}; 124 } 125 ) abiVersions 126 ) systemImageTypes ··· 128 129 lldb = map (version: 130 import ./lldb.nix { 131 - inherit deployAndroidPackage os autoPatchelfHook pkgs; 132 - inherit (stdenv) lib; 133 package = packages.lldb."${version}"; 134 } 135 ) lldbVersions; 136 137 cmake = map (version: 138 import ./cmake.nix { 139 - inherit deployAndroidPackage os autoPatchelfHook pkgs; 140 - inherit (stdenv) lib; 141 package = packages.cmake."${version}"; 142 } 143 ) cmakeVersions; 144 145 ndk-bundle = import ./ndk-bundle { 146 - inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs platform-tools; 147 - inherit (stdenv) lib; 148 package = packages.ndk-bundle."${ndkVersion}"; 149 }; 150 ··· 164 165 # Function that automatically links all plugins for which multiple versions can coexist 166 linkPlugins = {name, plugins}: 167 - stdenv.lib.optionalString (plugins != []) '' 168 mkdir -p ${name} 169 - ${stdenv.lib.concatMapStrings (plugin: '' 170 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 171 '') plugins} 172 ''; 173 174 # Function that automatically links a plugin for which only one version exists 175 linkPlugin = {name, plugin, check ? true}: 176 - stdenv.lib.optionalString check '' 177 ln -s ${plugin}/libexec/android-sdk/* ${name} 178 ''; 179 180 # Links all plugins related to a requested platform 181 linkPlatformPlugins = {name, plugins, check}: 182 - stdenv.lib.optionalString check '' 183 mkdir -p ${name} 184 - ${stdenv.lib.concatMapStrings (plugin: '' 185 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 186 '') plugins} 187 ''; # */ ··· 194 https://developer.android.com/studio/terms 195 by setting nixpkgs config option 'android_sdk.accept_license = true;' 196 '' else import ./tools.nix { 197 - inherit deployAndroidPackage requireFile packages toolsVersion autoPatchelfHook makeWrapper os pkgs pkgs_i686; 198 - inherit (stdenv) lib; 199 200 postInstall = '' 201 # Symlink all requested plugins ··· 210 ${linkPlugins { name = "cmake"; plugins = cmake; }} 211 ${linkPlugin { name = "ndk-bundle"; plugin = ndk-bundle; check = includeNDK; }} 212 213 - ${stdenv.lib.optionalString includeSystemImages '' 214 mkdir -p system-images 215 - ${stdenv.lib.concatMapStrings (system-image: '' 216 apiVersion=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*)) 217 type=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*/*)) 218 mkdir -p system-images/$apiVersion/$type ··· 224 ${linkPlatformPlugins { name = "add-ons"; plugins = google-apis; check = useGoogleTVAddOns; }} 225 226 # Link extras 227 - ${stdenv.lib.concatMapStrings (identifier: 228 let 229 path = addons.extras."${identifier}".path; 230 addon = deployAndroidPackage {
··· 21 }: 22 23 let 24 + inherit (pkgs) stdenv lib fetchurl makeWrapper unzip; 25 26 # Determine the Android os identifier from Nix's system identifier 27 os = if stdenv.system == "x86_64-linux" then "linux" ··· 59 }; 60 61 system-images-packages = 62 + lib.recursiveUpdate 63 system-images-packages-android 64 + (lib.recursiveUpdate system-images-packages-android-tv 65 + (lib.recursiveUpdate system-images-packages-android-wear 66 + (lib.recursiveUpdate system-images-packages-android-wear-cn 67 + (lib.recursiveUpdate system-images-packages-google_apis system-images-packages-google_apis_playstore)))); 68 69 # Generated addons 70 addons = import ./generated/addons.nix { ··· 77 }; 78 79 platform-tools = import ./platform-tools.nix { 80 + inherit deployAndroidPackage os autoPatchelfHook pkgs lib; 81 package = packages.platform-tools."${platformToolsVersion}"; 82 }; 83 84 build-tools = map (version: 85 import ./build-tools.nix { 86 + inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686 lib; 87 package = packages.build-tools."${version}"; 88 } 89 ) buildToolsVersions; ··· 94 }; 95 96 emulator = import ./emulator.nix { 97 + inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686 lib; 98 package = packages.emulator."${emulatorVersion}"."${os}"; 99 }; 100 ··· 112 } 113 ) platformVersions; 114 115 + system-images = lib.flatten (map (apiVersion: 116 map (type: 117 map (abiVersion: 118 deployAndroidPackage { 119 inherit os; 120 package = system-images-packages.${apiVersion}.${type}.${abiVersion}; 121 + # Patch 'google_apis' system images so they're recognized by the sdk. 122 + # Without this, `android list targets` shows 'Tag/ABIs : no ABIs' instead 123 + # of 'Tag/ABIs : google_apis*/*' and the emulator fails with an ABI-related error. 124 + patchInstructions = lib.optionalString (lib.hasPrefix "google_apis" type) '' 125 + sed -i '/^Addon.Vendor/d' source.properties 126 + ''; 127 } 128 ) abiVersions 129 ) systemImageTypes ··· 131 132 lldb = map (version: 133 import ./lldb.nix { 134 + inherit deployAndroidPackage os autoPatchelfHook pkgs lib; 135 package = packages.lldb."${version}"; 136 } 137 ) lldbVersions; 138 139 cmake = map (version: 140 import ./cmake.nix { 141 + inherit deployAndroidPackage os autoPatchelfHook pkgs lib; 142 package = packages.cmake."${version}"; 143 } 144 ) cmakeVersions; 145 146 ndk-bundle = import ./ndk-bundle { 147 + inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs lib platform-tools; 148 package = packages.ndk-bundle."${ndkVersion}"; 149 }; 150 ··· 164 165 # Function that automatically links all plugins for which multiple versions can coexist 166 linkPlugins = {name, plugins}: 167 + lib.optionalString (plugins != []) '' 168 mkdir -p ${name} 169 + ${lib.concatMapStrings (plugin: '' 170 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 171 '') plugins} 172 ''; 173 174 # Function that automatically links a plugin for which only one version exists 175 linkPlugin = {name, plugin, check ? true}: 176 + lib.optionalString check '' 177 ln -s ${plugin}/libexec/android-sdk/* ${name} 178 ''; 179 180 # Links all plugins related to a requested platform 181 linkPlatformPlugins = {name, plugins, check}: 182 + lib.optionalString check '' 183 mkdir -p ${name} 184 + ${lib.concatMapStrings (plugin: '' 185 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 186 '') plugins} 187 ''; # */ ··· 194 https://developer.android.com/studio/terms 195 by setting nixpkgs config option 'android_sdk.accept_license = true;' 196 '' else import ./tools.nix { 197 + inherit deployAndroidPackage requireFile packages toolsVersion autoPatchelfHook makeWrapper os pkgs pkgs_i686 lib; 198 199 postInstall = '' 200 # Symlink all requested plugins ··· 209 ${linkPlugins { name = "cmake"; plugins = cmake; }} 210 ${linkPlugin { name = "ndk-bundle"; plugin = ndk-bundle; check = includeNDK; }} 211 212 + ${lib.optionalString includeSystemImages '' 213 mkdir -p system-images 214 + ${lib.concatMapStrings (system-image: '' 215 apiVersion=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*)) 216 type=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*/*)) 217 mkdir -p system-images/$apiVersion/$type ··· 223 ${linkPlatformPlugins { name = "add-ons"; plugins = google-apis; check = useGoogleTVAddOns; }} 224 225 # Link extras 226 + ${lib.concatMapStrings (identifier: 227 let 228 path = addons.extras."${identifier}".path; 229 addon = deployAndroidPackage {
+2 -2
pkgs/development/mobile/androidenv/default.nix
··· 10 }; 11 12 buildApp = import ./build-app.nix { 13 - inherit (pkgs) stdenv jdk ant gnumake gawk; 14 inherit composeAndroidPackages; 15 }; 16 17 emulateApp = import ./emulate-app.nix { 18 - inherit (pkgs) stdenv; 19 inherit composeAndroidPackages; 20 }; 21
··· 10 }; 11 12 buildApp = import ./build-app.nix { 13 + inherit (pkgs) stdenv lib jdk ant gnumake gawk; 14 inherit composeAndroidPackages; 15 }; 16 17 emulateApp = import ./emulate-app.nix { 18 + inherit (pkgs) stdenv lib; 19 inherit composeAndroidPackages; 20 }; 21
+23 -26
pkgs/development/mobile/androidenv/emulate-app.nix
··· 1 - { composeAndroidPackages, stdenv }: 2 { name, app ? null 3 - , platformVersion ? "16", abiVersion ? "armeabi-v7a", systemImageType ? "default", useGoogleAPIs ? false 4 , enableGPU ? false, extraAVDFiles ? [] 5 , package ? null, activity ? null 6 - , avdHomeDir ? null 7 - }@args: 8 9 let 10 - androidSdkArgNames = builtins.attrNames (builtins.functionArgs composeAndroidPackages); 11 - 12 - # Extract the parameters meant for the Android SDK 13 - androidParams = { 14 platformVersions = [ platformVersion ]; 15 includeEmulator = true; 16 includeSystemImages = true; 17 systemImageTypes = [ systemImageType ]; 18 abiVersions = [ abiVersion ]; 19 - }; 20 21 - androidsdkComposition = (composeAndroidPackages androidParams).androidsdk; 22 in 23 stdenv.mkDerivation { 24 inherit name; ··· 44 ''} 45 46 # We need to specify the location of the Android SDK root folder 47 - export ANDROID_SDK_ROOT=${androidsdkComposition}/libexec/android-sdk 48 49 # We have to look for a free TCP port 50 ··· 52 53 for i in $(seq 5554 2 5584) 54 do 55 - if [ -z "$(${androidsdkComposition}/libexec/android-sdk/platform-tools/adb devices | grep emulator-$i)" ] 56 then 57 port=$i 58 break ··· 70 export ANDROID_SERIAL="emulator-$port" 71 72 # Create a virtual android device for testing if it does not exists 73 - ${androidsdkComposition}/libexec/android-sdk/tools/android list targets 74 75 - if [ "$(${androidsdkComposition}/libexec/android-sdk/tools/android list avd | grep 'Name: device')" = "" ] 76 then 77 # Create a virtual android device 78 - yes "" | ${androidsdkComposition}/libexec/android-sdk/tools/android create avd -n device -t 1 --abi ${systemImageType}/${abiVersion} $NIX_ANDROID_AVD_FLAGS 79 80 - ${stdenv.lib.optionalString enableGPU '' 81 # Enable GPU acceleration 82 echo "hw.gpu.enabled=yes" >> $ANDROID_SDK_HOME/.android/avd/device.avd/config.ini 83 ''} 84 85 - ${stdenv.lib.concatMapStrings (extraAVDFile: '' 86 ln -sf ${extraAVDFile} $ANDROID_SDK_HOME/.android/avd/device.avd 87 '') extraAVDFiles} 88 fi 89 90 # Launch the emulator 91 - ${androidsdkComposition}/libexec/android-sdk/emulator/emulator -avd device -no-boot-anim -port $port $NIX_ANDROID_EMULATOR_FLAGS & 92 93 # Wait until the device has completely booted 94 echo "Waiting until the emulator has booted the device and the package manager is ready..." >&2 95 96 - ${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port wait-for-device 97 98 echo "Device state has been reached" >&2 99 100 - while [ -z "$(${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell getprop dev.bootcomplete | grep 1)" ] 101 do 102 sleep 5 103 done 104 105 echo "dev.bootcomplete property is 1" >&2 106 107 - #while [ -z "$(${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell getprop sys.boot_completed | grep 1)" ] 108 #do 109 #sleep 5 110 #done ··· 113 114 echo "ready" >&2 115 116 - ${stdenv.lib.optionalString (app != null) '' 117 # Install the App through the debugger, if it has not been installed yet 118 119 - if [ -z "${package}" ] || [ "$(${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell pm list packages | grep package:${package})" = "" ] 120 then 121 if [ -d "${app}" ] 122 then ··· 125 appPath="${app}" 126 fi 127 128 - ${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port install "$appPath" 129 fi 130 131 # Start the application 132 - ${stdenv.lib.optionalString (package != null && activity != null) '' 133 - ${androidsdkComposition}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell am start -a android.intent.action.MAIN -n ${package}/${activity} 134 ''} 135 ''} 136 EOF
··· 1 + { composeAndroidPackages, stdenv, lib }: 2 { name, app ? null 3 + , platformVersion ? "16", abiVersion ? "armeabi-v7a", systemImageType ? "default" 4 , enableGPU ? false, extraAVDFiles ? [] 5 , package ? null, activity ? null 6 + , avdHomeDir ? null, sdkExtraArgs ? {} 7 + }: 8 9 let 10 + sdkArgs = { 11 platformVersions = [ platformVersion ]; 12 includeEmulator = true; 13 includeSystemImages = true; 14 systemImageTypes = [ systemImageType ]; 15 abiVersions = [ abiVersion ]; 16 + } // sdkExtraArgs; 17 18 + sdk = (composeAndroidPackages sdkArgs).androidsdk; 19 in 20 stdenv.mkDerivation { 21 inherit name; ··· 41 ''} 42 43 # We need to specify the location of the Android SDK root folder 44 + export ANDROID_SDK_ROOT=${sdk}/libexec/android-sdk 45 46 # We have to look for a free TCP port 47 ··· 49 50 for i in $(seq 5554 2 5584) 51 do 52 + if [ -z "$(${sdk}/libexec/android-sdk/platform-tools/adb devices | grep emulator-$i)" ] 53 then 54 port=$i 55 break ··· 67 export ANDROID_SERIAL="emulator-$port" 68 69 # Create a virtual android device for testing if it does not exists 70 + ${sdk}/libexec/android-sdk/tools/android list targets 71 72 + if [ "$(${sdk}/libexec/android-sdk/tools/android list avd | grep 'Name: device')" = "" ] 73 then 74 # Create a virtual android device 75 + yes "" | ${sdk}/libexec/android-sdk/tools/android create avd -n device -t 1 --abi ${systemImageType}/${abiVersion} $NIX_ANDROID_AVD_FLAGS 76 77 + ${lib.optionalString enableGPU '' 78 # Enable GPU acceleration 79 echo "hw.gpu.enabled=yes" >> $ANDROID_SDK_HOME/.android/avd/device.avd/config.ini 80 ''} 81 82 + ${lib.concatMapStrings (extraAVDFile: '' 83 ln -sf ${extraAVDFile} $ANDROID_SDK_HOME/.android/avd/device.avd 84 '') extraAVDFiles} 85 fi 86 87 # Launch the emulator 88 + ${sdk}/libexec/android-sdk/emulator/emulator -avd device -no-boot-anim -port $port $NIX_ANDROID_EMULATOR_FLAGS & 89 90 # Wait until the device has completely booted 91 echo "Waiting until the emulator has booted the device and the package manager is ready..." >&2 92 93 + ${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port wait-for-device 94 95 echo "Device state has been reached" >&2 96 97 + while [ -z "$(${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell getprop dev.bootcomplete | grep 1)" ] 98 do 99 sleep 5 100 done 101 102 echo "dev.bootcomplete property is 1" >&2 103 104 + #while [ -z "$(${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell getprop sys.boot_completed | grep 1)" ] 105 #do 106 #sleep 5 107 #done ··· 110 111 echo "ready" >&2 112 113 + ${lib.optionalString (app != null) '' 114 # Install the App through the debugger, if it has not been installed yet 115 116 + if [ -z "${package}" ] || [ "$(${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell pm list packages | grep package:${package})" = "" ] 117 then 118 if [ -d "${app}" ] 119 then ··· 122 appPath="${app}" 123 fi 124 125 + ${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port install "$appPath" 126 fi 127 128 # Start the application 129 + ${lib.optionalString (package != null && activity != null) '' 130 + ${sdk}/libexec/android-sdk/platform-tools/adb -s emulator-$port shell am start -a android.intent.action.MAIN -n ${package}/${activity} 131 ''} 132 ''} 133 EOF