去掉XOSLauncher自带的widget组件图标

背景:系统集成了XOSLauncher,无源码。要求去掉其自带的一键清理、一键壁纸图标。通过系统源码尝试无果,发现这是launcher通过hard-coding写入的。

1.发现

在采用多种办法尝试无果之后,无意间操作图标进行移除时获取到以下日志。

复制代码
LauncherPreAnalytics: postAthenaEvent tid = 9461 eventName = launcher_widget_show_list bundle = Bundle[{widget_list=["{\"widget_name\":\"com.android.launcher3.widget.VerticalClockWidget\"}"], widget_name=com.transsion.xlauncher.switchwallpaper.SwitchWidget, status=0}]

此为线索一。

2.反编译

通过一系列排查可以确认这些是内部组件,需要:

复制代码
# 1. 导出 APK
adb pull /system/priv-app/XOSLauncher/XOSLauncher.apk

# 2. 反编译
apktool d XOSLauncher.apk -o XOSLauncher_src

# 3. 查找"一键清理"、"一键壁纸"相关的代码和资源
cd XOSLauncher_src
grep -r "一键清理\|一键壁纸" res/values*/strings.xml
grep -r "SwitchWidget\|CleanWidget" smali/

# 4. 找到对应的布局文件
find res/layout -name "*.xml" | xargs grep -l "清除\|壁纸\|switch\|clean"

# 5. 找到添加这些组件的代码(通常在 Workspace 或 Launcher 类中)
find smali -name "*Workspace*.smali" -o -name "*Launcher*.smali" | xargs grep -l "addWidget\|addShortcut"

# 6. 修改代码跳过添加这些组件,或直接删除相关资源文件

# 7. 重新打包
apktool b XOSLauncher_src -o XOSLauncher_mod.apk

# 8. 签名并安装

通过反编译确实查找了到了相关的源码信息,结果如下:

复制代码
guan@DESKTOP-EA83T13:~/XOSLauncher_src$ grep -r "一键清理\|一键壁纸" res/values*/strings.xml
res/values-zh-rCN/strings.xml:    <string name="clean_widget_title">一键清理</string>
res/values-zh-rCN/strings.xml:    <string name="switch_wallpaper_title">一键壁纸</string>
guan@DESKTOP-EA83T13:~/XOSLauncher_src$ grep -r "SwitchWidget\|CleanWidget" smali/
smali/com/android/launcher3/LauncherModel.smali:    const-string v1, "com.android.systemui/com.android.systemui.widget.clean.CleanWidgetProvider"
smali/com/android/launcher3/Launcher.smali:    const-class v11, Lcom/transsion/xlauncher/clean/CleanWidget;
smali/com/android/launcher3/Launcher.smali:    const-class v11, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
smali/com/android/launcher3/model/s1.smali:    new-instance v0, Lcom/transsion/xlauncher/clean/CleanWidget;
smali/com/android/launcher3/model/s1.smali:    invoke-direct {v0}, Lcom/transsion/xlauncher/clean/CleanWidget;-><init>()V
smali/com/android/launcher3/model/s1.smali:    new-instance v0, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
smali/com/android/launcher3/model/s1.smali:    invoke-direct {v0}, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;-><init>()V
smali/com/android/launcher3/model/w1.smali:    const-string v7, "com.android.systemui/com.android.systemui.widget.clean.CleanWidgetProvider"
smali/com/android/launcher3/model/w1.smali:    const-class v7, Lcom/transsion/xlauncher/clean/CleanWidget;
smali/com/android/launcher3/model/w1.smali:    const-class v7, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
smali/com/android/launcher3/model/WidgetsModel.smali:    const-class v3, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
smali/com/android/launcher3/widget/c.smali:    const-class v1, Lcom/transsion/xlauncher/clean/CleanWidget;
smali/com/android/launcher3/widget/c.smali:    const-class v1, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;

这些 Widget 是在代码中硬编码添加的。现在我们需要修改这些 smali 文件,阻止这些 Widget 被创建和显示

关键文件分析

从结果看,主要涉及:

  1. Launcher.smali - 主 Launcher 类
  2. s1.smali - 负责创建 Widget 实例
  3. w1.smaliWidgetsModel.smali - Widget 模型管理
  4. widget/c.smali - Widget 相关逻辑

先执行以下命令:

复制代码
# 1. 查看 s1.smali 中创建 Widget 的完整代码
cat ~/XOSLauncher_src/smali/com/android/launcher3/model/s1.smali | grep -B 15 -A 15 "new-instance.*CleanWidget"

# 2. 查看 SwitchWidget 的创建代码
cat ~/XOSLauncher_src/smali/com/android/launcher3/model/s1.smali | grep -B 15 -A 15 "new-instance.*SwitchWidget"

# 3. 查看 WidgetsModel.smali 中如何添加 Widget 到列表
cat ~/XOSLauncher_src/smali/com/android/launcher3/model/WidgetsModel.smali | grep -B 20 -A 20 "SwitchWidget"

执行结果:

复制代码
guan@DESKTOP-EA83T13:~/XOSLauncher_src$ cat ~/XOSLauncher_src/smali/com/android/launcher3/model/s1.smali | grep -B 15 -A 15 "new-instance.*CleanWidget"
    .param p1    # Landroid/content/Context;
        .annotation build Landroidx/annotation/NonNull;
        .end annotation
    .end param
    .line 1
    new-instance v0, Lcom/android/launcher3/widget/AllAppIconWidget;
    invoke-direct {v0}, Lcom/android/launcher3/widget/AllAppIconWidget;-><init>()V
    const v1, -0x3e8dcc0
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 2
    new-instance v0, Lcom/transsion/xlauncher/clean/CleanWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/clean/CleanWidget;-><init>()V
    const v1, 0x6e55c594
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 3
    new-instance v0, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;-><init>()V
    const v1, -0x4be2bc14
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
guan@DESKTOP-EA83T13:~/XOSLauncher_src$ cat ~/XOSLauncher_src/smali/com/android/launcher3/model/s1.smali | grep -B 15 -A 15 "new-instance.*SwitchWidget"
    const v1, -0x3e8dcc0
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 2
    new-instance v0, Lcom/transsion/xlauncher/clean/CleanWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/clean/CleanWidget;-><init>()V
    const v1, 0x6e55c594
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 3
    new-instance v0, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;-><init>()V
    const v1, -0x4be2bc14
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 4
    new-instance v0, Lcom/android/launcher3/widget/VerticalClockWidget;
    invoke-direct {v0}, Lcom/android/launcher3/widget/VerticalClockWidget;-><init>()V
    const v1, 0x5e4d1579
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
guan@DESKTOP-EA83T13:~/XOSLauncher_src$ cat ~/XOSLauncher_src/smali/com/android/launcher3/model/WidgetsModel.smali | grep -B 20 -A 20 "SwitchWidget"
    .line 19
    :cond_0
    iget-boolean v4, v3, Lcom/android/launcher3/LauncherAppWidgetProviderInfo;->isCustomWidget:Z
    if-eqz v4, :cond_3
    .line 20
    const-class v3, Lcom/android/launcher3/recentwidget/RecentWidget;
    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
    move-result-object v3
    invoke-virtual {v3, v8}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
    move-result v3
    if-nez v3, :cond_7
    .line 21
    const-class v3, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
    invoke-virtual {v3}, Ljava/lang/Class;->getName()Ljava/lang/String;
    move-result-object v3
    invoke-virtual {v3, v8}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
    move-result v3
    if-eqz v3, :cond_1
    .line 22
    invoke-static {}, Lg0/j/m/m/m/q;->n()Z
    move-result v3
    if-eqz v3, :cond_1
    move v6, v10

3.修改方案

修改 s1.smali(最简单有效)
复制代码
cd ~/XOSLauncher_src
vim smali/com/android/launcher3/model/s1.smali

找到这段代码(大约在 line 2-3):

复制代码
	.line 2
    new-instance v0, Lcom/transsion/xlauncher/clean/CleanWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/clean/CleanWidget;-><init>()V
    const v1, 0x6e55c594
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 3
    new-instance v0, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
    invoke-direct {v0}, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;-><init>()V
    const v1, -0x4be2bc14
    invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V

完全删除或注释掉这两段(推荐注释,方便恢复):

复制代码
	.line 2
    # new-instance v0, Lcom/transsion/xlauncher/clean/CleanWidget;
    # invoke-direct {v0}, Lcom/transsion/xlauncher/clean/CleanWidget;-><init>()V
    # const v1, 0x6e55c594
    # invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V
    .line 3
    # new-instance v0, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;
    # invoke-direct {v0}, Lcom/transsion/xlauncher/switchwallpaper/SwitchWidget;-><init>()V
    # const v1, -0x4be2bc14
    # invoke-virtual {p0, p1, v1, v0}, Lcom/android/launcher3/model/s1;->a(Landroid/content/Context;ILcom/android/launcher3/o5;)V

保存并退出后,重新打包

复制代码
cd ~
apktool b XOSLauncher_src -o XOSLauncher_nowidgets.apk

# 检查是否编译成功
ls -lh XOSLauncher_nowidgets.apk

如果编译成功,你会看到生成的 APK 文件。

签名 APK
复制代码
# 1. 先对齐
zipalign -p -f 4 XOSLauncher_nowidgets.apk XOSLauncher_aligned.apk

# 2. 使用 apksigner 签名(会自动处理对齐)
apksigner sign --key platform.pk8 --cert platform.x509.pem XOSLauncher_aligned.apk

# 3. 验证
apksigner verify -v XOSLauncher_aligned.apk

# 4.检查对齐
zipalign -c -v 4 XOSLauncher_signed.apk
安装APK
复制代码
# 1. 获取 root 权限
adb root

# 2. 重新挂载系统分区为可写
adb remount

# 3. 备份原 APK(如果还没备份)
adb shell cp /system/priv-app/XOSLauncher/XOSLauncher.apk /system/priv-app/XOSLauncher/XOSLauncher.apk.bak

# 4. 推送新 APK
adb push XOSLauncher_aligned.apk /system/priv-app/XOSLauncher/XOSLauncher.apk

# 5. 设置正确的权限和 SELinux 上下文
adb shell chmod 644 /system/priv-app/XOSLauncher/XOSLauncher.apk
adb shell chown root:root /system/priv-app/XOSLauncher/XOSLauncher.apk
adb shell chcon u:object_r:system_file:s0 /system/priv-app/XOSLauncher/XOSLauncher.apk

# 6. 清除应用数据并重启
adb shell pm clear com.transsion.XOSLauncher
adb reboot

查看是否生效。

相关推荐
飞梦工作室39 分钟前
PHP 中 php://input 的全面使用指南
android·开发语言·php
熬夜敲代码的小N1 小时前
Unity WebRequest高级操作:构建高效稳定的网络通信模块
android·数据结构·unity·游戏引擎
Android技术之家1 小时前
安卓对外发布工程源码:如何实现仅暴露 UI 层
android·ui
Digitally1 小时前
如何快速将iPhone上的图片发送到安卓手机(6种方法)
android·智能手机·iphone
w***74172 小时前
MySQL压缩版安装详细图解
android·mysql·adb
童话的守望者3 小时前
DC5通关及溯源分析
android
青莲8433 小时前
Android Lifecycle 完全指南:从设计原理到生产实践
android·前端