sdkmanager avdmanager emulator 创建运行 avd android 模拟器
#sdkmanager, #avdmanager, #avd, #emulator, #android, #fastboot, #adb, #openjdk, #java
- 搭建 android sdkmanager 环境
- sdkmanager 命令
- 拼接解压
- 配置临时环境安装必备组件
- 创建适合的模拟器
- 修改 android 模拟器的分辨率(可选)
- 运行 avd android 模拟器
- 其他命令
- 参考
搭建 android sdkmanager 环境
- 进入 android sdkmanager 官网点击 command-line-tools-only 下载对应架构的工具包,比如我的是 macmini m4 则下载 Download Android Command Line Tools for Mac
- 进入 https://github.com/adoptium 搜索最新版本
openjdk比如 openjdk 25 下载对应架构的包,比如我的是 macmini m4 则下载 OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz
- 接下来的环境搭建都是参考了 sdkmanager 命令 请享用
- 拼接创建
/cmdline-tools和/jdk路径并解压commandlinetools-mac-13114758_latest.zip和OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz
# 创建存放 sdkmanager 工具的路径结尾一定要拼接 `cmdline-tools` 比如
mkdir -pv "$HOME/Desktops/android_sdk/cmdline-tools"
# 创建存放 jdk 工具的路径这个没有特别的要求路径没有空格英文路径即可,比如
mkdir -pv "$HOME/Desktops/android_sdk/jdk"
# 解压 `commandlinetools-mac-13114758_latest.zip`
unzip -o commandlinetools-mac-13114758_latest.zip -d "$HOME/Desktops/android_sdk/cmdline-tools"
# 提取 `OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz` 根目录
OPENJDK_ROOT_PATH=$(tar tf OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz | awk -F'/' 'NF <= 2 { print }' | head -n 1)
echo $OPENJDK_ROOT_PATH
# 解压 `OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz`
tar zxvf OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.1_8.tar.gz -C "$HOME/Desktops/android_sdk"
# 修改工具包 cmdline-tools 文件夹的名字
rm -frv "$HOME/Desktops/android_sdk/cmdline-tools/latest"
mv -fv "$HOME/Desktops/android_sdk/cmdline-tools/cmdline-tools" "$HOME/Desktops/android_sdk/cmdline-tools/latest"
# 修改替换 openjdk 路径后清空文件夹
# 需要注意的是 macos openjdk 根目录会有 Contents/Home
# linux 请将 jdk/Contents 改为 jdk
rm -frv "$HOME/Desktops/android_sdk/jdk/Contents"
# linux 请将 ${OPENJDK_ROOT_PATH}Contents 改为 ${OPENJDK_ROOT_PATH}
mv -fv "$HOME/Desktops/android_sdk/${OPENJDK_ROOT_PATH}Contents" "$HOME/Desktops/android_sdk/jdk"
rm -frv "$HOME/Desktops/android_sdk/${OPENJDK_ROOT_PATH}"
4. 补充配置临时环境变量,安装 platform-tools和emulator 两大件,后续也可以将这个环境写入到像是 .zshrc,.zprofile 和 .bashrc 之类的 shell 配置文件中一劳永逸
# 临时配置 `SDK root` 环境
# 定义基础目录
BASE_DIR="$HOME/Desktops"
ANDROID_SDK_DIR="$BASE_DIR/android_sdk"
JDK_DIR="$ANDROID_SDK_DIR/jdk"
# **加载 Android SDK 相关环境**
# https://developer.android.com/tools/sdkmanager
if [ -d "$ANDROID_SDK_DIR" ]; then
# android 模拟器路径 `.android`
export ANDROID_HOME="$ANDROID_SDK_DIR"
# sdk root 路径
export ANDROID_SDK_HOME="$ANDROID_HOME"
export ANDROID_SDK_ROOT="$ANDROID_SDK_HOME"
# openjdk 路径
# 需要注意的是 macos openjdk 根目录会有 Contents/Home
# linux 请将 $JDK_DIR/Contents/Home 改为 $JDK_DIR
JAVA_HOME="$JDK_DIR/Contents/Home"
export PATH="$ANDROID_SDK_HOME/cmdline-tools/latest/bin:$ANDROID_SDK_HOME/platform-tools:$ANDROID_SDK_HOME/emulator:$JAVA_HOME/bin:$PATH"
echo "已配置 Android SDK 环境"
else
echo "未检测到 Android SDK,跳过所有相关工具的配置"
fi
# 测试 `java` 命令
java --version
# 测试 `sdkmanager` 命令
sdkmanager --version
# 检查目前最新版的 `platform-tools`和`emulator` 三大件
sdkmanager --list | grep -EIi 'platform-tools' | tail -n 1
sdkmanager --list | grep -EIi 'emulator' | grep -v 'extras' | tail -n 1
# 将信息存为变量用作的下载
PLATFORM_TOOLS=$(sdkmanager --list | grep -EIi 'platform-tools' | tail -n 1 | awk 'NR=1 {print $1}')
EMULATER=$(sdkmanager --list | grep -EIi 'emulator' | grep -v 'extras' | tail -n 1 | awk 'NR=1 {print $1}')
# 在 Linux / macOS / Git Bash 上自动化接受许可证
yes | sdkmanager --licenses
# 批量安装所需包 `platform-tools`和`emulator` 两大件
sdkmanager --install $PLATFORM_TOOLS $EMULATER
# 检查两大件已经展示在列表
sdkmanager --list_installed
# 测试 `adb`, `fastboot`, `avdmanager`, `emulator` 命令
adb --version
fastboot --version
emulator -version
avdmanager --help
5. 创建适合 macmini m4 的 android arm64-v8a android 模拟器(适用于 Apple Silicon Mac)
# sdk 36 -> android 16
# 如果是 x86_64 机器可以尝试以下规则
# grep -E 'system-images;android-[0-9]{2,};.+;x86_64' | \
# 以下是可选的筛选,其中需要注意的是 google_apis_playstore 没有 root 权限
# grep -v "playstore" | \
# grep -m 1 "google_apis_playstore" | \
# grep -m 1 "google_apis" | \
# 先挑选合适的镜像,比如 `system-images;android-36;google_apis_playstore;arm64-v8a` 也可以自定义修改筛选方式
# 目标:最高 API Level + google_apis_playstore + arm64-v8a
sdkmanager --list | \
grep -E 'system-images;android-[0-9]{2,};.+;arm64-v8a' | \
awk -F'[;-]' '{ print $3 " " $0 }' | \
sort -nr | \
grep -v "playstore" | \
grep -m 1 "google_apis" | \
awk '{print $2}'
# 将其存储为又臭又长的变量用作安装
SYSTEM_IMAGES_VERSION=$(sdkmanager --list | \
grep -E 'system-images;android-[0-9]{2,};.+;arm64-v8a' | \
awk -F'[;-]' '{ print $3 " " $0 }' | \
sort -nr | \
grep -v "playstore" | \
grep -m 1 "google_apis" | \
awk '{print $2}')
echo $SYSTEM_IMAGES_VERSION
# 再挑选合适的设备, 比如 `pixel_9_pro_xl` 也可以自定义修改筛选方式
# 也可以添加 `grep -v -E '(fold|tablet|c|xl|tv|watch)' | \` 过滤一些不需要的设备类型?
avdmanager list device | \
grep -E 'pixel' | \
sed -E 's/.*pixel_([0-9]{1,}).*/\1&/' | \
sort -k1,1nr -k2,2r | \
head -n 1 | \
awk -F' or "' '{ print $2 }' | \
tr -d '"' | \
awk '{ print $1 }'
# 将其存储为又臭又长的变量用作安装
DEVIDE_NAME=$(avdmanager list device | \
grep -E 'pixel' | \
sed -E 's/.*pixel_([0-9]{1,}).*/\1&/' | \
sort -k1,1nr -k2,2r | \
head -n 1 | \
awk -F' or "' '{ print $2 }' | \
tr -d '"' | \
awk '{ print $1 }')
echo $DEVIDE_NAME
# 给 android 模拟器起个名字,比如 `pixel_9_pro_xl_Android16_aarch64`
AVD_NAME=${DEVIDE_NAME}_Android16_aarch64
# 假设 AVD 名称作为脚本的第一个参数
# AVD_NAME=${1:-pixel_9_pro_xl_Android16_aarch64} # 如果没有参数,使用默认名称
if [ -z "$AVD_NAME" ]; then
echo "错误:请设置 AVD_NAME 变量或作为参数传递。"
fi
echo $AVD_NAME
# 下载镜像
sdkmanager $SYSTEM_IMAGES_VERSION
# 创建一个新的 AVD pixel_7_pro 或 resizable
echo no | avdmanager create avd \
--force \
--name "$AVD_NAME" \
--package "$SYSTEM_IMAGES_VERSION" \
--device "$DEVIDE_NAME"
# 确认 AVD 已创建
emulator -list-avds
6. 修改 android 模拟器的分辨率,你要是没需求,可以跳过
# 由于我配置了 ANDROID_SDK_HOME 所以配置文件在 $ANDROID_SDK_HOME/.android 中
# 所以假设我们已经确定了 AVD 的配置文件的路径
CONFIG_FILE="$ANDROID_SDK_HOME/.android/avd/$AVD_NAME.avd/config.ini"
echo $CONFIG_FILE
# 校验 CONFIG_FILE 是否存在
if [ -z "$CONFIG_FILE" ] || [ ! -f "$CONFIG_FILE" ]; then
echo "错误:CONFIG_FILE 未定义或文件不存在!"
fi
# =========================================================================
# 函数:检查并设置配置值
# 参数1: 配置键 (例如: hw.lcd.height)
# 参数2: 配置值 (例如: 3120)
# 依赖: CONFIG_FILE 变量必须指向 AVD 的 config.ini 文件
# =========================================================================
set_config_value() {
local key="$1"
local value="$2"
local new_line="${key} = ${value}"
# 检查 key 是否已存在
if grep -q "^${key}" "$CONFIG_FILE"; then
# --- 跨平台兼容性设置 ---
# 检测系统,如果是 macOS (Darwin),则需要 -i '',否则为 -i
if [ "$(uname)" = "Darwin" ]; then
# macOS BSD sed
# 用安全的方式替换整行
sed -i '' "s;^${key}.*;${new_line};" "$CONFIG_FILE"
else
# GNU sed
# 用安全的方式替换整行
sed -i "s;^${key}.*;${new_line};" "$CONFIG_FILE"
fi
if [ $? -eq 0 ]; then
echo "更新配置:$new_line"
else
echo "错误:更新 $key 失败!" >&2
fi
else
# 不存在则追加
echo "$new_line" >> "$CONFIG_FILE"
echo "追加配置:$new_line"
fi
}
# --- 执行配置修改 (与之前相同) ---
echo "开始修改 AVD 配置文件:$CONFIG_FILE"
# 禁用或检查蓝牙(有时蓝牙的虚拟驱动可能影响网络)
set_config_value "hw.bluetooth" "no"
# 检查 Wi-Fi 是否启用(默认通常是 yes)
set_config_value "hw.wifi" "yes"
# 屏幕分辨率
set_config_value "hw.lcd.height" "3120"
set_config_value "hw.lcd.width" "1440"
# 屏幕 DPI
set_config_value "hw.lcd.density" "560"
# 禁用模拟器的边框
set_config_value "showDeviceFrame" "no"
# 其他显示相关设置
set_config_value "hw.lcd.depth" "16"
set_config_value "hw.lcd.vsync" "60"
# 修改内存,通常需要使用后缀 `M` (MB) 或 `G` (GB)不一定生效
# 同时,你可能需要调整 Dalvik/ART 堆大小,你通常需要使用后缀 `M` (MB) 或 `G` (GB)
# 如果你的 RAM 很大,可以相应增加堆大小
# 内存与堆大小关系 2G -> 256M, 4G -> 512M 以此类推
# 2G=2*1024M -> 256M=2*128M
set_config_value "hw.ramSize" "$((4*1024))M"
set_config_value "vm.heapSize" "$((4*128))M"
# 开启音频输出/入
# 确保这两行存在且设置为 yes
set_config_value "hw.audioInput" "yes"
set_config_value "hw.audioOutput" "yes"
# 开启双摄像头
# 如果你希望测试 ARCore 或只是一个虚拟场景:
# hw.camera.back = virtualscene
# hw.camera.front = none
# 配置双摄像头都使用宿主机摄像头 (Webcam0)
set_config_value "hw.camera.back" "webcam0"
set_config_value "hw.camera.front" "webcam0"
# 修改存储器大小
# 32G=32*1024^3B
set_config_value "disk.dataPartition.size" "$((32*1024*1024*1024))"
# 修改存储器路径
set_config_value "disk.dataPartition.path" "$ANDROID_SDK_HOME/.android/avd/$AVD_NAME.avd"
# 让新存储器生效,等待 30s
# 30s 后终止
emulator -avd "$AVD_NAME" \
-wipe-data \
-no-snapshot-load \
-writable-system \
-no-boot-anim \
-no-window \
-no-audio 2>&1 &
sleep 30 && pkill -f 'avd '$AVD_NAME
echo "配置修改完成。请检查"
CONFIG_INFO='
hw.lcd.height
hw.lcd.width
hw.lcd.density
showDeviceFrame
hw.lcd.depth
hw.lcd.vsync
hw.ramSize
vm.heapSize
disk.dataPartition.size
disk.dataPartition.path
hw.audioInput
hw.audioOutput
hw.camera.back
hw.camera.front
hw.bluetooth
hw.wifi
'
echo "--- AVD配置检测报告 ---"
# 关键:通过管道将变量内容逐行传递给 read 命令
echo "$CONFIG_INFO" | grep -v '^[[:space:]]*$' | while read config
do
# 确保 config 非空(排除变量定义开头或结尾的空行)
if [ -n "$config" ]; then
if grep -Eiq "^[[:space:]]*${config}[[:space:]]*=" "$CONFIG_FILE"; then
# 查找并打印参数值
echo "$config: $(grep -E "^[[:space:]]*${config}[[:space:]]*=" "$CONFIG_FILE" | head -n 1 | cut -d '=' -f 2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
else
echo "$config: 未找到"
fi
fi
done
echo "--- 报告结束 ---"
7. 运行 avd android 模拟器,并检查参数是否生效?
# -memory 物理内存分配,如果配置文件未生效,则可以通过参数强制内存大小 8G=8*1024MB
# -no-snapshot-load 确保从干净状态启动
# -no-boot-anim 跳过启动动画
# -port 5555 adb调试端口
# -qemu -netdev user,id=net0,hostfwd=tcp::5555-:5555 通过 -qemu 参数指定转发监听所有网络接口(0.0.0.0)和端口转发(5555)
# -device virtio-net-device,netdev=net0 转发端口所需的网络设备,如果机器/镜像用的是 PCI 网络设备,也可能需要把 `virtio-net-device` 换成 `virtio-net-pci`
# & 允许它在后台运行,释放你的终端
# dns
# -dns-server 8.8.8.8,8.8.4.4 \
# 系统可读写
pkill -f 'avd '$AVD_NAME
emulator -avd "$AVD_NAME" \
-memory $((4*1024)) \
-no-snapshot-load \
-writable-system \
-port 5554 \
-qemu -netdev user,id=net0,hostfwd=tcp::5555-:5555 \
-device virtio-net-device,netdev=net0 &
disown
# 重启端口为全局
adb kill-server
adb devices
adb -s emulator-5554 tcpip 5555
# 综合检查参数启动状况
echo "--- 屏幕 ---"
adb shell wm size
adb shell wm density
echo "--- 内存 ---"
adb shell cat /proc/meminfo | grep MemTotal
adb shell getprop dalvik.vm.heapsize
echo "--- 存储 ---"
adb shell df -h /data
adb shell mount | grep /data
echo "--- 音频 ---"
adb shell dumpsys media.audio_flinger | grep -E "Input|Output"
echo "--- 摄像头 ---"
adb shell ls /dev/video* 2>/dev/null
adb shell dumpsys media.camera | grep -i "Camera"
echo "--- 快照状态 ---"
adb shell getprop | grep snapshot
adb shell getprop | grep fastboot
如果它已停止想要“再运行虚拟机”只需要执行以下命令即可
# 获取虚拟机列表比如得到 'pixel_9_pro_xl_Android16_aarch64'
emulator -list-avds
# 请将 'pixel_9_pro_xl_Android16_aarch64' 替换为脚本中实际的 AVD 名称
AVD_NAME='pixel_9_pro_xl_Android16_aarch64'
# 确保之前启动的实例被关闭
pkill -f 'avd '$AVD_NAME
# 启动虚拟机
# -dns-server 8.8.8.8,8.8.4.4 \
emulator -avd "$AVD_NAME" \
-memory $((4*1024)) \
-no-snapshot-load \
-writable-system \
-port 5554 \
-qemu -netdev user,id=net0,hostfwd=tcp::5555-:5555 \
-device virtio-net-device,netdev=net0 &
disown
# 重启端口为全局
adb kill-server
adb devices
adb -s emulator-5554 tcpip 5555
# 如果创建失败,可能会产生残留,则可以删除失败的 AVDs (如果它们创建了残留文件)
avdmanager delete avd --name $AVD_NAME # 如果存在
# 删除 AVD
avdmanager delete avd --name $AVD_NAME
# 远程连接android,其中将192.168.255.253修改为你的IP
# 甚至可以安装 scrcpy 让局域网连接屏幕
adb kill-server
REMOTE_ANDROID=192.168.255.253:5555
adb connect ${REMOTE_ANDROID}
adb devices
scrcpy -s ${REMOTE_ANDROID} -b 16M --audio-codec=aac
# ===============================================
# 为 AVD 配置全局代理,假定 Sing-box HTTP/SOCKS5 监听端口为 7890
# ===============================================
adb kill-server
REMOTE_ANDROID=192.168.255.253:5555
adb connect ${REMOTE_ANDROID}
adb devices
PROXY_HOST="10.0.2.2" # AVD 私有网关DNS
PROXY_PORT="7890" # 请替换为您的实际端口
# 确保 AVD 已完全启动并连接 ADB
adb -s ${REMOTE_ANDROID} wait-for-device
# 设置全局 HTTP 代理 (适用于大部分 App 和系统服务)
adb -s ${REMOTE_ANDROID} shell settings put global http_proxy $PROXY_HOST:$PROXY_PORT
# 验证设置(可选)
echo "AVD 全局代理已设置为:$PROXY_HOST:$PROXY_PORT"
adb -s ${REMOTE_ANDROID} shell settings get global http_proxy
# ===============================================
# 解除 AVD 全局代理
# ===============================================
REMOTE_ANDROID="192.168.255.253:5555"
# 1. 删除全局代理的核心配置
adb -s ${REMOTE_ANDROID} shell settings delete global http_proxy
# 2. (保险起见) 删除可能残留的独立主机和端口字段配置
adb -s ${REMOTE_ANDROID} shell settings delete global global_http_proxy_host
adb -s ${REMOTE_ANDROID} shell settings delete global global_http_proxy_port
# 3. 验证是否已解除 (输出为空或者显示 "null" 即为成功)
echo "当前代理状态:"
adb -s ${REMOTE_ANDROID} shell settings get global http_proxy
# 4. (强烈建议) 重启设备,确保所有系统服务和 App 的网络缓存被重置
adb -s ${REMOTE_ANDROID} reboot
# ===============================================
# 为 AVD shell 配置 root 权限,并开启系统可读写
# 并以 -writable-system 参数运行虚拟机
# ===============================================
# 获取虚拟机列表比如得到 'pixel_9_pro_xl_Android16_aarch64'
emulator -list-avds
# 请将 'pixel_9_pro_xl_Android16_aarch64' 替换为脚本中实际的 AVD 名称
AVD_NAME='pixel_9_pro_xl_Android16_aarch64'
# 确保之前启动的实例被关闭
pkill -f 'avd '$AVD_NAME
# 启动虚拟机
# -dns-server 8.8.8.8,8.8.4.4 \
emulator -avd "$AVD_NAME" \
-memory $((4*1024)) \
-no-snapshot-load \
-writable-system \
-port 5554 \
-qemu -netdev user,id=net0,hostfwd=tcp::5555-:5555 \
-device virtio-net-device,netdev=net0 &
disown
# 重启端口为全局
adb kill-server
REMOTE_ANDROID=192.168.255.253:5555
adb connect ${REMOTE_ANDROID}
adb devices
# 1. 切换 ADB 到 Root 模式
adb -s ${REMOTE_ANDROID} root
# 2. 禁用 AVB 验证 (对于 Android 16/API 35+ 至关重要)
adb -s ${REMOTE_ANDROID} shell avbctl disable-verification
# 3. 禁用 dm-verity
adb -s ${REMOTE_ANDROID} disable-verity
# 4. 禁用验证后,必须重启设备才能生效。
adb -s ${REMOTE_ANDROID} reboot
adb kill-server
REMOTE_ANDROID=192.168.255.253:5555
adb connect ${REMOTE_ANDROID}
adb devices
# 5. 再次获取 Root 权限 (重启后会丢失,需重新获取)
adb -s ${REMOTE_ANDROID} root
# 6. 执行 Remount (这是最关键的一步)
adb -s ${REMOTE_ANDROID} remount
现在我终于可以好好的看片了
Comments
Post a Comment