news 2026/9/28 7:21:50

devenv 中的 Android 开发环境配置:从最小 SDK 到 android-nixpkgs 全版本覆盖

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
devenv 中的 Android 开发环境配置:从最小 SDK 到 android-nixpkgs 全版本覆盖
  • 开发工具
  • CLI

【免费下载链接】devenv

Fast, Declarative, Reproducible, and Composable Developer Environments using Nix

项目地址:https://gitcode.com/gh_mirrors/de/devenv
点击查看免费下载

导读

本文围绕 devenv 的android.enable集成模块,讲解如何在 Nix 驱动的开发环境中一键构建可复现的 Android 开发环境:包括完整可复制的devenv.nix配置、SDK 版本选择策略(nixpkgs androidenv 与 android-nixpkgs 两套来源的取舍)、模拟器创建的正确姿势,以及 React Native 与 Flutter 的专用配置。读完本文,你将能独立写出适用于 Android 原生、RN、Flutter 项目的 devenv 配置,并理解底层ANDROID_HOME、NDK、Gradle 参数是如何被 Nix 模块组装起来的。

最小可用配置:三行开启 Android 环境

在项目根目录创建devenv.nix,写入如下内容即可获得一套完整可用的 Android 开发环境:

{ pkgs, ... }: { android.enable = true; }

android.enable是 src/modules/integrations/android.nix 中定义的总开关。开启后,该模块会自动完成一系列环境搭建工作:

  • 向packages注入完整 SDK 组合(SDK、platform-tools、模拟器等,具体来源见下文);
  • 自动开启 Java 语言支持(java.enable = lib.mkDefault true,见 src/modules/integrations/android.nix);
  • 设置ANDROID_HOME、ANDROID_NDK_ROOT环境变量;
  • 通过GRADLE_OPTS让 Gradle 使用 SDK 自带的 patched aapt2;
  • 进入 shell 时自动生成local.properties(写入sdk.dir与ndk.dir),并设置ANDROID_USER_HOME/ANDROID_AVD_HOME到当前目录的.android/下(见 src/modules/integrations/android.nix)。

也就是说,android.enable = true不只是"装上几个包",而是把 JDK、SDK 路径、Gradle 参数和本地属性文件全部一次性配置到位。

仓库还提供了一个精简的参考示例 examples/android/devenv.nix,它在默认配置基础上显式关闭了 Android Studio:

{ pkgs, ... }: { android.enable = true; android.android-studio.enable = false; }

定制化配置:完整选项清单与默认值

如果默认组合不满足需求,可以按需指定各组件版本。官方文档给出了一份覆盖几乎所有选项的完整配置:

{ pkgs, ... }: { android = { enable = true; platforms.version = [ "32" "34" ]; systemImageTypes = [ "google_apis_playstore" ]; abis = [ "arm64-v8a" "x86_64" ]; cmake.version = [ "3.22.1" ]; cmdLineTools.version = "11.0"; tools.version = "26.1.1"; # platformTools.version defaults to latest from nixpkgs buildTools.version = [ "30.0.3" ]; emulator = { enable = true; # version defaults to latest from nixpkgs }; sources.enable = false; systemImages.enable = true; ndk.enable = true; googleAPIs.enable = true; googleTVAddOns.enable = true; extras = [ "extras;google;gcm" ]; extraLicenses = [ "android-sdk-preview-license" "android-googletv-license" "android-sdk-arm-dbt-license" "google-gdk-license" "intel-android-extra-license" "intel-android-sysimage-license" "mips-android-sysimage-license" ]; android-studio = { enable = true; package = pkgs.android-studio; }; }; }

对照 src/modules/integrations/android.nix 中的选项定义,各选项的真实默认值如下表:

选项默认值说明
platforms.version[ "32" "34" "36" ]要安装的 Android 平台(API level)列表
systemImageTypes[ "google_apis_playstore" ]系统镜像类型
abis[ "arm64-v8a" "x86_64" ]目标 ABI 列表
cmake.version[ "3.22.1" ]随 SDK 安装的 CMake 版本
cmdLineTools.version"11.0"(若启用 Flutter 则为"8.0")命令行工具版本
tools.version"26.1.1"旧版 SDK tools 版本
platformTools.versionnixpkgs 中最新版本由 nixpkgs 的repo.json动态解析
buildTools.version[ "34.0.0" ](若启用 Flutter 则为[ "35.0.0" "33.0.2" "30.0.3" ])Build Tools 版本列表
emulator.enabletrue是否包含模拟器
emulator.versionnixpkgs 中最新版本动态解析
sources.enablefalse是否包含 Android 源码
systemImages.enabletrue是否包含系统镜像
ndk.enabletrue是否包含 NDK
ndk.version[ "26.1.10909125" ](Flutter 下为[ "28.2.13676358" ])NDK 版本列表
googleAPIs.enabletrue是否使用 Google APIs
googleTVAddOns.enabletrue是否使用 Google TV Add-Ons
extras[ "extras;google;gcm" ]额外组件
extraLicenses上表所列 7 个 license 的默认集合自动接受的额外许可证
android-studio.enable/.packagefalse/pkgs.android-studio是否安装 Android Studio 及使用的包
flutter.enable/.packagefalse/pkgs.flutter是否包含 Flutter 工具
reactNative.enablefalse是否包含 React Native 工具

默认值的底层来源

需要特别说明:platformTools.version与emulator.version的默认值并不是写死的字符串,而是从 nixpkgs 的 androidenv 仓库 JSON 中动态读取的。源码实现如下(src/modules/integrations/android.nix):

repoJson = builtins.fromJSON (builtins.readFile "${toString pkgs.path}/pkgs/development/mobile/androidenv/repo.json"); availableVersions = package: builtins.attrNames repoJson.packages.${package}; latestVersion = package: lib.last (builtins.sort lib.lessThan (availableVersions package));

这就是文档中"platformTools.version和emulator.version默认使用 nixpkgs 中的最新版本"这一说法的实现依据。因此,这两个选项的可用版本完全取决于你所引用的 nixpkgs 快照——如果你尝试构建一个不存在的版本,构建报错信息里会列出所有可用版本。

环境变量与 Gradle 的底层联动

开启模块后,以下环境变量会被自动注入(src/modules/integrations/android.nix):

  • ANDROID_HOME:指向组装好的 SDK 根目录;
  • ANDROID_NDK_ROOT:指向ndk-bundle(nixpkgs 来源)或ndk/<version>(android-nixpkgs 来源);
  • GRADLE_OPTS:-Dorg.gradle.project.android.aapt2FromMavenOverride=<ANDROID_HOME>/build-tools/<首个 buildTools 版本>/aapt2,强制 Gradle 使用 SDK 中打过补丁的 aapt2,避免与从 Maven 拉取的版本产生不兼容;
  • 启用 Flutter 时还会设置FLUTTER_ROOT与DART_ROOT。

进入 shell 时还会把tools、platform-tools、cmdline-tools/latest/bin、emulator目录加入PATH,并导出ANDROID_USER_HOME、ANDROID_AVD_HOME指向项目目录下的.android/,确保 AVD 状态不污染全局用户目录。

关于 unfree 包的重要前提

Android SDK 包含大量 unfree 软件包(如 Google Play Store 系统镜像、部分闭源组件),因此必须在devenv.yaml中允许 unfree 包,否则构建会直接失败:

nixpkgs: allow_unfree: true

选择 SDK 版本:nixpkgs androidenv 的滞后问题

platforms.version、buildTools.version、ndk.version等选项所能选择的版本,全部来自 nixpkgs 内置的androidenv包集合。由于 androidenv 的更新节奏落后于 Google 的官方发布,一个刚发布的新版本(例如platforms;android-36)在 androidenv 中可能还不可用,此时选择它会导致构建失败。

注意:这里说的"不可用"是相对于你当前锁定的 nixpkgs 版本而言的。当前仓库默认的platforms.version已经是[ "32" "34" "36" ],说明该 nixpkgs 快照已包含 API 36——但这并不改变 androidenv 整体滞后于 Google 官方发布的客观事实。

切换到 android-nixpkgs:获得每日更新的完整版本集

要选取完整且最新的版本集合,官方推荐引入android-nixpkgsinput。该项目基于 Google 的 SDK 仓库每日重新生成,因此新平台、新 Build Tools 版本的可用性远超 nixpkgs androidenv。

添加 input 的命令如下:

$ devenv inputs add android-nixpkgs github:tadfisher/android-nixpkgs --follows nixpkgs

这条命令会修改项目根目录的devenv.yaml。从 CLI 实现看,devenv inputs add是早期分发的命令之一,会先定位到外层项目根再编辑其devenv.yaml,避免在子目录中误建游离的配置文件(见 devenv/src/main.rs)。

发布轨道(release track)的选择

android-nixpkgs 的发布轨道由 input 的 URL ref 决定,默认是stable。如需其他轨道,把 URL 指向对应分支即可:

  • github:tadfisher/android-nixpkgs(默认stable)
  • github:tadfisher/android-nixpkgs/beta
  • github:tadfisher/android-nixpkgs/preview
  • github:tadfisher/android-nixpkgs/canary

切换后的行为变化

一旦android-nixpkgsinput 存在,模块会自动把 SDK 来源切换为 android-nixpkgs。源码中的判定逻辑非常直接(src/modules/integrations/android.nix):

android-nixpkgs = inputs.android-nixpkgs or null; useAndroidNixpkgs = android-nixpkgs != null;

切换后:

  • platforms.version、buildTools.version、ndk.version以及emulator.enable会被自动映射到 android-nixpkgs 的对应 SDK 包(映射规则见 src/modules/integrations/android.nix:版本号中的.会被转换为-,例如35.0.0→build-tools-35-0-0、36→platforms-android-36);
  • ANDROID_HOME指向share/android-sdk,NDK 目录布局变为ndk/<version>(与 nixpkgs 来源的ndk-bundle不同);
  • 系统镜像、源码、CMake、extras 不在自动映射范围内,需要把这些组件直接加入 devenv 的顶层packages。

组合示例:同时使用两套配置

以下配置展示了切换到 android-nixpkgs 后选择新版本,并手工安装系统镜像的完整写法:

{ inputs, pkgs, ... }: { android = { enable = true; platforms.version = [ "34" "35" "36" ]; buildTools.version = [ "35.0.0" ]; }; packages = [ (inputs.android-nixpkgs.sdk.${pkgs.system} (sdkPkgs: with sdkPkgs; [ system-images-android-36-google-apis-playstore-x86-64 ])) ]; }

注意:android-nixpkgs 目前支持x86_64-linux、x86_64-darwin与aarch64-darwin三个平台(见 src/modules/integrations/android.nix 中android-nixpkgs.sdk.${pkgs.system}的调用方式,实际可用平台以 android-nixpkgs 自身声明为准)。

模拟器:绕过 Android Studio GUI,用 CLI 创建 AVD

由于 Nix 的不可变 store 路径与 Android Studio 对可变路径的要求存在冲突,直接在 Android Studio 的 GUI 中创建模拟器可能无法正常工作。官方推荐的做法是先用命令行创建 AVD,再在 Android Studio 中开发。

创建 AVD

使用avdmanager(位于 cmdline-tools 中,进入 devenv shell 后已在PATH中)创建:

avdmanager create avd --force --name my-android-emulator-name --package 'system-images;android-32;google_apis_playstore;x86_64'

创建完成后即可用任意文本编辑器进行 Android 开发。官方文档记录的真实测试场景是:先在外部用上述命令创建好模拟器,然后在 Android Studio 自带的终端里运行一个 React Native 项目,能够成功运行。

需要注意,AVD 的存放位置由ANDROID_AVD_HOME决定——模块在进入 shell 时已将其指向项目目录下的.android/avd/,因此每个项目的模拟器状态是相互隔离的。

React Native:一行开启 RN 工具链

android.reactNative.enable会额外启用 JavaScript 与 npm 工具链,并把 JDK 固定为pkgs.jdk17(与 reactnative.dev 的环境设置文档)。该配置已通过 React Native starter 项目验证:

{ pkgs, ... }: { android = { enable = true; reactNative.enable = true; }; }

Flutter:一行开启 Flutter 工具链

android.flutter.enable会额外启用 Dart 语言支持、安装 Flutter 包,并把 JDK 固定为pkgs.jdk17(与 developer.android.com 的 JDK 版本建议)。该配置已通过 Flutter starter 项目验证:

{ pkgs, ... }: { android = { enable = true; flutter.enable = true; }; }

Flutter 的自动路径同步任务

开启 Flutter 后,模块还会注册一个名为devenv:android:flutter:sync-properties的 task(src/modules/integrations/android.nix),在每次进入 shell(before = [ "devenv:enterShell" ])之前自动运行,负责:

  • 更新android/local.properties与各级子目录中的同名文件:写入sdk.dir=$ANDROID_HOME、ndk.dir=$ANDROID_NDK_ROOT、flutter.sdk=$FLUTTER_ROOT;
  • 更新ios/Flutter/Generated.xcconfig中的FLUTTER_ROOT;
  • 更新ios/flutter_export_environment.sh中的FLUTTER_ROOT导出。

这个 task 的存在意味着:即使你手动改动了local.properties,每次进入 devenv shell 时这些路径都会被重新纠正为当前环境值,从机制上杜绝了"换机器后 Flutter 找不到 SDK"的经典问题。

总结:配置速查与常见问题

场景需要做什么
仅 Android 原生开发android.enable = true+devenv.yaml中nixpkgs.allow_unfree = true
需要 Android Studio追加android.android-studio.enable = true
需要最新 SDK 版本devenv inputs add android-nixpkgs github:tadfisher/android-nixpkgs --follows nixpkgs,并按需指定platforms.version等
需要新版本系统镜像通过 android-nixpkgs 的sdk函数加入顶层packages
React Nativeandroid.reactNative.enable = true
Flutterandroid.flutter.enable = true

常见问题速查:

  1. 构建报"版本不可用":说明所选版本在当前 nixpkgs androidenv(或 android-nixpkgs 轨道)中不存在。查看报错信息列出的可用版本列表,或切换到 android-nixpkgs 获取更新版本。
  2. 构建报 unfree 包被拒绝:检查devenv.yaml中是否已设置nixpkgs.allow_unfree = true。
  3. Android Studio 中无法创建 AVD:改用avdmanager create avd命令行方式创建,再在 IDE 中连接使用。
  4. Gradle 报 aapt2 相关错误:确认GRADLE_OPTS中aapt2FromMavenOverride指向的 SDK 路径存在且 build-tools 版本已安装。

本文全部配置项均可在 src/modules/integrations/android.nix 中找到实现定义,参考示例见 examples/android/devenv.nix,原始文档见 docs/src/content/docs/integrations/android.md。

  • 开发工具
  • CLI

【免费下载链接】devenv

Fast, Declarative, Reproducible, and Composable Developer Environments using Nix

项目地址:https://gitcode.com/gh_mirrors/de/devenv
点击查看免费下载
上一篇:使用 WebdriverIO Browser Runner 测试 Svelte 组件:配置、编写与源码原理详解
下一篇:如何轻松掌握LDOCE5词典工具:新手必看的3个实用技巧

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 7:19:39

美食数据爬取分析可视化实战:从乱码到热力图的闭环链路

简介&#xff1a;本资源是一套完整的Python数据科学实战项目&#xff0c;面向编程初学者与数据分析入门者&#xff0c;聚焦美食领域从数据获取到可视化呈现的全流程实践。项目涵盖网络爬虫&#xff08;requestsBeautifulSoup&#xff09;、数据清洗分析&#xff08;pandasNumPy…

作者头像 李华
网站建设 2026/9/28 7:19:37

易拉罐底部缺陷检测实战:VOC转YOLO与YOLOv8训练全流程

简介&#xff1a;面向工业质检、目标检测入门及毕设场景的易拉罐底部缺陷检测数据集&#xff0c;包含1122张标注图片与3308个真实标注框&#xff0c;覆盖FB、can、hole、scratch、stamped共5个类别&#xff0c;可用于训练缺陷分类与定位模型。数据同时提供Pascal VOC和YOLO两种…

作者头像 李华
网站建设 2026/9/28 7:19:31

STM32 SAI接口实现16通道TDM音频混音的完整方案

做一个多路音频聚合的项目&#xff0c;我一开始天真地以为I2S就够了&#xff0c;直到面对16通道混音需求时&#xff0c;才发现单根I2S数据线只能承载两路音频&#xff0c;想继续拓展就得往TDM方向走。最终我用STM32的SAI接口&#xff0c;把多路I2S数据按时隙拆开、再打包成一根…

作者头像 李华
网站建设 2026/9/28 7:18:39

PS+ComfyUI线稿转彩稿工作流实战指南

1. 为什么“线稿→成品”这个环节成了场景设计师的隐形瓶颈我带过三届视觉设计实习生&#xff0c;每届都会在第三周遇到同一个崩溃时刻&#xff1a;他们花8小时画完一张精细线稿&#xff0c;却卡在上色和氛围营造上——不是不会调色&#xff0c;而是反复修改十几次后&#xff0…

作者头像 李华