给Timi记账安卓软件去除广告

注意:本文仅供学习,不能做违法的事。

作为一名安卓人,安卓手机是我们每天都要接触的东西,使用安卓手机的频率甚至比使用我们身上的某些器官的时间还要长。在我们玩手机的时候,肯定会遇到一个烦恼,那就是无休无止的广告,有开屏广告、功能界面中嵌入的广告等等。更不能让人忍受的是,有些软件必须要求看完广告,才允许你继续浏览下面的内容。那我们有没有办法把平时经常使用的app里面的广告去掉呢?下面就是一个实用有效的界面方法。

需要的工具:

工欲善其事必先利其器,我们除了基础的环境外,例如java、AndroidSDK,还要特别准备好三样工具,有利于我们等好地进行操作。

1、Apktool 官网下载apktool工具。

2、Install Guide | Apktool 根据安装指引下载好脚本,并且把文件名称改为一致。这样就可以得到两个文件:apktool.bat、apktool.jar。
Pastedimage20251127094955.png

3、Release v2.4 · pxb1988/dex2jar下载dex-tools,目前最新版本为2.4。用于把dex文件翻译成jar文件。

4、Release JD-GUI 1.6.6 · java-decompiler/jd-gui 下载jd_gui工具,用于打开第三步翻译出的jar文件。

准备破解的软件

笔者以一款记账软件为例进行破解,主要就是为了去除软件中的广告和一些自己不需要的功能,达到界面简洁的目的,再说一次,仅供学习,不能干违法的事。软件名称为Timi记账,最新版本为6.4.2。如果这位软件的开发者发现了这篇文章,那你可能需要做一次更新,把漏洞修复掉。

Pastedimage20251127102221.png
Pastedimage20251127102314.png
Pastedimage20251127102356.png
Pastedimage20251127102444.png

上面三张图片红框处,就是我们要去掉的东西。

我们先下载软件,下载软件之前,需要先确定软件下载的地址,笔者用的是小米手机,在应用商店的设置中,关闭“安装完成后删除软件”开关。

下载的软件包地址:Android/data/com.xiaomi.market/files/apk

正式操作

一、反编译apk文件

把下载好的软件,放入apktool所在文件夹,进入cmd命令:
apktool d -f Timi6.4.2.apk -only-main-classes
Pastedimage20251127103829.png

成功得到Timi6.4.2文件夹,里面的内容就是资源文件以及smali文件,我们就是要在smali文件中大动手脚。

二、去掉“植物精选”选项

用编辑器打开Timi6.4.2文件夹,找到【res】- 【layout】-【activity_main】文件。如图所示:

Pastedimage20251127104458.png

我们不要轻易删掉“植物精选”选项按钮,防止程序出现找不到资源提示空指针的错误。但是我们可以加上android:visibility="gone",这样就可以把该选项隐藏了。

三、去掉广告

直接通过smali文件找到广告的内容可不是一件简单的事,在做后面的步骤之前,让我们把dex文件转换为可以看到java源码的jar文件吧。

(一)dex文件转换为jar文件

把 Timi6.4.2.apk 后缀改为 zip ,解压zip文件,得到 dex 文件。

鉴于核心代码都在 classes3.dex 文件中(我是从classes1.dex到classes4.dex一个个试出来的),把 classes3.dex 文件放进 dex-tools-v2.4 工具文件夹,进入cmd使用:d2j-dex2jar classes3.dex 得到 classes3-dex2jar.jar 文件。如图所示:

Pastedimage20251127105819.png

(二)查看java源码

把得到的 classes3-dex2jar.jar 文件放入 jd-gui-windows-1.6.6 工具文件夹,使用 jd-gui.exe 工具打开该文件。找到 com.talicai.timiclient 下的 ui 文件夹,我们所有的界面源码都在这里面。

Pastedimage20251127110550.png

(三)去掉开屏广告

从 jd-gui 工具中找到 splashActivity.class 文件,找到 init 方法,可以看到此处为判断是否显示广告的逻辑。

Pastedimage20251127110925.png

如图所示,我们只需要把下面两行代码放到 if 判断的前面去即可。也即是 responseConfig 定义语句的下方。

1
2
generalJump();  
finish();

来,我们去找到对应的 smali 文件,找到该段代码的转义部分。

Pastedimage20251127111656.png

init 方法源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
.method private init()V
.locals 4

const-string v0, "EEEE"

const-string v1, "splash-init()"

.line 1
invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 2
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->increaseStartUpCount()V

.line 3
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->initClose()V

.line 4
iget-boolean v0, p0, Lcom/talicai/timiclient/ui/SplashActivity;->isBack:Z

if-nez v0, :cond_4

.line 5
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->G()Lcom/talicai/timiclient/network/model/ResponseConfig;

move-result-object v0

.line 6
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v1

invoke-virtual {v1}, Lf/l/b/o/e;->M()Z

move-result v1

const-string v2, "DDDD"

if-eqz v1, :cond_0

const-string v0, "\u5df2\u53bb\u5e7f\u544a\u670d\u52a1"

.line 7
invoke-direct {p0, v0}, Lcom/talicai/timiclient/ui/SplashActivity;->showToast(Ljava/lang/String;)V

const-string v0, "noAD"

.line 8
invoke-static {v2, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 9
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->generalJump()V

.line 10
invoke-virtual {p0}, Landroid/app/Activity;->finish()V

goto/16 :goto_0

.line 11
:cond_0
iget-object v1, v0, Lcom/talicai/timiclient/network/model/ResponseConfig;->ShowScreenAd_v1:Ljava/lang/String;

const-string v3, "0"

invoke-virtual {v3, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

if-eqz v1, :cond_1

const-string v0, "\u5df2\u6253\u5f00\u63d2\u5c4f"

.line 12
invoke-direct {p0, v0}, Lcom/talicai/timiclient/ui/SplashActivity;->showToast(Ljava/lang/String;)V

const-string v0, "splashShowScreenAd"

.line 13
invoke-static {v2, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 14
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->generalJump()V

.line 15
invoke-virtual {p0}, Landroid/app/Activity;->finish()V

goto :goto_0

.line 16
:cond_1
iget-object v1, v0, Lcom/talicai/timiclient/network/model/ResponseConfig;->ShowScreenAd_v1:Ljava/lang/String;

const-string v3, "1"

invoke-virtual {v3, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

if-eqz v1, :cond_2

invoke-static {}, Lf/l/b/o/a;->j()Z

move-result v1

if-eqz v1, :cond_2

invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v1

invoke-virtual {v1}, Lf/l/b/o/e;->M()Z

move-result v1

if-nez v1, :cond_2

iget v1, p0, Lcom/talicai/timiclient/ui/SplashActivity;->startUpCount:I

if-eqz v1, :cond_2

const/4 v3, 0x4

if-eq v1, v3, :cond_2

.line 17
new-instance v1, Ljava/lang/StringBuilder;

invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V

const-string v3, "thirddAD\uff1a"

invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

iget-object v3, v0, Lcom/talicai/timiclient/network/model/ResponseConfig;->loadAdOrder:Ljava/lang/String;

invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v1

invoke-static {v2, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 18
new-instance v1, Ljava/lang/StringBuilder;

invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V

const-string v2, "loadAdOrder\uff1a"

invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

iget-object v2, v0, Lcom/talicai/timiclient/network/model/ResponseConfig;->loadAdOrder:Ljava/lang/String;

invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v1

invoke-direct {p0, v1}, Lcom/talicai/timiclient/ui/SplashActivity;->showToast(Ljava/lang/String;)V

.line 19
invoke-direct {p0, v0}, Lcom/talicai/timiclient/ui/SplashActivity;->showThirdAd(Lcom/talicai/timiclient/network/model/ResponseConfig;)V

goto :goto_0

:cond_2
const-string v0, "selfAD"

.line 20
invoke-static {v2, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 21
iget-object v0, p0, Lcom/talicai/timiclient/ui/SplashActivity;->close:Ljava/lang/Runnable;

if-eqz v0, :cond_3

.line 22
iget-object v1, p0, Lcom/talicai/timiclient/ui/SplashActivity;->handler:Landroid/os/Handler;

invoke-virtual {v1, v0}, Landroid/os/Handler;->removeCallbacks(Ljava/lang/Runnable;)V

.line 23
:cond_3
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->showCurrentAd()V

.line 24
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->loadNextAdData()V

:cond_4
:goto_0
return-void
.end method

更改之后,源码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
.method private init()V
.locals 4

const-string v0, "EEEE"

const-string v1, "splash-init()"

.line 1
invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 2
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->increaseStartUpCount()V

.line 3
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->initClose()V

.line 4
iget-boolean v0, p0, Lcom/talicai/timiclient/ui/SplashActivity;->isBack:Z

if-nez v0, :cond_4

.line 5
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->G()Lcom/talicai/timiclient/network/model/ResponseConfig;

move-result-object v0

.line 6
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v1

invoke-virtual {v1}, Lf/l/b/o/e;->M()Z

move-result v1

const-string v2, "DDDD"

const-string v0, "\u5df2\u53bb\u5e7f\u544a\u670d\u52a1"

.line 7
invoke-direct {p0, v0}, Lcom/talicai/timiclient/ui/SplashActivity;->showToast(Ljava/lang/String;)V

const-string v0, "noAD"

.line 8
invoke-static {v2, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 9
invoke-direct {p0}, Lcom/talicai/timiclient/ui/SplashActivity;->generalJump()V

.line 10
invoke-virtual {p0}, Landroid/app/Activity;->finish()V

:cond_4
:goto_0
return-void
.end method

至于为什么这么改,大家可以自己研究研究,我相信有 Android 基础的同学定能发现其中 if 语句对应的开始和结束。

(四)去掉功能界面弹出的广告

同上,从 jd-gui 工具中找到 MainActivity.class 文件,找到 onCreate 方法,可以看到此处直接显示广告的逻辑。我们只要在 MainActivity.smali 文件中删掉showAdMobileAd() 方法的调用即可。

Pastedimage20251127113216.png

MainActivity.smali 文件中的 showAdMobileAd() 方法调用在第十一行,那就让我们删除此段代码吧。如图所示:

Pastedimage20251127113449.png

直接删掉第11行,更改后源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
.method public onCreate(Landroid/os/Bundle;)V
.locals 4

.line 1
invoke-super {p0, p1}, Lcom/talicai/timiclient/ui/BaseActivity;->onCreate(Landroid/os/Bundle;)V

const p1, 0x7f0c0030

.line 2
invoke-virtual {p0, p1}, Landroid/app/Activity;->setContentView(I)V

.line 3
invoke-direct {p0}, Lcom/talicai/timiclient/ui/MainActivity;->initTab()V

.line 4
invoke-direct {p0}, Lcom/talicai/timiclient/ui/MainActivity;->checkUpdate()V

.line 5
invoke-direct {p0}, Lcom/talicai/timiclient/ui/MainActivity;->showLoginPromptIfNeed()V

const/4 p1, 0x1

.line 6
sput-boolean p1, Lcom/talicai/timiclient/ui/MainActivity;->isAlive:Z

.line 7
invoke-virtual {p0}, Lcom/talicai/timiclient/ui/MainActivity;->getPurchaseService()V

const/4 p1, 0x0

.line 8
invoke-direct {p0, p1}, Lcom/talicai/timiclient/ui/MainActivity;->initFromIntent(Landroid/content/Intent;)V

.line 9
invoke-static {}, Lf/l/b/b;->a()V

.line 10
invoke-static {p0}, Lf/l/b/o/d;->b(Landroid/app/Activity;)V


.line 12
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object p1

invoke-virtual {p1}, Lf/l/b/o/e;->P()Z

move-result p1

if-eqz p1, :cond_1

.line 13
invoke-static {}, Lf/l/b/k/d;->S()Lf/l/b/k/d;

move-result-object p1

invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->l()J

move-result-wide v0

invoke-virtual {p1, v0, v1}, Lf/l/b/k/d;->Z(J)J

move-result-wide v0

.line 14
invoke-static {}, Lf/l/b/l/b;->f()Lf/l/b/l/b;

move-result-object p1

invoke-virtual {p1}, Lf/l/b/l/b;->o()V

.line 15
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object p1

invoke-virtual {p1}, Lf/l/b/o/e;->U()Z

move-result p1

if-nez p1, :cond_0

const-wide/16 v2, 0x0

cmp-long p1, v0, v2

if-nez p1, :cond_0

.line 16
invoke-static {}, Lf/l/b/l/b;->f()Lf/l/b/l/b;

move-result-object p1

invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->l()J

move-result-wide v0

invoke-virtual {p1, v0, v1}, Lf/l/b/l/b;->m(J)Lrx/Observable;

move-result-object p1

new-instance v0, Lf/l/b/m/b;

invoke-direct {v0}, Lf/l/b/m/b;-><init>()V

invoke-virtual {p1, v0}, Lrx/Observable;->subscribe(Lrx/Subscriber;)Lrx/Subscription;

goto :goto_0

.line 17
:cond_0
invoke-static {}, Lf/l/b/l/b;->f()Lf/l/b/l/b;

move-result-object p1

invoke-virtual {p1}, Lf/l/b/l/b;->t()Lrx/Observable;

move-result-object p1

new-instance v0, Lf/l/b/m/b;

invoke-direct {v0}, Lf/l/b/m/b;-><init>()V

invoke-virtual {p1, v0}, Lrx/Observable;->subscribe(Lrx/Subscriber;)Lrx/Subscription;

.line 18
:cond_1
:goto_0
new-instance p1, Ljava/lang/StringBuilder;

invoke-direct {p1}, Ljava/lang/StringBuilder;-><init>()V

const-string v0, "getRegistrationID:"

invoke-virtual {p1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

invoke-static {p0}, Lcn/jpush/android/api/JPushInterface;->getRegistrationID(Landroid/content/Context;)Ljava/lang/String;

move-result-object v0

invoke-virtual {p1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

invoke-virtual {p1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object p1

const-string v0, "DDDD"

invoke-static {v0, p1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

.line 19
invoke-static {}, Lf/l/a/b;->a()V

return-void
.end method

(五)去掉检测更新

通过分析 MainActivity.class 文件,我们发现在 exitShowTost() 方法中有进行检测更新。也就是在退出时会做更新判断。由于我们现在在破解该软件,后面打包时会用到自己的签名。签名不一致的话更新会不成功,既然如此,与其以后每次有更新提醒,不如在破解版本里去掉更新检测吧。

Pastedimage20251127114237.png

smali 文件中 exitShowToast() 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
.method private exitShowTost()Z
.locals 9

.line 1
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

const/4 v1, 0x1

const/4 v2, 0x0

invoke-static {v0, v1, v0, v2, v1}, Ljava/lang/System;->arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V

.line 2
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

invoke-static {}, Ljava/lang/System;->currentTimeMillis()J

move-result-wide v3

aput-wide v3, v0, v1

.line 3
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

aget-wide v3, v0, v2

aget-wide v5, v0, v1

const-wide/16 v7, 0x3e8

sub-long/2addr v5, v7

cmp-long v0, v3, v5

if-ltz v0, :cond_0

.line 4
invoke-direct {p0}, Lcom/talicai/timiclient/ui/MainActivity;->exit()V

return v1

.line 5
:cond_0
new-instance v0, Landroid/content/Intent;

const-class v1, Lcom/talicai/timiclient/TimiAppWidget;

invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

const-string v1, "android.appwidget.action.APPWIDGET_UPDATE"

.line 6
invoke-virtual {v0, v1}, Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;

const-string v1, "widgetUpdate"

.line 7
invoke-virtual {v0, v1}, Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;

.line 8
invoke-virtual {p0, v0}, Landroid/app/Activity;->sendBroadcast(Landroid/content/Intent;)V

const v0, 0x7f0f0048

.line 9
invoke-static {p0, v0}, Lf/l/b/t/x;->j(Landroid/content/Context;I)V

return v2
.end method

更改后如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.method private exitShowTost()Z
.locals 9

.line 1
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

const/4 v1, 0x1

const/4 v2, 0x0

invoke-static {v0, v1, v0, v2, v1}, Ljava/lang/System;->arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V

.line 2
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

invoke-static {}, Ljava/lang/System;->currentTimeMillis()J

move-result-wide v3

aput-wide v3, v0, v1

.line 3
iget-object v0, p0, Lcom/talicai/timiclient/ui/MainActivity;->hits:[J

aget-wide v3, v0, v2

aget-wide v5, v0, v1

const-wide/16 v7, 0x3e8

sub-long/2addr v5, v7

cmp-long v0, v3, v5

if-ltz v0, :cond_0

.line 4
invoke-direct {p0}, Lcom/talicai/timiclient/ui/MainActivity;->exit()V

.line 5
:cond_0

return v1
.end method

(六)去掉“我的”界面的弹框广告

根据上面的逻辑,找到【ui】- 【fragment】下的 MineFragment.class 文件,如下图所示,弹框小广告 showSuspendAd() 主要是在 setUserVisibleHint() 方法中调用的,那我们直接修改 setUserVisibleHint() 方法即可。

Pastedimage20251127115450.png

smali 文件源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
.method public setUserVisibleHint(Z)V
.locals 1

.line 1
invoke-super {p0, p1}, Landroid/app/Fragment;->setUserVisibleHint(Z)V

.line 2
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->M()Z

move-result v0

if-eqz v0, :cond_0

return-void

:cond_0
if-eqz p1, :cond_1

.line 3
iget-boolean p1, p0, Lcom/talicai/timiclient/ui/fragment/MineFragment;->isAdShow:Z

if-nez p1, :cond_1

.line 4
invoke-virtual {p0}, Lcom/talicai/timiclient/ui/fragment/MineFragment;->showSuspendAd()V

const/4 p1, 0x1

.line 5
iput-boolean p1, p0, Lcom/talicai/timiclient/ui/fragment/MineFragment;->isAdShow:Z

const-string p1, "TTTT"

const-string v0, "mineFragment:setUserVisibleHint"

.line 6
invoke-static {p1, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

:cond_1
return-void
.end method

直接删除弹框部分的代码,更改后,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.method public setUserVisibleHint(Z)V
.locals 1

.line 1
invoke-super {p0, p1}, Landroid/app/Fragment;->setUserVisibleHint(Z)V

.line 2
invoke-static {}, Lf/l/b/o/e;->o()Lf/l/b/o/e;

move-result-object v0

invoke-virtual {v0}, Lf/l/b/o/e;->M()Z

move-result v0

if-eqz v0, :cond_0

return-void

:cond_0
return-void
.end method

四、打包更改后的 smali 文件

现在我们把所有需要修改的地方都改的差不多了,我们可以使用如下命令打包文件了。apktool b foldername ,其中 foldername 就是我们反编译生成的 “Timi6.4.2” 文件夹名称。

Pastedimage20251127120425.png

在 dist 文件夹中,就可找到生成的修改后的文件了。

Pastedimage20251127120600.png

五、最后一步,文件签名

虽然我们拿到了我们想要的apk,但是很有可能在手机上安装不了,这是因为Android系统有自己的验签机制。我们还得做好签名文件,这就需要 AndroidSDK 了。一般而言,只要我们下载一个Android Studio,就会自当下载 sdk 了。

文件签名前,我们需要执行对齐优化。

cmd 进入D:\SoftWareSDK\AndroidSdk\build-tools\35.0.0,执行检查命令:

1
.\zipalign -c -v 4 D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\timi6.4.2.apk

再执行对齐优化命令,即可得到一个 timi6.4.2_aligned.apk:

1
2
3
.\zipalign -v 4 D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\timi6.4.2.apk

 D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\timi6.4.2_aligned.apk

最后,我们再使用自己生成的签名文件对 timi6.4.2_aligned.apk 文件进行签名。签名格式为: apksigner sign --ks path --ks-key-alias ALIAS --out outputpath apkpath

我们把 timi6.4.2_aligned.apk 放入签名文件所在的文件夹,使用 apksigner 签名。

签名命令为.\apksigner sign --ks D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\decompiler.jks --ks-key-alias key0 --out D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\timiclient-signed.apk  D:\WorkSpace\05decompile\AndroidDecompileTool\mykeyfile\timi6.4.2_aligned.apk

这个时候得到的 timiclient-signed.apk 文件就是我们最终需要的文件,赶紧安装一下试试吧。