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

一、概述

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

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

二、resolveIntent()解析

2.1 resolveIntent()解析时序图

在这里插入图片描述

2.2 resolveIntent()源码

// 从startActivity(Intent)进来,Intent不为null;
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
        int flags, int userId) {
    // ...代码省略...
    
    // 查询出满足Intent条件的ResolveInfo集合(如果该Activity没有在清单文件中注册过,则返回一个空集合)
    List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
    // 找出满足Intent条件的Activity(如果集合query为空,则直接回返null;)
    return chooseBestActivity(intent, resolvedType, flags, query, userId);
}


public List<ResolveInfo> 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<ResolveInfo> list = new ArrayList<ResolveInfo>(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<ComponentName, PackageParser.Activity>,这个属性字段在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<ResolveInfo> 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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值