菜单

模块开发

相关源文件

本指南涵盖 Magisk 模块的开发——这些组件允许开发者修改 Android 系统行为和文件,而无需永久性地更改底层系统分区。有关安装 Magisk 本身或从源代码构建 Magisk 的信息,请参阅 从源代码构建安装

概述

Magisk 模块通过受控的文件覆盖系统、自定义脚本、系统属性修改和代码注入功能,提供了强大的自定义 Android 设备的框架。本文档将详细介绍如何创建、打包和分发 Magisk 模块。

模块架构

来源: docs/guides.md16-79 docs/details.md38-74

模块结构

Magisk 模块是一个位于 /data/adb/modules 的文件夹,具有特定的结构。文件夹名称对应模块的唯一 ID。

/data/adb/modules
├── $MODID                  <--- The folder is named with the ID of the module
│   │
│   │      *** Module Identity ***
│   │
│   ├── module.prop         <--- Stores the metadata of the module
│   │
│   │      *** Main Contents ***
│   │
│   ├── system              <--- Files to be overlaid on /system
│   │   ├── ...
│   │   ├── ...
│   │   └── ...
│   │
│   ├── zygisk              <--- Zygisk native libraries for code injection
│   │   ├── arm64-v8a.so
│   │   ├── armeabi-v7a.so
│   │   ├── riscv64.so
│   │   ├── x86.so
│   │   ├── x86_64.so
│   │   └── unloaded        <--- Indicates incompatible libraries
│   │
│   │      *** Status Flags ***
│   │
│   ├── skip_mount          <--- If exists, system folder won't be mounted
│   ├── disable             <--- If exists, module will be disabled
│   ├── remove              <--- If exists, module will be removed next reboot
│   │
│   │      *** Optional Files ***
│   │
│   ├── post-fs-data.sh     <--- Executed in post-fs-data stage
│   ├── service.sh          <--- Executed in late_start service stage
│   ├── uninstall.sh        <--- Executed when module is removed
│   ├── action.sh           <--- Executed when action button is clicked in app
│   ├── system.prop         <--- Properties loaded as system properties
│   ├── sepolicy.rule       <--- Custom sepolicy rules
│   │
│   │      *** Auto Generated Symlinks ***
│   │
│   ├── vendor              <--- Symlink to $MODID/system/vendor
│   ├── product             <--- Symlink to $MODID/system/product
│   ├── system_ext          <--- Symlink to $MODID/system/system_ext

来源: docs/guides.md19-77

module.prop

module.prop 文件以严格的格式定义了模块的元数据

id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
updateJson=<url> (optional)

要求

  • id 必须匹配正则表达式:^[a-zA-Z][a-zA-Z0-9._-]+$
  • versionCode 必须是整数
  • updateJson URL 提供 JSON 格式的更新信息
  • 所有字段必须是单行字符串
  • 使用 UNIX (LF) 行尾符

更新 JSON 格式

来源: docs/guides.md79-110

模块安装流程

模块安装程序结构

Magisk 模块安装程序是一个 zip 文件,可以通过 Magisk 应用或自定义 Recovery 来刷入。最小结构是:

module.zip
│
├── META-INF                           <--- Only needed for flashing in recovery
│   └── com
│       └── google
│           └── android
│               ├── update-binary      <--- The module_installer.sh script
│               └── updater-script     <--- Should only contain "#MAGISK"
│
├── customize.sh                       <--- Optional customization script
│
├── ...                                <--- Module files
├── ...

来源: docs/guides.md141-165 scripts/module_installer.sh1-34

安装流程

来源: scripts/util_functions.sh634-739 scripts/module_installer.sh1-34

自定义脚本

customize.sh 脚本允许自定义安装过程。在文件解压后,安装程序会调用它。

可用变量

  • MAGISK_VER:Magisk 版本字符串(例如:v20.0
  • MAGISK_VER_CODE:Magisk 版本代码(例如:20000
  • BOOTMODE:如果在 Magisk 应用中安装,则为 true
  • MODPATH:模块文件安装的路径
  • TMPDIR:安装的临时目录
  • ZIPFILE:模块 zip 文件的路径
  • ARCH:CPU 架构(arm, arm64, x86, x64, 或 riscv64
  • IS64BIT:如果 $ARCH 是 64 位,则为 true
  • API:Android API 级别

可用函数

  • ui_print <msg>:将消息打印到控制台
  • abort <msg>:打印错误消息并终止安装
  • set_perm <target> <owner> <group> <permission> [context]:设置权限
  • set_perm_recursive <dir> <owner> <group> <dirperm> <fileperm> [context]:设置递归权限

您可以使用 REPLACEREMOVE 变量指定要替换或删除的目录

要完全控制安装过程,请在 customize.sh 中设置 SKIPUNZIP=1,以便自行处理解压。

来源: docs/guides.md168-235

模块功能

系统修改

system 文件夹是大多数模块的核心,包含要覆盖到真实 /system 分区的文件。覆盖过程遵循以下规则:

  1. 模块 system 文件夹中的文件会替换真实系统中的同名文件
  2. 新文件将被添加到系统中
  3. .replace 文件放在目录中将替换整个目录,而不是合并
  4. 要删除文件/文件夹,请使用 mknod <path> c 0 0 创建一个虚拟字符设备

例如,替换 YouTube 应用

module/system/app/YouTube/.replace
module/system/app/YouTube/YouTube.apk

移除系统应用

# In customize.sh
mknod $MODPATH/system/app/Bloatware c 0 0

来源: docs/guides.md122-127

启动脚本

模块可以在启动过程的两个阶段运行脚本

  1. post-fs-data 模式post-fs-data.sh

    • 阻塞执行(暂停启动长达 40 秒)
    • 在挂载模块之前运行
    • 在 Zygote 启动之前执行
    • 警告:使用 setprop 会导致启动死锁;请改用 resetprop -n
    • 仅在绝对必要时使用
  2. late_start service 模式service.sh

    • 非阻塞执行(与启动并行运行)
    • 推荐用于大多数脚本

所有启动脚本都在 Magisk 的 BusyBox ash shell 中运行,并启用了“独立模式”。

在脚本中,使用 MODDIR=${0%/*} 来获取模块的基础目录路径。如果启用了 Zygisk,则环境变量 ZYGISK_ENABLED 将设置为 1

来源: docs/guides.md114-117 docs/guides.md244-270

系统属性

system.prop 文件允许模块修改系统属性。每行都遵循 key=value 格式,类似于 build.prop

示例

# Disable signature verification
ro.secure=0
ro.debuggable=1

属性由 Magisk 的 resetprop 工具加载,该工具甚至可以修改只读属性。

来源: docs/guides.md134-136

SELinux 规则

可以通过 sepolicy.rule 文件添加自定义 SELinux 策略规则。每行都是一个策略语句,由 magiskpolicy 处理。

示例

allow appdomain app_data_file file { read write open getattr }
allowxperm untrusted_app self capability_service_ipc ioctl 0x0000

来源: docs/guides.md138-140 docs/tools.md156-232

Zygisk 集成

Zygisk 允许模块在每个 Android 应用进程内部运行代码。对于 Zygisk 支持:

  1. 实现所有支持架构的 Zygisk API 的原生库
  2. 将编译好的共享库放在 zygisk 文件夹中,并使用适当的名称
    • arm64-v8a.so
    • armeabi-v7a.so
    • riscv64.so
    • x86.so
    • x86_64.so

当 Zygisk 模块不兼容时,在 zygisk 目录中创建一个名为 unloaded 的空文件。

来源: docs/guides.md129-132

最佳实践

模块设计

  1. 遵循最小修改原则:

    • 仅修改必需的部分
    • 目标是特定文件,而不是整个目录
    • 谨慎使用 .replace
  2. 正确处理权限:

    • 为文件使用 set_permset_perm_recursive
    • 二进制文件通常需要 0755 权限
    • 系统应用需要正确的 SELinux 上下文
  3. 脚本优化:

    • 大多数操作使用 service.sh
    • 仅在绝对必要时才使用 post-fs-data.sh
    • 保持脚本高效,以避免启动延迟
  4. 跨设备兼容性:

    • 检查特定于设备的路径
    • 通过 API 检查处理多个 Android 版本
    • 支持所有处理器架构

常见陷阱

  1. 启动循环原因:

    • 修改关键系统文件
    • SELinux 上下文问题
    • 权限问题
    • 启动脚本中的无限循环
    • 启动期间资源密集型操作
  2. 安装错误:

    • 硬编码路径而非使用变量
    • 未处理不同的 Android 版本
    • 缺少架构支持
    • 未清理临时文件
  3. 更新问题:

    • 未保持向后兼容性
    • 更改模块 ID
    • 未提供卸载功能

来源: docs/guides.md1-15 docs/faq.md1-17

示例模块结构

这是一个结构良好的 Magisk 模块的完整示例

example_module/
├── META-INF/
│   └── com/
│       └── google/
│           └── android/
│               ├── update-binary           # module_installer.sh script
│               └── updater-script          # Contains only "#MAGISK"
├── customize.sh                            # Custom installation logic
├── module.prop                             # Module metadata
├── post-fs-data.sh                         # Early boot script (if needed)
├── service.sh                              # Main boot script
├── system.prop                             # System properties to modify
├── sepolicy.rule                           # SELinux policy rules
├── system/                                 # System modifications
│   ├── app/
│   │   └── ModifiedApp/
│   │       ├── .replace                    # Replace entire directory
│   │       └── ModifiedApp.apk             # Replacement APK
│   ├── bin/
│   │   └── custom_binary                   # Added binary
│   └── etc/
│       └── custom_config                   # Configuration file
├── zygisk/                                 # Zygisk support (optional)
│   ├── arm64-v8a.so                        # Architecture-specific libraries
│   ├── armeabi-v7a.so
│   ├── x86.so
│   └── x86_64.so
└── uninstall.sh                            # Cleanup when module is removed

来源: docs/guides.md16-141

模块安装和管理

安装方法

可以通过以下方式安装模块:

  1. Magisk 应用:安装模块的推荐方式

    • 导航到“模块”部分
    • 点击“从存储安装”
    • 选择模块 ZIP 文件
  2. 自定义 Recovery:传统方法(不推荐用于现代设备)

    • 将模块 APK 重命名为 ZIP
    • 通过自定义恢复刷入
    • 重启

模块生命周期

来源: docs/guides.md16-77 scripts/util_functions.sh634-739

结论

Magisk 模块提供了一个强大的框架,可以在不进行永久性系统修改的情况下定制 Android 设备。在开发模块时,请关注

  1. 正确的结构和元数据
  2. 干净的安装和卸载
  3. 高效且兼容的系统修改
  4. 适当的脚本执行时机
  5. 跨设备的全面测试

遵循这些指南,您可以创建能够增强 Android 功能同时保持系统稳定性和安全的模块。