修复mxplayer pro删除文件的bug 教程

查看 75|回复 10
作者:芽衣   
三哥不得不说好像有个神奇的大脑,想法总和别人不一样。这次难得的pro更新1.93.3果然也没有让大家失望,一个惊天大bug迎面袭来。
这个bug最早是在国外的交流群发现的,然后好像本坛的用户也有说过?就是在应用内删除文件的时候没有被永久删除,而是放到了回收站当中,然而当前版本并没有回收站的入口,所以文件并没有消失,而是重命名后修改了后缀(添加.trash隐藏)而已。
ad版的回收站功能是后面才出的,很可能是三哥搬代码没搬完,这种事在印度好像都已经见怪不怪了。
昨天晚上我试了一下pro版,界面还是做得比较像单纯的播放器的,没有其它乱七八糟的功能,试了一下删除,也确实有这个bug存在。


1 (2).jpg (11.83 KB, 下载次数: 0)
下载附件
2025-7-15 11:07 上传

我收集了各路大神的修改版,交流群里面已经很多人反馈了,没人愿意修复这个问题,当然我潜水在里面肯定是不会说话的
像这种bug,可以根据弹出的吐司、文件后缀入手。因为APP对文件有重命名动作,所以我感觉从这里入手会比较简单。

反编译apk,dex内直接搜索字符串.trash,有几个结果,点进a类。


1.png (76.92 KB, 下载次数: 0)
下载附件
2025-7-15 09:56 上传

    public static boolean a(File file, Lw lw) {
        long j;
        try {
            File b2 = b(file);     //调用下面的b方法
            if (file.renameTo(b2)) {
                RecycleBinItem a2 = RecycleBinItem.a.a(file, b2, lw);
                SW.p().getClass();
                try {
                    j = SW.n.d.insertWithOnConflict("RecycleBin", null, a2.c(), 5);
                } catch (Exception unused) {
                    j = -1;
                }
                if (j != -1) {
                    of0.a(of0.e(file.getPath()), b2.getPath());
                    return true;
                }
                b2.renameTo(file);
            }
        } catch (Exception unused2) {
        }
        return false;
    }
    public static File b(File file) {
        String D = qp.D(Files.o(file.getPath()));
        if (D == null || D.length() == 0) {
            String replaceAll = Pattern.compile("_+").matcher(Pattern.compile("[^a-zA-Z0-9._-]").matcher(Pattern.compile("[\\s\\[\\](){}]").matcher(Files.r(file.getPath())).replaceAll("_")).replaceAll("_")).replaceAll("_");
            char[] cArr = {'_'};
            int length = replaceAll.length() - 1;
            int i = 0;
            boolean z = false;
            while (i = 1) {
                        i2 = -1;
                        break;
                    }
                    if (charAt == cArr[i2]) {
                        break;
                    }
                    i2++;
                }
                boolean z2 = i2 >= 0;
                if (z) {
                    if (!z2) {
                        break;
                    }
                    length--;
                } else if (z2) {
                    i++;
                } else {
                    z = true;
                }
            }
            D = replaceAll.subSequence(i, length + 1).toString();
        }
        Hu0 hu0 = a;
        File file2 = new File((String) hu0.getValue(), o0.f(D, ".trash"));
        int i3 = 1;
        while (file2.exists()) {
            file2 = new File((String) hu0.getValue(), D + '_' + i3 + ".trash");
            i3++;
        }
        return file2;
    }
a和b方法的代码如上,可以发现他在重命名文件后,将文件移动到回收站里,并返回a状态。
那就接着往上找,查找a方法调用,看看他跑去哪里了。


2.png (32.91 KB, 下载次数: 0)
下载附件
2025-7-15 10:19 上传

有几个结果,进入public static final a(LSW;Ljava/io/File;LLw;Lcom/mxtech/media/MediaExtensions;ZLvm;)Ljava/lang/Object;,这个是删除逻辑,用于决定该如何处理文件。
public static final Object a(SW sw, File file, Lw lw, MediaExtensions mediaExtensions, boolean z, vm vmVar) {
                        if ((vmVar instanceof Zr) == false) goto L45;
                        Zr zr = (Zr) vmVar;
                        int i = zr.e;
                        if ((i & Integer.MIN_VALUE) == 0) goto L45;
                        zr.e = i - Integer.MIN_VALUE;
        L46:
                        Object obj = zr.d;
                        mn mnVar = mn.d;
                        int i2 = zr.e;
                        if (i2 == 0) goto L52;
                        if (i2 != 1) goto L51;
                        Bk0.a(obj);
        L74:
                        return Boolean.TRUE;
        L51:
                        throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
        L52:
                        Bk0.a(obj);
                        SystemClock.uptimeMillis();
                        if (z == false) goto L55;
                        boolean a2 = Files.b(e.K, file);
        L56:
                        if (a2 == false) goto L70;            //根据a2的返回值决定该如何处理文件
                        int i3 = uH0.a;
                        mediaExtensions.getClass();
                        if (mediaExtensions.i(file.getPath()) == false) goto L66;
                        AsyncTask.SERIAL_EXECUTOR.execute(new M1(4, file));
                        sw.i(file, sw.o(sw.n(file.getParent()), file.getName()));  
        L62:
                        e = move-exception;
                        new Integer(Log.e("MX.DeleteUtil", "", e));
        L66:
                        Object obj2 = Zt.a;
                        dn b2 = a.b();
                        as asVar = new as(file, null);
                        zr.e = 1;
                        if (sN.r(b2, asVar, zr) != mnVar) goto L74;
                        return mnVar;
        L70:
                        int i4 = uH0.a;
                        return Boolean.FALSE;
        L55:
                        a2 = a.a(file, lw);
        L45:
                        zr = new Zr(vmVar);
                        goto L46
        }
a2用于决定该如何处理文件,直接删还是丢回收站。在a2之上又有个if (z == false) goto L55;,z来自该方法参数中的boolean,看看他是从哪里进来的。
位于cs类中的public final invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;,如下图:
可以看到这个布尔值来自上面的v5,那看一下v16在哪里。


3.png (53.16 KB, 下载次数: 0)
下载附件
2025-7-15 10:34 上传

[Java] 纯文本查看 复制代码
    if-nez v10, :cond_c5
    .line 191
    .line 192
    if-eqz v5, :cond_c2
    .line 193
    .line 194
    goto :goto_c5
    .line 195
    :cond_c2
    const/16 v16, 0x0
    .line 196
    .line 197
    goto :goto_c7
    .line 198
    :cond_c5
    :goto_c5
    const/16 v16, 0x1
往上翻一翻,这里很清楚的看见v16来自这个判断。但是上面又有v10和v5两个判断。先看第一个v10,看看v10从哪里来的。
找了一下其实就来自方法代码开头。
.method public final invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
    .registers 20
    .line 1
    move-object/from16 v7, p0
    .line 2
    .line 3
    const/4 v0, 0x1
    .line 4
    sget-object v8, Lmn;->d:Lmn;
    .line 5
    .line 6
    iget v1, v7, Lcs;->r:I
    .line 7
    .line 8
    const-string v9, "MX.List.Builder.Local"
    .line 9
    .line 10
    iget-boolean v10, v7, Lcs;->t:Z    //v10从这里取值
    .line 11
    .line 12
    const/4 v11, 0x0
    .line 13
    if-eqz v1, :cond_35
    .line 14
    .line 15
    if-ne v1, v0, :cond_2d
这里是iget-boolean,那再找一下iput-boolean,看看在哪里。
搜索结果显示就在该类的
.method public constructor (Z[LLw;Ljava/util/ArrayList;Ltm;)V
    .registers 5
    .line 1
    iput-boolean p1, p0, Lcs;->t:Z
    .line 2
    .line 3
    iput-object p2, p0, Lcs;->x:[LLw;
    .line 4
    .line 5
    iput-object p3, p0, Lcs;->y:Ljava/util/ArrayList;
    .line 6
    .line 7
    const/4 p1, 0x2
    .line 8
    invoke-direct {p0, p1, p4}, Lzu0;->(ILtm;)V
    .line 9
    .line 10
    .line 11
    return-void
.end method
所以iput-boolean p1, p0, Lcs;->t:Z,对p1赋值1即可直接永久删除文件。


2 (2).jpg (11.2 KB, 下载次数: 0)
下载附件
2025-7-15 11:07 上传

测试了一下,提示已经变了,再检查使用空间已经减少,确认文件已经被永久删除。

在使用中我还发现一个问题,不知道是谁改的。就是启动的时候好像会黑一下,对比了一下原版,原来是启动界面的logo没了。但是改得一言难尽……
现在的高安卓版本,特别是原生系统,是强制冷启动显示logo的,和activity启动顺序无关。如果删掉icon,就会变成一个安卓机器人,很丑。我把这个破解版放到皮鞋8里测试,果然不出所料,启动背景是黑的,然后中间是一个大icon,更丑了。
如果要屏蔽启动logo,应该将图片替换为透明或者白色。
[XML] 纯文本查看 复制代码
   
        true
        @style/activityAnimation_res_0x7f1304a4
        @color/transparent
        @color/transparent
        @color/splash_window_background
        @drawable/mxplayer_logo_12
        false
        true
        true
   
在上面的xml文件中,
android:windowSplashScreenAnimatedIcon
应该设置
[color=]@color/transparent
属性,屏蔽启动logo。
像小米手机是魔改系统,已经从系统底层干掉这个属性了,如果不设置windowSplashScreenAnimatedIcon,就不会显示任何logo。如果是魔改系统,才可以直接删掉这个item屏蔽logo。

文件, 下载次数

canghaisui   

谢谢大佬分享,伸手党期待优化后的成品
swingzwh   


芽衣 发表于 2025-7-18 11:44
应该是修复了

突然想到,既然老大装了pro版,如果有空的话,顺便看看pro版有没这些之前ad版总结的bug?纯粹出于有点好奇,哈
目前已知bug(官方版也一样):
1、删除正在播放的音乐文件后(仅有1首时),音乐播放无法取消(再次点击音乐底栏时,还有残留记录)
2、打开退出按钮后(我的——设置——常规——退出按钮),点击退出按钮1秒内,再点击APP启动,会一直闪退
3、播放某些视频时,如果默认勾选硬解+,视频偶尔会卡住。
4、继续播放按钮在标题栏时,会失效(该问题已在1.97.0版本中修复)。
skycharlene   

原来是这回事。之前都没有注意这个bug
dszsu   

感谢大佬分享
sangaqiao   

感谢大佬分享
mirai2021   

感谢感谢,在iput-boolean p1, p0, Lcs;->t:Z前面加一行const/4 p1, 0x1,或者把create方法中的iget-boolean v1, p0, Lcs;->t:Z改为const/4 v1, 0x1
lx2894   

谢谢分享!!
schm168   

期待大神修改后的成品
anwaryzd   

大佬,评分弹窗怎么去除啊?
您需要登录后才可以回帖 登录 | 立即注册