微信资源混淆打包工具导致华为推送crash问题分析过程

为了对APK体积进行优化,引入了微信资源混淆打包工具。版本上线不久便收到很多线上crash报告,大部分是华为手机。经分析是混淆了华为推送的资源文件导致的crash,本篇是分析过程。

问题出现

APM监测到线上集中爆发华为手机crash,日志如下:

Caused by:
android.content.res.Resources$NotFoundException:String resource ID #0x0
android.content.res.Resources.getText(Resources.java:410)
android.content.res.HwResources.getText(HwResources.java:465)
android.content.res.Resources.getString(Resources.java:504)
com.huawei.hms.c.h.e(ResourceLoaderUtil.java:73)
com.huawei.hms.update.e.p.a(SilentUpdateWizard.java:126)
com.huawei.hms.update.e.p.a(SilentUpdateWizard.java:90)
com.huawei.hms.activity.BridgeActivity.b(BridgeActivity.java:169)
com.huawei.hms.activity.BridgeActivity.onCreate(BridgeActivity.java:57)
android.app.Activity.performCreate(Activity.java:7372)
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3150)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3305)
android.app.ActivityThread.-wrap12(Unknown Source:0)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1894)
android.os.Handler.dispatchMessage(Handler.java:108)

从关键日志Resources$NotFoundExceptioncom.huawei.hms初步推测是混淆了资源文件导致华为推送出了问题。实际hms是指华为移动服务(Huawei Mobile Services,缩写HMS)

问题定位

很多问题的分析即使追踪到源码,也要锲而不舍的追踪下去,才能真正了解问题所以从而解决问题。从华为推送的HMSSdkBase_2.5.3.305.jar包中找到com.huawei.hms.c.hcom.huawei.hms.update.e.p两个类。

com.huawei.hms.c.h.java这个类为普通的工具类,根据名称获取资源ID

package com.huawei.hms.c;

import android.content.Context;

public class h {
    private static Context a;
    private static String b;

    public static Context a() {
        return a;
    }

    public static void a(Context var0) {
        a = var0;
        b = var0.getPackageName();
    }

    public static int a(String var0) {
        return a.getResources().getIdentifier(var0, "layout", b);
    }

    public static int b(String var0) {
        return a.getResources().getIdentifier(var0, "id", b);
    }

    public static int c(String var0) {
        return a.getResources().getIdentifier(var0, "drawable", b);
    }

    public static int d(String var0) {
        return a.getResources().getIdentifier(var0, "string", b);
    }

    public static String e(String var0) {
        String var1 = a.getResources().getString(d(var0));
        var1 = var1 == null ? "" : var1;
        return var1;
    }

    public static String a(String var0, Object... var1) {
        String var2 = a.getResources().getString(d(var0), var1);
        var2 = var2 == null ? "" : var2;
        return var2;
    }
}

com.huawei.hms.update.e.p.java这个类的a函数是关键,在此函数内获取了一些资源,通过getIdentifier的方式。一旦资源的名称被改变(混淆)将会找不到该资源而报错。

字符串名称字符串值
hms_install“安装”
hms_cancel“取消”
hms_update_message_new“该服务需安装以下应用的最新版本才能使用:\n\n·%1$s”
private void a(Activity var1) {
        Intent var2 = new Intent("com.huawei.appmarket.intent.action.ThirdUpdateAction");
        var2.setPackage("com.huawei.appmarket");
        Intent var3 = var1.getIntent();
        if (var3 != null) {
            r var4 = (r)var3.getSerializableExtra("intent.extra.update.info");
            if (var4 != null) {
                this.h = var4.b();
                JSONArray var5 = new JSONArray();
                JSONObject var6 = new JSONObject();

                try {
                    var6.put("pkgName", var4.b());
                    var6.put("versioncode", var4.c());
                } catch (JSONException var9) {
                    com.huawei.hms.support.log.a.d("SilentUpdateWizard", "create hmsJsonObject fail" + var9.getMessage());
                    return;
                }

                var5.put(var6);
                var2.putExtra("params", var5.toString());
                var2.putExtra("isHmsOrApkUpgrade", var4.a());
                var2.putExtra("buttonDlgY", com.huawei.hms.c.h.e("hms_install"));
                var2.putExtra("buttonDlgN", com.huawei.hms.c.h.e("hms_cancel"));
                var2.putExtra("upgradeDlgContent", com.huawei.hms.c.h.a("hms_update_message_new", new Object[]{"%P"}));

                try {
                    var1.startActivityForResult(var2, 2000);
                } catch (ActivityNotFoundException var8) {
                    com.huawei.hms.support.log.a.d("SilentUpdateWizard", "ActivityNotFoundException");
                }

            }
        }
    }

问题复现

从字符串的值可以得知,场景应该是:华为移动服务版本太低,在华为推送初始化时系统进行提示升级。费了一些时间在华为mate8上进行了问题复现。

  1. 卸载华为移动服务即可回退到出厂时的版本
  2. 集成华为推送SDK后启动App即会提示华为移动服务的升级
效果复现效果
机型华为mate8、EMUI5.0.1、Android7.0
华为移动服务版本2.3.3.323
华为推送版本2.5.3.305

问题修复

既然已经明确华为推送Sdk中的资源不可以混淆,那么将其全部加入微信资源混淆打包工具的白名单即可。

白名单配置如下:

whiteList = [//所有使用getIdentifier访问的资源都需要加入白名单
                 //HUAWEI Push
                 "R.string.hms_*",
                 "R.string.connect_server_fail_prompt_toast",
                 "R.string.getting_message_fail_prompt_toast",
                 "R.string.no_available_network_prompt_toast",
                 "R.string.third_app_*",
                 "R.string.upsdk_*",
                 "R.style.upsdkDlDialog",
                 "R.style.AppTheme",
                 "R.style.AppBaseTheme",
                 "R.dimen.upsdk_dialog_*",
                 "R.color.upsdk_*",
                 "R.layout.upsdk_*",
                 "R.drawable.upsdk_*",
                 "R.drawable.hms_*",
                 "R.layout.hms_*",
                 "R.id.hms_*",
    ]

问题反思

  1. AndResGuard的WhiteList.md其实已经给出了华为推送的白名单,但是不全面。引入该打包工具时应该再次全面的检测是否对App有影响,避免不必要的损失。
  2. 分析问题应该要深入源码,结合一些库原理进行全面分析,结合关键日志快速定位问题,无法复现的bug都是复现条件未找到。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值