MAML 背屏主题开发技能
小米背屏(后盖屏/小屏)主题开发完整技能包,基于多主题实战 + 反编译破解验证。
何时使用
- 用户要求创建/修改小米背屏主题(开机动画、桌面、时钟、充电动画等)
- 需要把 HTML/WebView 内容加载到背屏
- 需要读取系统数据(存储/电量/步数/开机时长)显示在背屏
- 需要在背屏点击图标唤起安卓应用
- 需要 AOD 息屏显示、摄像头避让、多机型适配
核心能力
- WebView 加载 HTML 到背屏:manifest.xml 用
<WebView>元素,本地 HTML 放 web/ 目录 - 摄像头避让:左侧 277px 摄像头区,内容用
left:29vw安全区,背景可全屏 - MAML 系统变量传递:ContentProviderBinder 读存储/步数,
window.maml.getDoubleByName在 HTML 里读取 - HTML 唤起安卓应用:
window.maml.doAction('xxx')触发 WebView 内<Triggers><Trigger action="xxx">的 IntentCommand(反编译破解) - AOD 息屏 HTML 侧实现:MAML
enterAod → RUNJS __setAod(1)通知 HTML 切 AOD 画面(不能用 MAML<Aod>元素) - XP 桌面交互:窗口拖动、显示桌面、托盘点击、开始菜单等
目录结构
skill-docs/ # 详细技能文档(19 篇)
├── 00-搜索索引.md # AI 优先读取:关键词→文件映射
├── 基础语法/ # 变量、UI、命令、动画
├── 实战技巧/ # 机型适配、AOD、WebView、踩坑
├── 进阶主题/ # GL、摄像头、日程、电池
└── 配置规范/ # var_config、description.xml
快速开始(AI 工具用)
- 先读
skill-docs/00-搜索索引.md定位关键词 - 新建主题:读
实战技巧/14-背屏Web主题-AI创作规范.md+15-精华速览与黄金标准.md - WebView 主题:读
实战技巧/12-WebView加载HTML到背屏.md - 完整示例:读
实战技巧/13-HTML背屏主题完整示例-星舰矩阵时钟.md - 安装测试:
miroot_theme_test_install优先 Hook 直接安装(directApply=true,仅 root+模块生效,失败自动回退替换流程);替换流程为替换 AI 文件夹主题 + 跳转主题设置手动应用,不重启背屏
关键速查
摄像头避让(absolute 布局)
.safe{position:absolute;left:29vw;top:0;right:0;bottom:0} /* 内容安全区 */
.wp{position:fixed;left:0;top:0;width:100vw;height:100vh} /* 背景全屏 */
HTML 唤起应用(doAction 机制)
<WebView name="wv" ...>
<Triggers>
<Trigger action="launch_app">
<IntentCommand action="android.intent.action.MAIN" package="xx.xx" class="xx.xx.Activity"/>
</Trigger>
</Triggers>
</WebView>
window.maml.doAction('launch_app'); // ⚠️ Trigger 必须在 WebView 元素内,不是 ExternalCommands!
AOD 息屏(HTML 侧)
<Trigger action="enterAod"><WebViewCommand target="wv" command="runjs" params="'__setAod(1)'"/></Trigger>
<Trigger action="exitAod"><WebViewCommand target="wv" command="runjs" params="'__setAod(0)'"/></Trigger>
window.__setAod = function(v){ v===1 ? $('#aod').classList.add('show') : $('#aod').classList.remove('show'); };
AOD 居中(避开摄像头后右侧剩余区域居中)
用户说 "右侧居中 / 水平居中 / 垂直居中 / 整体居中" = 避开左侧摄像头避让区后,右侧剩余区域内居中,不是全屏居中、也不是屏幕右半区居中。
var availL=SAFE+2, availR=W-8, availW2=availR-availL; /* SAFE=0.30W 摄像头避让 */
var tx=availL+availW2/2; /* 水平:剩余区域居中 */
/* 垂直:整体块居中用固定线高模型(禁止 measureText 纵向度量——WebView 粗体大数字返回异常) */
var OFFSET=0, timeLH=tf*1.0, dateLH=df*1.0, gap=Math.max(2,Math.round(FS*0.12));
var blockH=timeLH+gap+dateLH, blockTop=(H-blockH)/2+OFFSET;
var ty=blockTop+tf*0.78, dy=blockTop+timeLH+gap+df*0.80;
⚠️ 别加 Math.max(SAFE+2, W*0.5) 这种右半区限制。(详见 07 坑10/11 + 14 第七节)
MAML 系统变量(存储/步数/开机)
<ContentProviderBinder name="getStorageData" uri="content://com.miui.securitycenter.widgetProvider/getCleanMasterData" columns="availableSpace,totalSpace" countName="hasStorageData">
<Variable name="_availableSpace" type="long" column="availableSpace"/>
</ContentProviderBinder>
var availGB = window.maml.getDoubleByName('_availableSpace')/(1024*1024*1024);
注意
- 背屏视口 348×212(dpr 2.8125),不是 976×596;避让用 vw 不用 px
- 双击会息屏:桌面图标必须单击即开
- 右下 35dp 圆角:托盘/时间要留 padding 避让
- 打包统一 .zip 后缀:
miroot_theme_packformat=zip / outputName 写完整主题名_vX.Y.zip,严禁 .zip.zip / .mrc.mrc 重复后缀;测试用miroot_theme_test_install(优先 Hook directApply=true,失败回退替换)