本文主要目的是交流学习Xposed的使用技巧,以及给大家分享一下分析问题的思路。
有一天在用某视频APP看视频的时候,发现“高清”的清晰度也很糊,看得脑阔痛,就想选择更高的清晰度,结果告诉我需要激活特权
。
可是要软妹币啊,本来人就穷,没办法,只有自己动手去搞一波。
因为准备使用xposed去修改代码执行逻辑,所以得需要知道原先的代码是怎样的。首先,准备好jadx用于反编译APK文件,开开心心选择安装包。结果
用了360加固,瞬间懵逼。只得google一下:记一次使用Xposed框架DumpDex插件脱壳_dumpdex github-CSDN博客,一番折腾后,终于拿到了它的dex源码
现在拿到了dex源码,jadx也准备就绪,得先掐住它的七寸,知道它的关键代码在哪里。
我的方法是利用Android studio 的Layout Inspector,随便打开一个项目
这样就能知道是哪个Activity,而且在后面分析页面上的控件时用处也很大。
现在打开TVIJKPlayNewActivity:由于是多dex文件,这个Activity可能需要一个一个地用jadx反编译dex才能找到,反编译完成后通过jadx File->Save as cradle project,保存下来(我们的安装包.apk也要执行一下此操作,因为dex不包含资源文件,我们后面要使用到这些资源),后面再用Android Studio打开会方便使用。PS:后面在TVIJKPlayNewActivity查找关键方法失败了,在此记录下查找过程。
将dex反编译保存完成后,我们还需要再次jadx反编译安装包.apk,
双击resources.arsc,把里面的内容全选复制,另外保存到文本中,这里面包含了布局文件、viewId、drawable等元素的id,后面用文本编辑工具可以方便地进行查找,用id查找文件名,或用文件名查找对应的id。
现在准备工作完成,可以继续下一步。
前面说到,播放页面是在TVIJKPlayNewActivity,那么我们打开之后,又找不到从何下手,不知道如何才会触发到切换清晰度的方法。我的做法是继续Layout Inspector生成手机屏幕快照,
可以看到id/tv_projector_video_quality,那我们打开刚刚的记事本,查找tv_projector_video_quality,可以看到记录是 0x7f110355 (2131821397) = id.tv_projector_video_quality: false,括号里面的2131821397就是我们需要的真实id,
由此就能知道在这个点击事件里面有点东西
继续找到myMediaController,去寻找它的showQualityLayout()方法。从字面意思就知道,这个方法是展示清晰度的布局,继续跟进。
看到2052行的view.setVisibility(0),0是代表显示,那猜测this.llQuality就是清晰度在的地方。
找到它被初始化的地方
反推出这个控件的布局id就是2130969697
去记事本查找2130969697,找到 0x7f040461 (2130969697) = layout.player_controller_full: res/layout/player_controller_full.xml,知道它的布局文件名为player_controller_full。这个布局文件里面的mediacontroller_ll_quality就是包含清晰度的控件( 查找2131823211, 0x7f110a6b (2131823211) = id.mediacontroller_ll_quality: false)
胡乱都能猜测出mediacontroller_tv_quality_super是原画的控件。
知道是这个控件后,回到IjkMediaController,找到这个控件的点击 0x7f110a6c (2131823212) = id.mediacontroller_tv_quality_super: false,id为2131823212,
找到点击事件为qualitySuperListener,在
分析在365行,进入PlayerAction查看
,但是后面的d.b
是阿里的啥代码,反复查找都找不到相关的逻辑处理
结果都是
溜了溜了。
刚才通过播放页面去查找关键代码的方式失败,转变思维,想一想它不仅在播放的时候可以切换清晰度,在缓存的时候同样也可以切换清晰度,那么我们就从缓存去下手。
继续用屏幕快照,
打开这个Activity
总代码不到200行,分析也会方便很多。
一眼就找到关键字tv_quality:清晰度,似乎这个就是选择清晰度的控件了
映入眼帘的@BindView,这似乎是ButterKnife的风格,而且它的可见修饰符是default,那么在同级包下肯定有东西会访问到这个控件。
果不其然,有一个ViewBinder的类,继续打开往下分析:
一眼就看到了showSelectDialog()有点东西,那么继续回到DownloadDramaActivity,去寻找这个方法
继续往下
到这里就有点东西了,一看就能猜出来点击清晰度后执行的方法是boolean a(int i)。跟进SelectDialogFragment
并找到关键代码
Boolean a(int i)返回 true就切换成功,反之就切换失败,那回到showSelectQualityDialog,
看到在118行,mPresenter.a(i)还会执行操作,继续跟进。发现mPresenter被强转为b类型,那我们就还要找到这个b,
进入b类并找到a()方法
似乎b(i)返回true后,整个方法块也就返回true了,继续找到b(i)
看来还要继续往前跟进到utils.b类的e()方法
到此处似乎足够了,已经看到了原画的影子,如果继续走到d里面,那下面的f还会受到影响。先到此处不要走动。我们去写Xposed把这个方法修改一下返回值试试。
开始编写Xposed模块
由于安装包.apk是使用过360加固过的,要注意它的classLoader不能直接使用[Android 分享] 使用xposed来hook使用360加固的应用_xposed classloader hook-CSDN博客,需要从Application中获取,我这里是通过ᵢˋ(context)方法去拿到context,再通过context.getClassLoader()取到classLoader,完整代码如下
安装到手机上,打勾生效重启手机。
发现播放可以选择原画了
从下载页去比较,
这是高清画质的文件大小
这是原画画质的文件大小
原画选择还是成功的。