微信资源混淆,导致的约束布局 Constraintlayout 控件重叠!

问题

1、广告六要素

虽然我不参与广告 sdk 接入等相关工作,但是最近总是听到一个词广告六要素。这到底是什么?

国内下载类广告,尤其是针对移动应用推广的广告,其成功实施往往围绕几个关键要素进行,这些要素能够帮助广告主更有效地触达目标用户,促进应用下载。

经查阅知道,国内各大广告 SDK 平台优量汇、穿山甲、快手等已逐步开始(早已)支持广告六要素,提供了获取应用的下载六项信息:

  • 应用名称
  • 开发者公司名称
  • 应用版本
  • 隐私协议超链
  • 权限列表超链
  • 产品功能

下图以荣耀广告为例,这个是六要素控件显示正常的情况

2、布局错乱

在不使用自定义混淆(包含微信资源混淆 AndResGuard)出包运行布局是正确的!

使用微信资源混淆之后,运行错乱,六要素重叠显示!

AndResGuard Github

排查

通过使用uiautomatorviewer布局分析,定位找到了该广告的布局文件honor_ads_six_factor.xml,并确定了每个显示文本对应的控件,uiautomatorviewer 工具跟随 Android studio,安装目录下可以找到,也可以全局搜索查找。

C:\Users\Primer\AppData\Local\Android\Sdk\tools\bin\uiautomatorviewer.bat

我们知道,父容器使用的是约束布局ConstraintLayout(减少布局嵌套,布局优化),既然是因为使用了资源混淆导致问题出现,得了解资源混淆的配置是什么?

groovy 复制代码
andResGuard {
    mappingFile = null
    use7zip = true
    useSign = true
    // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
    keepRoot = false
    // 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小
    fixedResName = "arg"
    // 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
    mergeDuplicatedRes = true
    //混淆白名单
    whiteList = [
        // for your icon
        "R.drawable.icon",
        // for fabric
        "R.string.com.crashlytics.*",
        // for google-services
        "R.string.google_app_id",
        "R.string.gcm_defaultSenderId",
        "R.string.default_web_client_id",
        "R.string.ga_trackingId",
        "R.string.firebase_database_url",
        "R.string.google_api_key",
        "R.string.google_crash_reporting_api_key"
    ]
    compressFilePattern = [
        "*.png",
        "*.jpg",
        "*.jpeg",
        "*.gif",
    ]
    sevenzip {
         artifact = 'com.tencent.mm:SevenZip:1.2.21'
    }

    /**
    * 可选: 如果不设置则会默认覆盖assemble输出的apk
    **/
    // finalApkBackupPath = "${project.rootDir}/final.apk"

    /**
    * 可选: 指定v1签名时生成jar文件的摘要算法
    * 默认值为"SHA-1"
    **/
    // digestalg = "SHA-256"
}

1、首先,布局文件加白名单

白名单配置是whiteList ,一开始我们是连同布局文件也混淆的(上图是加白之后的),查看荣耀广告 SDK 的资源文件,发现文件名称都有统一前缀 honor_ads,所以加白了下面的资源,测试 -> 运行 -> 布局错乱 -> 异常

java 复制代码
"R.drawable.honor_ads*",
"R.interpolator.honor_ads*",
"R.anim.honor_ads*",
"R.animator.honor_ads*",
"R.attr.honor_ads*",
"R.color.honor_ads*",
"R.dimen.honor_ads*",
"R.mipmap.honor_ads*",
"R.id.honor_ads*",
"R.string.honor_ads*",
"R.layout.honor_ads*",
"R.style.honor_ads*",

2、仔细查看布局

上图的布局细看是这样的:

① 名称 广告 公司

② 隐私 权限 介绍 版本

  • 两行,七个控件
  • 第一行三个,第二行四个控件
  • 猜想:第二行如何很好的约束布局(按照我们的正常编码思维哈)
    • 1、第二行可能是:app:layout_constraintTop_toBottomOf="第一行",这个里是把第一行和第二行分别看成一个整体
      【很明显,该布局代码不是这样的(简单布局嵌套过深,没必要)】
    • 2、第二行的第一个可能是:app:layout_constraintTop_toBottomOf="第一行的第一个(名称)",然后第二行的其他元素像第一个或上一个控件对齐
      【很明显,布局代码也不是这样的(想必大多数人会这样写吧,没错我就是那大多数人)】
    • 3、使用 androidx.constraintlayout.widget.Barrier 进一步约束布局
      【代码确实是这样】

此前,我从未使用或了解过约束布局中的 androidx.constraintlayout.widget.Barrier这到底是什么?大概意思就是可以控制布局,具体如何使用自行搜索。

简书:Barrier的使用及实例

查资料他有两个重要的属性:

  • barrierDirection:方向
  • constraint_referenced_ids:被约束的控件 id 名称集合
xml 复制代码
<androidx.constraintlayout.widget.Barrier
    android:id="@+id/xlp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    <!-- 这里编译后是 3,我推测是 Bottom (你们可以验证下)-->
    app:barrierDirection="3"
    app:constraint_referenced_ids="ad_empty_view_top,ad_brand_name,ad_flag_view,ad_developer_view"/>

我们知道约束布局中 Direction 是这样的:

所以布局中的 Barrier 起到什么作用你应该知道了。

问题的关键是要找到关键问题(手动狗头),关键果然是 Barrier 的 app:constraint_referenced_ids,因为只有他会约束布局影响控件显示位置!

再细看 Barrier !

比如像这种属性值能正常替换

constraint_referenced_ids 属性值为什么不能被替换?

  • 像是插件还不支持比较新的属性值替换?
  • 或者属性值为数组列表的格式不同导致没有被替换?

3、解决

总之,问题清晰了,如果要进一步看资源混淆插件源码排查属性值为什么没被替换,自己尝试适配插件那可麻烦,耗时费力(除非你真的激情满满),所以最终解决就是给资源 id 名称加入白名单,保持 constraint_referenced_ids 集合里面的名称不被混淆即可!

还记的之前的加白里面虽然包含了 id,但是 keep 的是 honor_ads*,无效啊!

java 复制代码
"R.id.honor_ads*",

最终,再次提取加白前缀,那就是

java 复制代码
"R.id.ad_*",

app:constraint_referenced_ids="

ad_empty_view_top,

ad_brand_name,

ad_flag_view,

ad_developer_view"

荣耀联运 SDK 竟也有坑,只是当时没测到~

相关推荐
计算机源码社4 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
丶白泽5 小时前
重修设计模式-结构型-门面模式
android
晨春计6 小时前
【git】
android·linux·git
标标大人7 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言
木鬼与槐8 小时前
MySQL高阶1783-大满贯数量
android·数据库·mysql
iofomo8 小时前
【Abyss】Android 平台应用级系统调用拦截框架
android·开发工具·移动端
AirDroid_cn10 小时前
在家找不到手机?除了语音助手,还可以用远程控制!
android·智能手机·远程控制·手机使用技巧·远程控制手机
Good_tea_h18 小时前
Android中如何处理运行时权限?
android
冬田里的一把火318 小时前
[Android][Reboot/Shutdown] 重启/关机 分析
android·gitee
大海..18 小时前
Android 系统开发人员的权限说明文档
android