去掉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.smali 和 WidgetsModel.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

查看是否生效。

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui