Better

业精于勤荒于嬉

动态修改Activity名称

Better's Avatar 2021-08-01 Android

最近公司项目中的APP,在OppoVivo手机上安装时,提示有病毒,异常展示弹窗。

最后从业务逻辑上排查,发现是锁屏页的Activity名称被标记为病毒弹窗了,这怎么能行,弹个锁屏保护页就不行了吗。

调试发现,是锁屏页的类名被标记被病毒了。解决报毒的方式也很简单,就是修改Activity的名称,修改后再次安装安装包,没有报毒了。

虽然修改了名称这次是没有报毒了,但是如果对方也更新校验规则呢,岂不是又要修改,那么最好是每次发版的时候,名称自动修改。所以问题就变为了如何动态修改Activity的名称了。

最后选择的方式是一种简单的方式,利用Andorid Studio中构建变种代码的方式build-variants,即Flavor特性来实现,每个Flavor都可以在自己对应的src目录下添加javares等代码,最后在打包的时候,所有的Flavor代码和main中中代码都会被合并到一起。那么在每次打包的前,先自动生成一个锁屏页,并且将这个锁屏页的类名全路径保存下来,这样动态修改的Activity名称的方式就完成了。最后是要用到展示锁屏页的时候,因为类名是动态变化的,只有从刚刚保存的类名中取出一个类名来展示Activity就行。说干就干。

实现的前提是先要找到AndroidStudio中在打包前的一个动作,添加自己的业务逻辑。通过打印assembleRelease任务是可以找到第一个任务的,然后可以新建一个gralde任务,让第一个任务依赖这个新建的任务,这样在打包前会先执行自己定义的任务,算是找到了打包前的动作。不过在同事的提醒下发现,这里有个更简便的方式是,利用Project对象,比如如果想定义一个全局的变量,会在gradle中定义

1
2
3
project.ext {
compileSdkVersion = 28
}

查看Project源码,发现它本身就提供了一个构建前的操作

1
2
3
4
5
6
7
/**
* <p>Adds a closure to be called immediately before this project is evaluated. The project is passed to the closure
* as a parameter.</p>
*
* @param closure The closure to call.
*/
void beforeEvaluate(Closure closure);

最后修改如下:

  1. 新增一个flavorDimensions,这个Flavor只是用来保存目标Activity代码。
  2. beforeEvaluate增加逻辑修改Java代码和Manifest代码
    • 修改Java代码。将锁屏页的所有业务逻辑都放在基类中,然后派生一个子类实现它,这个子类虽然继承于基类,但是什么业务事情都不用做。它只干一件事情,即提供一个Activity入口,因为它的所有业务逻辑都在基类中,它里面没有任何代码。同时将生产的Activity类名保存在BuildConfig文件中。
    • 修改Manifest。代码在Flavor中的manifest.xml文件中申明上一步创建的目标Activity组件信息。
  3. 修改使用逻辑。修改目标页面的弹出逻辑,从读取BuildConfig中的锁屏页类名,创建Intent的方式变为new Intent(context, Class.forName(path))
This article was last updated on days ago, and the information described in the article may have changed.