分享

一步步深入smali,完美去广告

 aaie_ 2012-10-13
http://www.oracle.com/technetwork/java/javase/downloads/index.html
2:android SDK环境
下载地址:http://dl.google.com/android/android-sdk_r08-windows.zip
3:常用的APK反编译工具,见附件
4:学习常用Dalvik指令集,地址:http://pallergabor./androidblog/dalvik_opcodes.html
以下是我的文档结构(记住这个结构,以下的过程都会基于此结构):
d:\android
d:\android\sdk---sdk所在目录
d:\android\crack---破解反编译工具所在目录
d:\android\crack\apktool---apktool目录
d:\android\crack\auto-sign---签名工具
sdk包下载后,解压得到如下结构:
D:\android\sdk\add-ons
D:\android\sdk\platforms
D:\android\sdk\platform-tools
D:\android\sdk\tools
D:\android\sdk\SDK Manager.exe
运行SDK Manager.exe,在弹出的窗口中找到:Avaliable packages,右侧展开:Android Respository
在里面找到:SDK Platform Android 2.2,API 8,revision 2(安装2.2版的虚拟机)
接下来会下载安装,时间可能会长点,耐心等
接下来需要设几个系统环境变量
XP:我的电脑-〉右键-〉属性-〉高级-〉环境变量
Win7:计算机-〉右键-〉属性-〉高级系统设置-〉环境变量
在弹出的窗口中点击:新建
按以下值填写
变量名:ANDROID_SDK_HOME
变量值:D:\android\sdk (看你自己的目录而定)
接着在系统变量的框里下滚找到:Path
双击打开
在最后面加入值 ;D:\android\sdk\tools\(注意前面的分号,目录按你自己目录而定)
点击确定,关闭窗口,重启电脑
打开 /sdk/tools/目录,双击android.bat,在弹出的窗口中,选择:Virtual devices
点击右侧的:New 新建虚拟机
输入虚拟机的名称,Target中选择要使用的系统版本,SD Card的Size那里填SD卡的大小,通常填128就成
然后点击下面的 Create AVD 创建
回到刚才的界面,列表中列出了刚新建的虚拟机,双击打开虚拟机
等很长时间虚拟机启动
反编译工具:crack.zip
游戏原文件:a.apk



二:去除游戏Zoo Trip中的广告,完美去广告是指删掉程序中一切跟广告调用相关的类,方法,视图
将apk文件拷贝到 d:\android\crack\apktool 目录下,为方便操作,重命名为a.apk
打开cmd窗口
输入: 
cd d:\android\crack\apktool
d:
输入:adb devices
检测虚拟设备是否连上,正常的会返回:emulator-5554   device 类似信息
输入:adb install a.apk
在虚拟设备上安装原apk文件,并运行查看效果,先玩一通,看下广告都在哪
广告总共出现在四处:

第一处:程序启动界面

第二处:游戏结束界面(此处有两个广告,中间的那个大的对话框样的为非google广告)

第三处:分数提交界面

第四处:更多游戏界面
接下来我们来看apk文件的内部
输入:apktool d a.apk
反编译apk文件,得到目录a
输入:apktool b a
看文件能否顺利编译回去。
一切正常后,打开 a\build\apk 把里面的classes.dex拷贝到:d:\android\crack\dex 目录下,将文件拖动到dex2jar.bat上面,将自动转成jar文件,然后运行jd-gui.exe,打开刚刚生成的classes.dex.dex2jar.jar,然后会看到对应的java代码,这种方式查看到的代码并不是完整的源码,有很多的出入,仅供参考。


接下来的过程需要很大的耐心与细心,进行以下操作前,请认真学习常用Dalvik指令集(至少要花一天时间),保证能看懂一般的smali代码!!!
打开里面的AndroidManifest.xml文件
找到以<activity 打头的xml节点,在android程序中的 activity 通常是指一个界面,但是一个界面并不会是一个activity,一个activity可能包括多个界面
这里一共出现了六处,其中节点中带有 <action android:name="android.intent.action.MAIN" /> 这类信息的是主活动,可以理解成主界面
我们首先来删掉主界面的广告
通过AndroidManifest.xml中的描述,我们知道主界面对应的类的名称是:".CoverActivity" 字符"."前面的东西是程序命名空间,在AndroidManifest.xml 中的package="com.droidhen.game.zootrip" 中定义,也就是说主界面的类名是:
com.droidhen.game.zootrip.CoverActivity,所以我们依次展开 smali\com\droidhen\game\zootrip 在里面找到CoverActivity.smali文件并打开,
这里可以看到两个以CoverActivity打头的,其中的CoverActivity$1.smali是CoverActivity中的子类,可以不用看
用编辑器在 smali\com\droidhen 文件夹中查找 GoogleAdView(GoogleAdView这个是google广告的标志)
共找到四个文件:MoreActivity.smali Ad.smali AdController.smali OnlineScoreActivity.smali,都打开
第一个对应的是:更多游戏的界面,第二个只是定义了一个结构,第三个里面出现最多,是广告的实际控制类,第四个是在线排行的界面
接下来回到第一屏的CoverActivity.smali,在里面搜索 AdController
第一处:

Code :
.method private tryMore()V
   .locals 1
   .prologue
   .line 83
   sget-object v0, Lcom/droidhen/game/zootrip/global/AdController;->INSTANCE:Lcom/droidhen/game/zootrip/global/AdController;
   invoke-static {p0, v0}, Lcom/droidhen/activity/MoreHelper;->showMoreGames(Landroid/content/Context;Lcom/droidhen/Ad;)V
   .line 84
   return-void
.end method
相当于以下代码:
private void tryMore(){
       MoreHelper.showMoreGames(this, AdController.INSTANCE);
}
通过字面意思,能明白此方法是用户点击主界面上"More"按纽时执行的,因为我们最终需要移除掉所有广告调用的类,所以此处的showMoreGames方法中的参数Lcom/droidhen/Ad必须删除,打开 com/droidhen/activity/MoreHelper.smali,由于代码比较少,我直接全翻一下:
Code :
package com.droidhen.activity;
import com.droidhen.Ad;
class MoreHelper{
       public static Ad AD;
       public void showMoreGames(Context context, Ad ad){
               Intent intent = new Intent(context, MoreActivity.class);
               MoreHelper.AD=ad;
               context.startActivity(intent);
       }
}
这个类的主要作用是存储了一个静态com.droidhen.Ad值,并且跳转到MoreActivity活动。,我们要删掉里面的Ad,不能直接删掉方法,还得看MoreActivity中的调用。
用jd-gui查看 com.droidhen.activity.MoreActivity 类,搜索下onCreate方法,这个名称的方法是android程序中活动的初始调用方法,可以看到这样的:Ad localAd = MoreHelper.AD;看到没有,在MoreHelper中定义的静态com.droidhen.Ad在这里被调用了,我要实现的就是如何去掉他的调用,进而去掉MoreHelper中的com.droidhen.Ad,打开com.droidhen.activity.MoreActivity.smali,查找 com/droidhen/Ad,依次删掉以下:
Code :.line 35
   sget-object v0, Lcom/droidhen/activity/MoreHelper;->AD:Lcom/droidhen/Ad;
       
   
Code :.line 36
   .local v0, ad:Lcom/droidhen/Ad;
       
接下来还有一个if语句,怎样判断if语句的开始与终结:
       if-eqz v0, :cond_0 这里的 :cond_0就是这一个循环的标识,搜索下一个:cond_0出现的地方就是这一整块语句的终结处,所以我们删掉如下:
Code :
       if-eqz v0, :cond_0
   .line 37
   new-instance v2, Lcom/google/ads/GoogleAdView;
   invoke-direct {v2, p0}, Lcom/google/ads/GoogleAdView;-><init>(Landroid/content/Context;)V
   .line 38
   .local v2, googleAdView:Lcom/google/ads/GoogleAdView;
   new-instance v3, Landroid/widget/LinearLayout$LayoutParams;
   .end local v3           #params:Landroid/widget/LinearLayout$LayoutParams;
   const/4 v7, -0x2
   invoke-direct {v3, v9, v7}, Landroid/widget/LinearLayout$LayoutParams;-><init>(II)V
   .line 39
   .restart local v3       #params:Landroid/widget/LinearLayout$LayoutParams;
   invoke-virtual {v4, v2, v3}, Landroid/widget/LinearLayout;->addView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V
   .line 40
   invoke-interface {v0, p0, v2, v10}, Lcom/droidhen/Ad;->show(Landroid/app/Activity;Lcom/google/ads/GoogleAdView;Z)V
   .line 42
   .end local v2           #googleAdView:Lcom/google/ads/GoogleAdView;
   :cond_0
现在回到MoreHelper.smali中,删除方法中的第二个com.droidhen.Ad类型的参数,修改后的smali如下:
Code :
.class public Lcom/droidhen/activity/MoreHelper;
.super Ljava/lang/Object;
.source "MoreHelper.java"
# direct methods
.method public constructor <init>()V
   .locals 0
   .prologue
   .line 8
   invoke-direct {p0}, Ljava/lang/Object;-><init>()V
   return-void
.end method
.method public static showMoreGames(Landroid/content/Context;)V
   .locals 2
   .parameter "context"
   .prologue
   .line 12
   new-instance v0, Landroid/content/Intent;
   const-class v1, Lcom/droidhen/activity/MoreActivity;
   invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
   .line 13
   .local v0, intent:Landroid/content/Intent;
   .line 14
   invoke-virtual {p0, v0}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
   .line 15
   return-void
.end method
接下来回到CoverActivity.smali,修改掉第一处AdController出现的方法 tryMore 改成如下:
Code :
.method private tryMore()V
   .locals 1
   .prologue
   .line 83
   invoke-static {p0}, Lcom/droidhen/activity/MoreHelper;->showMoreGames(Landroid/content/Context;)V
   .line 84
   return-void
.end method
保存后 可以通过运行 apktool b a 编译一下,看有没有逻辑错误,有的话编译会报错。
在CoverActivity.smali里面接着搜索 AdController,找到如下:
Code :
   .line 36
   const/4 v1, 0x0
   invoke-static {p0, v1}, Lcom/droidhen/game/zootrip/global/AdController;->initAdArea(Landroid/app/Activity;Z)V
代码的意思是调用AdController的initAdArea方法,字面意思是插入广告视图,这个直接删掉就成。
接下来搜索,提示找不到,表示CoverActivity修改完毕,现在我们编译一下来看下效果。
CMD窗口输入:apktool b a
打开 D:\android\crack\apktool\a\dist 里面是生成好的apk,拷贝到 D:\android\crack\sign ,然后拖动文件到sign.bat上进行程序签名
CMD窗口输入: adb uninstall com.droidhen.game.zootrip
删掉原来的程序
CMD窗口输入: adb install ../sign/a.apk.apk
安装新程序,安装完后运行程序,这时可能会看到程序异常退出了,原因是什么呢
在CMD窗口输入:adb logcat 查看日志文件,等窗口停止滚动时按下 ctrl+c停止,看到里面有一句:
Code :
E/AndroidRuntime(  509): FATAL EXCEPTION: main
E/AndroidRuntime(  509): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.droidhen.game.zootrip/com.droidhen.game.zootrip.CoverActivity}:java.lang.RuntimeException: Binary XML file line #10: You must supply a layout_width attribute.
Binary XML file line #10: You must supply a layout_width attribute. 
这句的意思是说你必须指定layout_width属性值,这是因为当smali中没有相应的类来支持这个布局视图显示时,属性缺失错误,这时打开cover.xml文件(为什么是cover.xml,这个可以通过搜索CoverActivity的setContentView方法得到,具体可以再问我),删除cover.xml下面的:
<com.google.ads.GoogleAdView android:layout_height="50.0dip" android:layout_alignParentTop="true" style="\@style/ad_style" />
然后重新编译,重新签名,重新安装,打开后如下图
 
第一屏的广告已删除,点击more后的界面也不再有广告
未完待续......(可自己尝试修改后面的界面)


现在开始去除第二屏的广告
首先我们需要知道用户点击 play 按纽时转向的是哪个活动(即Activity)
在上一节中有讲到cover.xml,但没有说怎么找到这个文件的,现在说下:
打开之前的CoverActivity.smali,在其中搜索setContentView,每一个android程序的Activity都必定有一个setContentView方法,setContentView中指定了本活动所使用的布局文件是哪一个。
我们可以看到这样的代码:
Code :
   .line 30
   const/high16 v1, 0x7f03
   invoke-virtual {p0, v1}, Lcom/droidhen/game/zootrip/CoverActivity;->setContentView(I)V
这句的意思是调用id为 0x7f030000 的视图文件 0x7f03这里是一个16位整型变量,16位标准的格式是0x后面8位,不足8位的用0补齐
然后我们在 res/values/public.xml 中搜索 0x7f030000 即可找到cover.xml
在Android程序中,一个活动跳转到另一个活动,通常用要用到startActivity方法,我们在CoverActivity中搜索:startActivity
找到两处,一处在方法gotoOptions中,另一处在方法 quickStart 中,通过字面意思,我们知道,gotoOptions是指跳转到设置页面,quickStart的意思是:快速开始,因此调用游戏的方法应该就是这个。
quickStart方法中的startActivity使用的参数类型是:android.content.Intent,通过里面的代码我们可以看到:
Code :
   .line 78
   new-instance v0, Landroid/content/Intent;
   const-class v1, Lcom/droidhen/game/zootrip/GameActivity;
   invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
   .line 79
   .local v0, intent:Landroid/content/Intent;
   invoke-virtual {p0, v0}, Lcom/droidhen/game/zootrip/CoverActivity;->startActivity(Landroid/content/Intent;)V
相当于
Code :
android.content.Intent intent=new android.content.Intent(this, com.droidhen.game.zootrip.GameActivity.class);
startActivity(intent);
也就是说此处跳转的活动是GameActivity,接下来修改 smali/com/droidhen/game/zootrip/GameActivity.smali吧
打开文件后,搜索前面说到的:AdController
第一处:方法more
Code :
.method more()V
   .locals 1
   .prologue
   .line 151
   sget-object v0, Lcom/droidhen/game/zootrip/global/AdController;->INSTANCE:Lcom/droidhen/game/zootrip/global/AdController;
   invoke-static {p0, v0}, Lcom/droidhen/activity/MoreHelper;->showMoreGames(Landroid/content/Context;Lcom/droidhen/Ad;)V
   .line 152
   invoke-virtual {p0}, Lcom/droidhen/game/zootrip/GameActivity;->finish()V
   .line 153
   return-void
.end method
这与前面CoverActivity中的tryMore方法一样的修改,改成如下:
Code :
.method more()V
   .locals 1
   .prologue
   .line 151
   invoke-static {p0}, Lcom/droidhen/activity/MoreHelper;->showMoreGames(Landroid/content/Context;)V
   .line 152
   invoke-virtual {p0}, Lcom/droidhen/game/zootrip/GameActivity;->finish()V
   .line 153
   return-void
.end method
第二处:
Code :invoke-static {p0, v4}, Lcom/droidhen/game/zootrip/global/AdController;->initAdArea(Landroid/app/Activity;Z)V
直接删除
这里需要了解下 AdController类中的initAdArea方法,作用是用来初始化广告位的相关属性。
删除上面的代码同样还要删除下面两处代码:
Code :
   .line 57
   const/high16 v2, 0x7f07
   invoke-static {p0, v2, v4}, Lcom/droidhen/score/ScoreUtil;->showView(Landroid/app/Activity;IZ)V
Code :
   .line 112
   const/high16 v1, 0x7f07
   const/4 v2, 0x1
   invoke-static {p0, v1, v2}, Lcom/droidhen/score/ScoreUtil;->showView(Landroid/app/Activity;IZ)V
因为ScoreUtil中的showView是用来显示id号为0x7f070000的视图元素,当initAdArea被删除后,元素的相关属性没有初始化,所以会导致程序出错

第三处:方法submit
Code :
.method submit()V
   .locals 4
   .prologue
   .line 158
   sget-object v0, Lcom/droidhen/game/zootrip/global/AdController;->INSTANCE:Lcom/droidhen/game/zootrip/global/AdController;
   const/4 v1, 0x1
   sget-object v2, Lcom/droidhen/game/zootrip/GameActivity;->server:Ljava/lang/String;
   const/4 v3, 0x0
   invoke-static {p0, v0, v1, v2, v3}, Lcom/droidhen/score/ScoreUtil;->redirectToSubmit(Landroid/app/Activity;Lcom/droidhen/Ad;ZLjava/lang/String;Z)V
   .line 159
   return-void
.end method
涉及到了 com.droidhen.score.ScoreUtil中的redirectToSubmit方法,所以我们得进到com.droidhen.score.ScoreUtil中去
打开 smali/com/droidhen/score/ScoreUtil.smali 搜索 redirectToSubmit,打开两处
Code :
.method public static redirectToSubmit(Landroid/app/Activity;Lcom/droidhen/Ad;ZLjava/lang/String;Ljava/lang/String;ZZ)V
   .locals 2
   .parameter "activity"
   .parameter "ad"
   .parameter "finishSelf"
   .parameter "server"
   .parameter "category"
   .parameter "asc"
   .parameter "isFloat"
   .prologue
   .line 60
   invoke-static {p1}, Lcom/droidhen/score/OnlineScoreActivity;->setAdController(Lcom/droidhen/Ad;)V
   .line 61
   new-instance v0, Landroid/content/Intent;
   const-class v1, Lcom/droidhen/score/OnlineScoreActivity;
   invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
   .line 62
   .local v0, intent:Landroid/content/Intent;
   const-string v1, "server"
   invoke-virtual {v0, v1, p3}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
   .line 63
   const-string v1, "category"
   invoke-virtual {v0, v1, p4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
   .line 64
   const-string v1, "asc"
   invoke-virtual {v0, v1, p5}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
   .line 65
   const-string v1, "float"
   invoke-virtual {v0, v1, p6}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
   .line 66
   invoke-virtual {p0, v0}, Landroid/app/Activity;->startActivity(Landroid/content/Intent;)V
   .line 67
   if-eqz p2, :cond_0
   .line 68
   invoke-virtual {p0}, Landroid/app/Activity;->finish()V
   .line 70
   :cond_0
   return-void
.end method
Code :
.method public static redirectToSubmit(Landroid/app/Activity;Lcom/droidhen/Ad;ZLjava/lang/String;Z)V
   .locals 7
   .parameter "activity"
   .parameter "ad"
   .parameter "finishSelf"
   .parameter "server"
   .parameter "asc"
   .prologue
   .line 55
   const-string v4, "0"
   const/4 v6, 0x0
   move-object v0, p0
   move-object v1, p1
   move v2, p2
   move-object v3, p3
   move v5, p4
   invoke-static/range {v0 .. v6}, Lcom/droidhen/score/ScoreUtil;->redirectToSubmit(Landroid/app/Activity;Lcom/droidhen/Ad;ZLjava/lang/String;Ljava/lang/String;ZZ)V
   .line 56
   return-void
.end method
我们要做的是像前面修改MoreHelper.smali一样,删除掉参数Lcom/droidhen/Ad,将以上代码修改成下面的:
Code :
.method public static redirectToSubmit(Landroid/app/Activity;ZLjava/lang/String;Ljava/lang/String;ZZ)V
   .locals 2
   .parameter "activity"
   .parameter "finishSelf"
   .parameter "server"
   .parameter "category"
   .parameter "asc"
   .parameter "isFloat"
   .prologue
   .line 61
   new-instance v0, Landroid/content/Intent;
   const-class v1, Lcom/droidhen/score/OnlineScoreActivity;
   invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
   .line 62
   .local v0, intent:Landroid/content/Intent;
   const-string v1, "server"
   invoke-virtual {v0, v1, p2}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
   .line 63
   const-string v1, "category"
   invoke-virtual {v0, v1, p3}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
   .line 64
   const-string v1, "asc"
   invoke-virtual {v0, v1, p4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
   .line 65
   const-string v1, "float"
   invoke-virtual {v0, v1, p5}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
   .line 66
   invoke-virtual {p0, v0}, Landroid/app/Activity;->startActivity(Landroid/content/Intent;)V
   .line 67
   if-eqz p2, :cond_0
   .line 68
   invoke-virtual {p0}, Landroid/app/Activity;->finish()V
   .line 70
   :cond_0
   return-void
.end method
Code :
.method public static redirectToSubmit(Landroid/app/Activity;ZLjava/lang/String;Z)V
   .locals 7
   .parameter "activity"
   .parameter "finishSelf"
   .parameter "server"
   .parameter "asc"
   .prologue
   .line 55
   const-string v3, "0"
   const/4 v5, 0x0
   move-object v0, p0
   move v1, p1
   move-object v2, p2
   move v4, p3
   invoke-static/range {v0 .. v5}, Lcom/droidhen/score/ScoreUtil;->redirectToSubmit(Landroid/app/Activity;ZLjava/lang/String;Ljava/lang/String;ZZ)V
   .line 56
   return-void
.end method
然后回到 GameActivity.smali 修改对 redirectToSubmit方法的调用,将submit方法改成如下:
Code :
.method submit()V
   .locals 4
   .prologue
   .line 158
   const/4 v1, 0x1
   sget-object v2, Lcom/droidhen/game/zootrip/GameActivity;->server:Ljava/lang/String;
   const/4 v3, 0x0
   invoke-static {p0, v1, v2, v3}, Lcom/droidhen/score/ScoreUtil;->redirectToSubmit(Landroid/app/Activity;ZLjava/lang/String;Z)V
   .line 159
   return-void
.end method
接下来删掉 res\layout\game.xml中的相应广告布局代码:
重新编译,重新签名,重新安装,运行程序,玩一次,游戏结束时google广告不再有了






接下来,我们检查下游戏结束界面的几个按纽点击是否正常
点击 submit 提交分数时程序报了异常
还是用adb logcat来查看具体错误
关于如何使用adb logcat定位错误:
CMD窗口输入adb logcat后,待窗口文字滚动速度慢下来时(大概一秒一行),按下ctrl+c,停止logcat,然后滚动鼠标查找最后一个:Shutting down VM
在这行下面就能找到具体错误
这次的错误是:
Code :
E/AndroidRuntime(  244): FATAL EXCEPTION: main
E/AndroidRuntime(  244): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.droidhen.game.zootrip/com.droidhen.score.OnlineScoreActivity}: java.lang.RuntimeException: Binary XML file line #49: You must supply a layout_width attribute.
这个错误前面两屏的修改也有遇到,同样是要删掉xml文件中googleadviwe的定义
首先我们要知道点击submit按纽时调用的是哪个活动(可理解成哪个屏幕)
还记得AndroidManifest.xml中的那几个Activity节点吗,里面有一个
Code :<activity android:label="@string/app_name" android:name="com.droidhen.score.OnlineScoreActivity" android:screenOrientation="landscape" />
OnlineScore 的中文意思即为:在线分数
所以我们可以认为submit扫纽点击跳转的是OnlineScoreActivity
通过OnlineScoreActivity中的setContentView找到它的布局文件ID为 0x7f030003 ,通过res/values/public.xml查找到为res/layout/score.xml
打开res/layout/score.xml
报错的代码是:Binary XML file line #49: You must supply a layout_width attribute.
也就是说这个xml文件的49行有问题,少了layout_width属性,这个代码的问题可能是由于apktool工具编译后产生的,在android的视布元素中,layout_width 与 layout_height都是必须的属性
所以我们将以下代码:
Code :
           <Button android:id="@id/top" android:layout_marginRight="8.0dip" android:text="@string/top" style="\@style/button_small" />
           <Button android:id="@id/previous" android:layout_marginRight="8.0dip" android:text="@string/previous" style="\@style/button_small" />
           <Button android:id="@id/next" android:layout_marginRight="8.0dip" android:text="@string/next" style="\@style/button_small" />
修改为:
Code :
           <Button android:id="@id/top" android:layout_marginRight="8.0dip" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/top" style="\@style/button_small" />
           <Button android:id="@id/previous" android:layout_marginRight="8.0dip" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/previous" style="\@style/button_small" />
           <Button android:id="@id/next" android:layout_marginRight="8.0dip" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/next" style="\@style/button_small" />
添加了这个:
Code :android:layout_height="wrap_content" android:layout_width="wrap_content"
wrap_content 意为根据内容自动调整,上面的代码就是指定布局宽度与高度为自适应。
重新编译,重新签名,重新安装
程序运行正常,点击submit按纽也没问题,但是显示分数页面的广告还是在的
接下来删掉广告
在OnlineScoreActivity.smali中搜索 com/droidhen/Ad
删除:
Code :.field private static adController:Lcom/droidhen/Ad;
删除:[code]
.method public static setAdController(Lcom/droidhen/Ad;)V
   .locals 0
   .parameter "ad"
   .prologue
   .line 65
   sput-object p0, Lcom/droidhen/score/OnlineScoreActivity;->adController:Lcom/droidhen/Ad;
   .line 66
   return-void
.end method
[code]
由于删的是一个方法(setAdController),所以还得确保别的地方没有调用,在smali/com/droidhen文件夹中搜索setAdController,找到并删掉调用的代码。
接下来删除:
Code :
   .line 111
   const/high16 v1, 0x7f07
   invoke-virtual {p0, v1}, Lcom/droidhen/score/OnlineScoreActivity;->findViewById(I)Landroid/view/View;
   move-result-object v0
   check-cast v0, Lcom/google/ads/GoogleAdView;
   .line 112
   .local v0, adView:Lcom/google/ads/GoogleAdView;
   sget-object v1, Lcom/droidhen/score/OnlineScoreActivity;->adController:Lcom/droidhen/Ad;
   if-eqz v1, :cond_0
   .line 113
   sget-object v1, Lcom/droidhen/score/OnlineScoreActivity;->adController:Lcom/droidhen/Ad;
   const/4 v2, 0x0
   invoke-interface {v1, p0, v0, v2}, Lcom/droidhen/Ad;->show(Landroid/app/Activity;Lcom/google/ads/GoogleAdView;Z)V
以上代码的原文大致为:
Code :
GoogleAdView adView=(GoogleAdView)findViewById(0x7f070000);
if(this.adController!=null){
this.adController.show(this,adView,false);
}
这段代码的意思就是查找到id为 0x7f070000 的视图,并实例化成GoogleAdView类型,然后显示广告。
通过 res/values/public.xml 可以知道 0x7f070000 对应的布局元素是:ad_area,回到score.xml中删除:
Code :<com.google.ads.GoogleAdView android:id="@id/ad_area" android:layout_width="320.0dip" android:layout_height="50.0dip" />
重新编译,重新签名,重新安装
显示分数的广告已消失:

程序第一次运行会有一个广告,此广告并不是google广告,是游戏自身的,如图:

接下来我们来删掉这个广告
我们看到广告中有一个图片按纽:
在res\drawable文件夹中查看缩略图,发现:r_dlg_download_default.png r_dlg_download_pressed.png r_dlg_download.xml
r_dlg_download.xml是这个按纽图片的动态交互描述文件
在res/values/public.xml 中搜索r_dlg_download 得到ID值:0x7f070013
然后用编辑器在 smali/com/droidhen 中搜索这个ID值,找到:RecommendActivity.smali(R打头的你要略过,因为这R打头的是自动生成的)
从字面意思看 RecommendActivity.smali 是用于显示 推荐
我们只需要游戏活动中删除对RecommendActivity的调用,在smali/com/droidhen 文件夹中搜索:RecommendActivity,找到:RecommendUtil.smali(略过RecommendActivity打头的)
进而在smali/com/droidhen 文件夹中搜索:RecommendUtil,找到并删除:
CoverActivity.smali
Code :
   .line 38
   invoke-static {p0}, Lcom/droidhen/recommend/RecommendUtil;->fetch(Landroid/content/Context;)V
GameActivity.smali
Code :
   .line 113
   invoke-static {p0}, Lcom/droidhen/recommend/RecommendUtil;->show(Landroid/content/Context;)V
重新编译,重新签名,重新安装,广告已全面消息
接下来做清理工作,删掉不用的类及资源
删除文件:smali\com\droidhen\game\zootrip\global\AdController.smali
删除文件:smali\com\droidhen\Ad.smali
删除文件:smali\com\droidhen\game\zootrip\global\TrackUtil.smali ----此代码是用于google广告统计的
删除文件夹 com\droidhen\recommend
删除文件夹 smali\com\google
删除 res\drawable 下如下文件:
[quote]
r_dlg_bg.png
r_dlg_cancel.xml
r_dlg_cancel_default.png
r_dlg_cancel_pressed.png
r_dlg_download.xml
r_dlg_download_default.png
r_dlg_download_pressed.png
[/quote]
删除 res\values\public.xml 中的以下节点:
[quote]
   <public type="id" name="ad_area" id="0x7f070000" />
   <public type="id" name="r_dlg_icon" id="0x7f070010" />
   <public type="id" name="r_dlg_title" id="0x7f070011" />
   <public type="id" name="r_dlg_desc" id="0x7f070012" />
   <public type="id" name="r_dlg_download" id="0x7f070013" />
   <public type="id" name="r_dlg_cancel" id="0x7f070014" />
[/quote]
删除ConverActivity.smali中如下代码:
Code :
   .line 37
   invoke-static {p0}, Lcom/droidhen/game/zootrip/global/TrackUtil;->track(Landroid/content/Context;)V
Code :
   .line 43
   invoke-static {}, Lcom/droidhen/game/zootrip/global/TrackUtil;->stopTrack()V
重新编译,安装,运行
清理好的apk:a_noad.apk


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多