Android Virtual Devices(AVD) root/Magisk/xposed

在 windows 下操作,终端使用 powershell。

旧系统(如 4.4 kitkat)+ supersu

主要参考文章:搞机:AS自带模拟器AVD Root 和 Xposed安装

旧系统可以安装 supersu + 旧版本 xposed。

  1. 在 as 中查询 sdk 目录位置(一般在 %localappdata%\Android\Sdk),将其中的 platform-toolstools 加入系统变量 path 中(一般来说,前者包含有 adb.exe,大多数人都已经加了。后者包含有 emulator.exe,大多数人没加但待会要用,如果不想加进去的话用这个命令的时候带上路径也可以;另外 emulator.exe 在 %localappdata%\Android\Sdk\emulator 下也有一份,有时候高版本安卓要用 emulator 目录的打开才行。可以先用 emulator 命令带上路径启动虚拟机看看)

  2. 查询要 root 的虚拟机名字

    1
    emulator -list-avds

    以可读状态启动虚拟机(启动后这个终端窗口就别关了,后面的操作新建一个新终端窗口)

    1
    emulator -avd [刚刚查到的虚拟机名字] -writable-system
  3. 解除 selinux

    1
    2
    3
    4
    5
    6
    adb root
    adb remount
    adb shell
    # 这里进入到虚拟机那边的 shell 中
    > setenforce 0
    > exit
  4. 替换 su。需要获取对应的 su.pie。获取方法有这么几个:

    • 文章里面有百度网盘,提取码 cg08,网盘里面有个压缩包,解压待用。
    • github 的某个项目 meefik/avd-root。同样是里面的压缩包,版本还比较新。值得一提的是这个其实是个 avd 一键 root 工具,但脚本适用于 shell,但应该是 linux 下使用的或者在虚拟机 sdcard 内展开然后用 adb shell 进去,总之我不太明白怎么用。。。
    • 编译。这个我有疑问,也挺麻烦,所以后面说。

    将其中的两个 su.pie 用 adb push 到相应位置。如果是通过前两个方法,解压后进入文件夹中运行终端,然后输入:

    1
    2
    3
    4
    5
    6
    adb push .\x86\su.pie /system/bin/su
    adb push .\x86\su.pie /system/xbin/su
    chmod 0755 /system/bin/su
    chmod 0755 /system/xbin/su
    su --install
    su --daemon&
  5. 再新建终端窗口。这次是装软件,要装 supersu 的管理器和 xposed 管理器。supersu 同样在上面前两个获取项目中有。如果你的模拟器用的是 5.0-8.0 版本,那上面的 xposed-framework 也能用。但这是旧系统,也就是 4.4,就需要用更低版本的,不好找,在这个帖子:Xposed for android 4.4.4 is NOT fixed, please compile 87v for sdk19 里这里找到一个能用的:Xposed 2.7.1 by Sola Warez.apk。另外 4.4 版本 avd 没有文件管理器,也得装一个;装一个钛备份测试 root 结果,等等等等。可使用 adb install 命令安装,以 supersu 和 xposed 为例:

    1
    2
    adb install .\SuperSU-v2.82-SR5.apk
    adb install .\Xposed_2.7.1_by_Sola_Warez.apk
  6. 此时打开钛备份就会弹出 root 提示了。注意打开 supersu 会提示你更新 su 文件,不要点击确认,不管它,点击 cancel 即可。

  7. 如果要重启就比较麻烦。文章建议用 adb reboot 但亲测无效。另外两个方法是使用 xposed 软重启和直接通过 gui 进行软重启。重启后可能还需要再运行一次 su --daemon&。关闭的话,不要通过 gui 的电源关机,直接点右上角的 x 让 avd 保存快照就好了。但未来启动仍然需要通过 emulator 命令启动而不是通过 avd gui 直接启动。

其他参考资料

  • How to get root access on Android emulator? 这里似乎给出了固化 root 的方法。
  • Rooting the Android Studio AVDs 这是另一个教程,补充了重启后失效的内容。
  • su.pie 编译方法获取:[原创]学习Androidx86模拟器root安装xposed。这同时也是另一个教程。不过看得我有些云里雾里:编译时应该用 supersu 项目的代码还是安卓源码?如果是安卓源码那就有点麻烦了。。。安卓源码非常大,需要谷歌的专门 cli 工具(基于 git 开发的)下载还要先下载一个 30g 的 base 包;然后再下载相应分支(系统版本)的代码。。。但看这篇教程,好像只编译了部分代码?但要获取部分代码也很麻烦:谷歌将不同组件分散在一大堆库中,你得找到相应的库才有对应的文件(当然,在网页端点开相应的库,没点错的话就会直接让你选择系统分支了)。而且貌似对应源码目录的结构还和教程中的结构不太一样(少一个 mk 文件),所以我倾向于编译 supersu 的源码。更多关于安卓源码下载的文章:
  • 第三方 su 生效原理
  • 听说该方法不能用在 google play 版本系统中(待验证)

新系统(android 10)+ magisk

先给两篇参考文章,分别代表了两种思路:

建议使用第一种。第二种需要手工编译并下载 sdk,操作繁琐的多。唯一的好处就是不用放修改后的 ramdisk.img 到 sdk 镜像里面。

第一种方法

  1. 到第一篇参考文章中,将整个项目拖下来(git clone / 直接下载源码压缩包)。

  2. 查询虚拟机名字后(见上文),启动虚拟机。

    1
    emulator -avd [刚刚查到的虚拟机名字]
  3. 找到 sdk 目录下的 system-images 文件夹,在你所启动的对应版本系统文件夹里面找到 ramdisk.img ,先在原地复制并粘贴(为了保留一份副本),再将该文件拷到项目文件夹中。

  4. 确认虚拟机和 adb 正常启动并运行的情况下,运行项目文件夹中的 patch.bat

  5. 运行完毕后将项目文件夹中的 ramdisk.img 拷回 system-images 对应版本系统文件夹中覆盖,关闭虚拟机并进行冷启动即可。

拓展

  • 本方法是关键文件是项目文件夹里面的 magisk_emu.zip。这个 zip 其实和官网 release 下载到的不同版本 magisk zip recovery 安装包是一个性质的东西。不同的地方在于,存在于项目文件夹的这个文件是 debug 版本的,文件大小要比 release 版大一倍。

  • 也正因如此,如果要升级 magisk / 使用 release 版本,替换这个 magisk 文件然后走一下 3~5 步即可。

  • 不直接运行 patch.bat,而是在 powershell 中运行,能查看到运行日志。release 版的压缩包,运行起来会会多显示一句

    1
    run-as: package not debuggable: com.topjohnwu.magisk

    也明显能感觉到 patch.bat 使用 release 包时比 canary 包慢。

  • 阅读文档,patch.bat 还能跑一个 canary 的参数。其实只是改为在线获取而已。

  • 使用 release 版本,附带的 magisk manager 有可能因为某些原因(版本过旧[^1]/网络太差[^2])无法正常识别所安装的 magisk。覆盖安装最新版的 magisk manager 可解(在目前这个时间点,release 版本低于 v20.3 用的都是旧版 ui 客户端,基本都会报错;v20.4 虽然已经用了新版 ui 客户端但还是报错,只有 v21.0 不需要覆盖装 manager 本身就正常)。

  • (软件兼容性问题) 非 google play rom 版本下钛备份无法正常使用,获取不到 root。原因是钛备份读取的是 /system/xbin/su,而用上面方法整出来的 magisk,生效文件在 /sbin/su。用 Root Checker Pro 就能发现问题,supersu 能够读取处 su 版本。

    magisk 这里就会显示有问题。

    实机 magisk 因为 /system/xbin/su 处没有文件,所以钛备份就才会读取 /sbin/su。那虚拟机这里怎么会有文件呢?原来这里的 /system/xbin/su 是给 adb 用的。。。

    解决方法,给一个硬连接。

    1. 先用可读 system 和 selinux 宽松模式启动虚拟机

      1
      emulator -avd [刚刚查到的虚拟机名字] -writable-system -selinux permissive
    2. remount adb 的 su

      1
      2
      adb root
      adb remount
    3. 给上硬连接。

      1
      ln -sf /sbin/su /system/xbin/su

      即可。重启不影响效果。和修改前的区别就是以后使用 adb root 时需要在系统内的 magisk 弹窗确认。

  • (系统兼容性)经测试不存在该问题。是否 google play 版本不影响 magisk 生效。另外 google play 版本不需要解决软件兼容性问题,因为本身就不运行在 adb 内运行 root,也就不会有 /system/xbin/su 的存在。

第二种方法

简单提一下,主要是编译坑多。编译步骤还可以看一下 magisk 项目 底下说明,参考文章里面用的是最新版的编译方法,旧一点的版本(低于 v21.0) build.py 里面就没有 ndk 的编译选项。如果要编译旧版本,可以从 magisk 项目切换到旧版本的 tag 就能在底下看到旧版本的对应说明了。

  1. 克隆项目。项目所在目录首选你系统的用户目录,其次是驱动器盘根目录(如果你的用户名是中文的话)。切记别放在路径有中文的目录中。

    1
    git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git
  2. 安装 jdk8,python 3.6,设置好 path,另外旧版本 magisk 需要设置 ANDROID_HOME 这个用户变量;而新版本 magisk 需要设置 ANDROID_SDK_ROOT 这个用户变量。两个用户变量都是指向 sdk 目录的。

  3. 装个 colorma。或者删掉 colorma 在 build.py 中的依赖代码(显示个代码颜色,不用不会死)。

    1
    pip install colorama
  4. 将文件 config.prop.sample 复制并改为 config.prop。修改内容,要修改的内容类似于下面这两串代码。(其实是成功安装后在 magisk manager 里面显示出来的版本号,都自己编译了,别按下面模板改,该非亿点就非一点)

    1
    2
    3
    4
    5
    6
    7
    # The version name and version code of Magisk
    version=20.4
    versionCode=20400

    # The version name and version code of Magisk Manager
    appVersion=7.5.1
    appVersionCode=267
  5. 开始编译

    1
    2
    python build.py ndk
    python build.py all

    可能会有很多报错坑,类似下 ndk 压缩包的时候网络慢报错(挂代理);

    类似编译 ndk 的时候出现

    1
    'gbk' codec can't decode byte 0x8b in position 79: illegal multibyte...

    这个需要修改 build.py 的相关位置,类似于

    1
    125     with open(file, 'r') as f:

    改成

    1
    125     with open(file, 'r',encoding='utf-8') as f:

    (话说回来这个错误在我把项目放在 c 盘根就出现了,放在用户目录就不会出现)

    还有编译 all 的时候出现

    1
    windows javax.net.ssl.SSLException

    这个得挂代理。

    等等等。

  6. 一顿操作

    1
    2
    3
    4
    5
    6
    7
    8
    adb root
    adb push native\out\x86\busybox scripts\emulator.sh /data/local/tmp
    adb push native\out\x86\magiskinit64 /data/local/tmp/magiskinit
    adb shell "mkdir -p /data/adb/magisk"
    adb shell "cp /data/local/tmp/busybox /data/adb/magisk/"
    adb push scripts\util_functions.sh /data/adb/magisk/

    adb shell sh /data/local/tmp/emulator.sh
  7. 验证一下

    1
    adb shell "ps -ef | grep -i magisk"

    出现

    1
    root  ..... 00:00:00 magiskd
  8. 然后装 magisk manager 就行了。

拓展

  • 这个方法也会生成一个 zip 文件,也是个典型的 magisk.zip 文件。但这个 magisk-debug.zip 放到方法 1 里面用,用 Root Checker Pro 检查,su 参数正确但 root 确认框一闪而过,没法正常使用。。。
  • 这个方法同样有钛备份的兼容问题,解决方法同上。

[^1]: 让模拟器 magisk 正常运行的 emulator.sh 放出时间不早于 v20.0。
[^2]: 让 magisk 网络功能在大陆能够比较畅快使用 cdn 功能的客户端大概版本也不低于 8.0。