阿里系App抓包分析(二)

3,787 阅读4分钟

经过上一篇文章分析ANetwork框架的基础运行方式后,本篇文章准备分析一下MtopSDK的初始化流程,如果大家还不知道Mtop在移动端App里面干啥的建议先读一下《移动API网关 》这篇文章简单了解MtopSDK。

话不多说,直接开始分析先将文件定位到Lmtopsdk/mtop/intf/Mtop;这个类上:

.field protected static final instanceMap:Ljava/util/Map;
.field final initTask:Lmtopsdk/mtop/global/init/IMtopInitTask;  
.field volatile instanceId:Ljava/lang/String;
.field final mtopConfig:Lmtopsdk/mtop/global/MtopConfig;

里面有几个重要的实例属性:

  • instanceMap(存放Mtop实例的)
  • initTask(初始化任务)
  • instanceId(实例ID可能为: OPEN、INNER、PRODUCT)
  • mtopConfig(MTOP配置信息)

那Mtop这个类是如何构造的呢?细看之下会发现Mtop只有一个私有的构造方法:

.method private constructor <init>(Ljava/lang/String;Lmtopsdk/mtop/global/MtopConfig;)V

翻译成Java代码大概就是这样:

private Mtop(String instancceId, MtopConfig config){
    ...
}

MtopConfig稍后再来分析,再继续往下分析Mtop类还有个私有init方法和几个静态instance的方法:

.method private declared-synchronized init(Landroid/content/Context;Ljava/lang/String;)V
.method public static instance(Landroid/content/Context;)Lmtopsdk/mtop/intf/Mtop;
.method public static instance(Landroid/content/Context;Ljava/lang/String;)Lmtopsdk/mtop/intf/Mtop;
.method public static instance(Ljava/lang/String;Landroid/content/Context;)Lmtopsdk/mtop/intf/Mtop;
.method public static instance(Ljava/lang/String;Landroid/content/Context;Ljava/lang/String;)Lmtopsdk/mtop/intf/Mtop;

因为init方法是个私有的,不太可能从外部调用,所以直接先看下几个instance方法。虽然instance有好几个重载形式,但最终都还是调用的instance(Ljava/lang/String;Landroid/content/Context;Ljava/lang/String;),简单的翻译成Java代码如下:


public static instance(Context ctx){
    instanec(ctx, null, null);
}

public static instance(Context ctx,String ttid){
    instanec(null, ctx, ttid);
}

public static instance(String instanceId, Context ctx){
    instanec(instanceId, ctx, null);
}

public static instance(String instanceId, Context ctx,String ttid){
   
}

知道最终的走向后,咱们就直接分析第四个instance方法就行啦,smali代码就不贴了直接转成Java方便阅读:

public static instance(String instanceId, Context ctx,String ttid){
    if(instanceId == null){
        instanceId = "INNER";
    }
    
    Mtop mtop = instanceMap.get(instanceId); //获取mtop实例
    if(mtop == null){
       synchronized (Mtop.class){
            mtop = instanceMap.get(instanceId); //获取mtop实例
            if(mtop == null){
                Map<String, MtopConfig> mtopConfigs = MtopSetting.mtopConfigMap;
                MtopConfig config  = mtopConfigs.get(instanceId);
                if(config == null){
                    config = new MtopConfig(instanceId);
                }
                mtop = new MTop(instanceId, config);
                config.mtopInstance = mtop;
                
                //MtopSetting.mtopConfigMap.put(instanceId, config);
                instanceMap.put(instanceId, mtop);
            }
       }
    }

    if(mtop.isInit){
        return mtop;
    }
    
    mtop.init(ctx,ttid);
    return mtop;
}

上面的instance方法差不多就是创建Mtop实例、调用init方法,所以再来看一个Mtop的构造方法:

.method private constructor <init>(Ljava/lang/String;Lmtopsdk/mtop/global/MtopConfig;)V
    ...
    iput-object p2, p0, Lmtopsdk/mtop/intf/Mtop;->mtopConfig:Lmtopsdk/mtop/global/MtopConfig;

    
    invoke-static {p1}, Lmtopsdk/mtop/global/init/MtopInitTaskFactory;->getMtopInitTask(Ljava/lang/String;)Lmtopsdk/mtop/global/init/IMtopInitTask;

    move-result-object v0

    iput-object v0, p0, Lmtopsdk/mtop/intf/Mtop;->initTask:Lmtopsdk/mtop/global/init/IMtopInitTask; 
 
    ....
.end method

Mtop构造方法做了一些实例属性的初始化工作,需要注意的是initTask这个实例属性的获取是从MtopInitTaskFactory里面获取的,跟过去看一下,是如何获取IMtopInitTask的实例的:

public static IMtopInitTask getMtopInitTask(String instanceId){
    
    switch{
        case "INNER":
        default:
            return InnerMtopInitTask();
        case "OPEN":
            returnn OpenMtopInitTask();
        case "PRODUCT":
            return ProductMtopInitTask();
    }
}

大概意思就是通过不同的instancceId获取对应的初始化任务。

有了IMtopInitTask实例后在哪里执行呢?继续分析Mtop的init方法会发现有一段运行IMtopInitTask的代码:

    new-instance v0, Lmtopsdk/mtop/intf/Mtop$1;
    invoke-direct {v0, p0}, Lmtopsdk/mtop/intf/Mtop$1;-><init>(Lmtopsdk/mtop/intf/Mtop;)V
    invoke-static {v0}, Lmtopsdk/mtop/util/MtopSDKThreadPoolExecutorFactory;->submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;

在分析IMtopInitTask的几个实现类之前,先去分析一下比较重要的类:MtopSetting,看名字知道专门用来配置Mtop和MtopConfig的,它有个静态属性和几个方法来设置一些配置:

 protected static final Map<String, MtopConfig> mtopConfigMap;
 public static MapConfig getMtopConfigByID(String instanceId){ }
 ...

getMtopConfigByID这个方法会通过instanceId获取MtopConfig的实例,如果没有的话会创建一个新的并且将它放入到mtopConfigMap中,方便下次获取。其他的方法都是通过getMtopConfigByID获取Mtop或MtopConfig实例后调用相应的设置项。

经过上面的一翻分析,猜测以下类的主要作用:

  • MtopSettings (设置工具类)
  • MtopConfig (存在Mtop配置类)
  • Mtop (Mtop核心功能类)
  • IMtopInitTask (Mtop初始化任务)

现在有人instanceId就能知道对应的IMtopInitTask实例来初始化Mtop,下一篇文章再来分析IMtopInitTask实例,最终完成爬包功能!!

最后欢迎大家关注我的公众号,获取最新的进展。

免责声明: 本文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请读者自负。