源码分析 — PackageManagerService(二)之resolveIntent()

    • 一、概述
    • 二、resolveIntent()解析
        • 2.1 resolveIntent()解析时序图
        • 2.2 resolveIntent()源码
    • 三、小结

一、概述

  1. 背景

    1. 在源码分析 — Activity的清单注册校验及动态注入一文中,我们通过AppGlobals.getPackageManager() 方法获取了IPackageManager的接口实现类PackageManagerService(PMS),由此引出了这篇文章;
  2. 版本

    系统 版本
    Android 23
  3. 关于PackageManagerService 的初始化,请参考:
    源码分析 — PackageManagerService(一)之启动流程

二、resolveIntent()解析

2.1 resolveIntent()解析时序图

源码分析 — PackageManagerService(二)之resolveIntent()_第1张图片

2.2 resolveIntent()源码

// 从startActivity(Intent)进来,Intent不为null;
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
        int flags, int userId) {
    // ...代码省略...

    // 查询出满足Intent条件的ResolveInfo集合(如果该Activity没有在清单文件中注册过,则返回一个空集合)
    List query = queryIntentActivities(intent, resolvedType, flags, userId);
    // 找出满足Intent条件的Activity(如果集合query为空,则直接回返null;)
    return chooseBestActivity(intent, resolvedType, flags, query, userId);
}


public List queryIntentActivities(Intent intent,
            String resolvedType, int flags, int userId) {
    // ...代码省略...

    /*
     * ComponentName对象内包含两个属性:
     * 1.包名:mPackage
     * 2.类名:mClass
     */ 
    ComponentName comp = intent.getComponent();
    if (comp == null) {
        if (intent.getSelector() != null) {
            intent = intent.getSelector();
            comp = intent.getComponent();
        }
    }

    if (comp != null) {//执行这里
        final List list = new ArrayList(1);
        // 根据所给的Component去清单文件中查找对应的ActivityInfo信息,如果没找到,则返回null;
        final ActivityInfo ai = getActivityInfo(comp, flags, userId);
        if (ai != null) {
            final ResolveInfo ri = new ResolveInfo();
            ri.activityInfo = ai;
            list.add(ri);
        }
        // 如果根据所给的Component没有找到对应的ActivityInfo,则返回一个空集合;
        return list;
    }
    // ...省略大段代码...
}

public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
    // ...代码省略...

    synchronized (mPackages) {
        /*
         * mActivities.mActivities的类型是ArrayMap,这个属性字段在PackageManagerService.scanPackageDirtyLI()方法中被赋值;
         * 如果Activity没有在清单文件中注册过,这里的 a=null;
         */ 
        PackageParser.Activity a = mActivities.mActivities.get(component);

        if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
            PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
            if (ps == null) return null;
            // 这里返回一个ActivityInfo实体(如果参数a=null,则该方法返回值也为null)
            return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
                    userId);
        }
        if (mResolveComponentName.equals(component)) {
            return PackageParser.generateActivityInfo(mResolveActivity, flags,
                    new PackageUserState(), userId);
        }
    }
    return null;
}

/*
 * 如果query是一个空集合,则直接回返null;
 */
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
            int flags, List query, int userId) {
    if (query != null) {
        // 此处如果集合(query)为空,则直接回返null;
        final int N = query.size();
        if (N == 1) {
            return query.get(0);
        } else if (N > 1) {
            // ...省略大段代码...
        }
    }
    return null;
}

三、小结

  1. PackageManagerService 初始化;
    1. PackageManagerService启动时,会去搜索指定目录下的所有apk包;
    2. 解析每个apk包里的 Manifest (注册清单)文件;
    3. 将解析出来的信息存储到 PackageParser.Package 对象中;
    4. PackageParser.Package 中的值赋值给 PackageManagerService 中对应的字段;
  2. PackageManagerService.resolveIntent(intent)
    1. 根据给定的 IntentPackageManagerService 中查找与之 Intent.ComponentName 相匹配的 Activity 集合;
    2. 从查出来的集合中获取最为匹配的 Activity

你可能感兴趣的:(源码分析,Android源码分析)