强制安卓模拟器将更改保存到/system目录

28

我知道在使用Android模拟器时这是一个常见的问题,但是否有一种方法可以强制模拟器接受对/system的持久更改?

由于模拟器基于QEMU,因此理论上应该可以强制系统镜像表现出与userdata相同的方式,但我不熟悉QEMU如何处理。有什么建议吗?


实际上,即使是本地系统映像(在我的AVD目录中)也没有在最新版本的模拟器中持久化...除非我做错了什么? - F.X.
看看Yury的答案,也许可以看看我的另一种方法(我昨天刚发现)。你可以使用adb remount来更改/system,但如果您重新启动模拟器,更改将不会保存,这正是我所需要的。 - F.X.
1
谢谢!我最初找到解决方案的博客最近已经关闭了。我肯定需要一个新的参考。 ;) - class stacker
请仅查看此帖子 https://dev59.com/EmUp5IYBdhLWcg3wPFtK#58935109 - Rasoul Miri
10个回答

17

目前(使用Build Tools v26的情况下,如果Google不像他们经常那样改变东西)如果您在从命令行启动模拟器时使用-writable-system指令,它将允许通过重新启动将持续性保留到/system分区。也就是说,您将能够写入/system分区,如果您重新启动,更改仍将得到维护。

emulator -avd <AVD_NAME> -writable-system

这也将使您的更改持久化到一个qcow2映像文件中,通常保存在.android/avd/<AVD_NAME>.avd/system.img.qcow2

您甚至可以复制此system.img.qcow2文件,使用-wipe-data指令擦除AVD上的数据,将此文件放回目录中,然后重新启动,最初所做的系统更改仍将被保留。(警告:至少目前为止,因为谷歌一直在改变事情)


1
感谢您保持更新 :) - F.X.
1
文件仍然被更改,但根目录未激活。您是否有最新构建工具的永久根解决方案? - Cristian Holdunu
“-wipe-data” 命令无效,还有如何调整系统分区大小? “-partition-size” 也不起作用,显示无效命令(已删除?) - user25
这个方法可行,但请注意它会将数据写入一个独立的qcow2文件而不是直接写入.img文件中:https://android.stackexchange.com/questions/110927/how-to-mount-system-rewritable-or-read-only-rw-ro/207200#207200 - Ciro Santilli OurBigBook.com
5
重要提示:为了看到您之前的持久更改,您需要继续使用“-writable-system”选项。省略“-writable-system”将使用默认的系统映像,不包含您的更改。 - Arseny Levin

15

更新:最近的QEMU版本中似乎已经删除了-nand选项,因此以下内容可能不再适用。

更新:请查看被接受的答案以获取当前的操作方式。


Yury的回答很普遍,但如果您想在最终进行脚本编写(这正是我所需要的),您需要能够在/tmp目录中找到模拟器映像。

我发现您可以覆盖QEMU的行为。这有点hackish,但它有效,所以我最终做了以下事情:

  1. system.img从平台目录复制到AVD目录中。
  2. 将所需的空间转换为十六进制。例如,如果你需要500M,则为0x1f400000
  3. 以读写模式运行模拟器:

    emulator -avd Galaxy_Nexus -qemu -nand system,size=0x1f400000,file=/home/fx/.android/avd/Galaxy_Nexus/system.img
    

    (如果你将模拟器设置为详细模式,你会注意到它默认使用initfile=而不是只用file=

  4. 做出你的更改,它们会立即保存到本地的system.img

  5. 现在你可以使用emulator -avd Galaxy_Nexus来启动模拟器,它将使用你的更改

更新: 如果使用脚本,QEMU不会立即将更改同步到映像中。因此,如果你在更改后立即重启,很可能会丢失数据。我正在寻找一种方法来解决这个问题...

下一个更新: 使用adb -e emu kill停止模拟器。使用reboot会导致不良后果。


1
嘿,伙计,这真是一个非常棒的技巧!我根本不知道可以在读写模式下启动模拟器。到现在为止,我一直在尝试使用yaff2来动态创建镜像,但你的答案使事情变得更加容易。我现在在Scala Libs for android installation script 的最新版本中使用了你的机制。非常感谢。 - sven
谢谢!很遗憾安卓团队没有添加这个选项,而是要用一些奇怪的QEMU选项来完成...(顺便说一句,我将采纳答案设置为我的,因为我们在最新的sbt-android插件中使用它,在一个简单的步骤中非常有效地设置了模拟器!) - F.X.
1
qemu-system-x86_64: -nand: 无效选项 — 这意味着他们删除了支持该操作的功能? - Display Name
你在哪里找到这些命令的?system,size=0x1f400000 我尝试使用 https://developer.android.com/studio/run/emulator-commandline#startup-options 中的 -partition-size 命令来更改系统分区大小,但它不再起作用了(而且他们没有更新网站上的信息)... - user25
这个值是多少字节?0x1f400000,524288000 等于 500MB,对吗? - user25
我通过快速翻阅qemu手册中的有趣部分找到了它们。不过,那是一篇比较长的阅读 :) - F.X.

8

这其实是一个非常好的问题,我也曾经遇到过同样的麻烦。以下是我的发现。我使用Ubuntu,并将描述Ubuntu的步骤。如果您使用Windows,则应更改路径。

  1. 创建新的AVD,例如example.avd
  2. android-sdk-linux/platforms/android-10/images复制system.img~/.android/avd/example.avd
  3. system.img设置为可写和可读(可以在属性中或直接使用终端)
  4. 使用命令emulator -avd example运行您的AVD
  5. 使用adb shell重新挂载您的系统为rw:mount -o rw,remount -t yaffs2 /dev/block/mtd0 /system(使用命令cat /proc/mtd查找分区)
  6. 进行更改...
  7. 现在,在模拟器运行期间,在/tmp/android-<your_computer_name>中找到临时模拟器,名称类似于:emulator-PQ7LgE,并将其复制到~/.android/avd/example.avd
  8. 删除system.img并将复制的临时模拟器重命名为system.img
  9. 关闭模拟器
  10. ~/.android/avd/example.avd中删除cache.imguserdata.imguserdata-qemu.img
  11. 再次运行您的模拟器

祝好运!


感谢您提供详细的答案,现在我不知道该选择哪一个了 ;) - F.X.
-1 '将system.img设置为可读写(可以在属性中设置,也可以使用终端命令)' 需要更多细节... - Shmil The Cat

2

方案#2令人惊叹。

如果您使用的是MS Win作为主机,请注意以下提示: AVD目录位于下面,但应使用“短”路径名作为file=path参数。由于某种原因,带引号的路径变体无法工作。

Win XP: C:\Documents and Settings\ (用户名) \ .android\avd\ ... 短路径:C:\DOCUME~1\ (用户名) \ANDROI~1\avd\ ...

Win 7: C:\Users\ (用户名) \ .android\avd\ ...

您可以按照以下示例创建自己的批处理文件,例如“startrw.bat”:

@echo off
C:\<ADTFOLDER>\sdk\tools\emulator -avd <AVDNAME> -qemu -nand system,size=0x1f400000,file=C:\DOCUME~1\<USERNAME>\ANDROI~1\avd\<AVDNAME>.AVD\system.img
cd C:\<ADTFOLDER>\sdk\platform-tools
echo .
echo Wait ... 
echo .
echo When emulator is FULLY loaded press any key to connect adb shell to it
echo To make /system writeable type in adb shell:
echo .
echo -----------------------------
echo mount -o rw,remount /system 
echo -----------------------------
echo .
echo You can use the Eclipse ADT DDMS File Browser to browse or push-pull files now.
echo .
echo Closing this window closes the emulator ! 
echo .
echo Wait emulator to load Android. When done
pause
C:\<ADTFOLDER>\sdk\platform-tools\adb shell

这样可以一键加载。修改完成后,只需关闭当前命令窗口以关闭模拟器。

大多数事情需要很长时间才能加载,比如模拟器、ADT编辑器、Hooking DDMS文件浏览器(您需要点击左侧的模拟器行才能在右侧窗口中看到文件树)等等。


2

我在寻找F.X.提到的system.img文件和AVD目录时遇到了麻烦。在Mac上,您可以在以下位置找到它们:

  • system.img: ~/Library/Android/sdk/system-images/android-19/default/
  • AVD目录: ~/.android/avd/Nexus.avd/

由于我的声望不够高,无法将其添加为评论,因此只能以这种方式发布。抱歉。


1
在终端中使用此命令。
cd /Users/NAME_USER/Library/Android/sdk/emulator # Move to emulator folder
sudo ./emulator -writable-system -avd NAME_AVD -partition-size 280 # Run avd by writable system 
sudo adb root # Change to root
sudo adb remount # remount again
sudo adb shell 
su
mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system 

更改 NAME_USER 和 NAME_AVD


无法工作。adbd不能在生产构建中以root权限运行。 - e-info128

0

F.X.的答案在我使用的Windows上的Android API 19和21版本中无法正常工作。根据给定的参数,无法实现预期效果。

emulator -avd <AVD> -qemu -nand system,size=0x<SIZE IN HEX>,file=<PATH/TO/system.img>

系统无法挂载镜像。通过查看内核输出,我发现它使用了可疑的页面大小(2048)和两个非零参数值:额外大小和“擦除”。这些参数在任何地方都没有记录,但是您可以在qemu的源代码中看到它们。最终对我有用的是

emulator -avd <AVD> -qemu -nand system,size=0x<SIZE IN HEX>,file=<PATH/TO/system.img>,pagesize=512,extrasize=0

通过指定这些参数,“erase”也被设置为0。

我也很惊讶地发现,使用这些参数后,系统无法启动到图形环境,但adb可以正常工作。


你在哪里找到了那些命令(例如 systemsize)?文档在哪里? - user25
值应该是以字节或兆字节为单位? - user25

0

做到这一点的最佳方法是使用以下命令:

<path-to-emulator-executable> -avd <AVD> -partition-size 512

你可能需要执行 ./emulator 或者 emulator-x86。基本上,将 emulator 替换为你的模拟器可执行文件的路径。 - user6754053

0

-1
新年新方案。 将 system.img 复制到您的 avd 文件夹中,并将其重命名为 system-qemu.img。
对我来说,将 C:\Android\sdk\system-images\android-22\android-tv\armeabi-v7a\system.img 复制到 C:\Users\Neil Agarwal\.android\avd\Android_TV_1080p_API_22.avd\将其重命名为 system-qemu.img就可以了。
请在此之后重新启动您的 avd。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接