隐式启动Activity

1)Aciton只要能匹配到其中一个字符串就可以

2)category  假如Activity如下声明

<activity android:name=".ActivitySecond">
                <intent-filter>
                        <action android:name="second"></action>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <category android:name="a"></category>
                    <category android:name="b"></category>
                    <category android:name="c"></category>
                    <category android:name="d"></category>
                </intent-filter>
        </activity>

我把这些category看成一个集合{a,b,c,d},只要是Intent的category是它的子集{a,c}{c,d}那么就可以成功启动

  Intent intent = new Intent();
                intent.setAction("second");
                intent.addCategory("a");
                startActivity(intent);

但是形如下面的不可以

 Intent intent = new Intent();
                intent.setAction("second");
                intent.addCategory("a");
                intent.addCategory("e");
                startActivity(intent);


但是我如果把

 <category android:name="android.intent.category.DEFAULT"/>

去掉之后,是不能成功启动的,我去查了一些也没弄明白为啥? 

只好去看源码,根据的Activity的启动过程开始了我的分析,下面是执行流程

1、   Activity.java
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options)


2、Instrumentation.java
public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options)


3、ActivityManagerService.java

final int startActivity(Intent intent, ActivityStackSupervisor.ActivityContainer container)


4、ActivityStarter.java
 final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask)


注意这里有一句话
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);


5、ActivityStackSupervisor.java
 ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
        try {
            return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
                    PackageManager.MATCH_DEFAULT_ONLY | flags
                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
        } catch (RemoteException e) {
        }
        return null;
    }


给这个flags 添加了一个
PackageManager.MATCH_DEFAULT_ONLY 
然后调用了另一个方法
6、PackageManagerService.java


  public ResolveInfo resolveIntent(Intent intent, String resolvedType,
            int flags, int userId) {
这个方法里有个调用,这个方法意思大概是查询符合条件所有的activity信息,存到一个list中,后面都是在查询返回这个list
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                    flags, userId);


7、还是这个类PackageManagerService.java


private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
            String resolvedType, int flags, int userId)


在这个方法中有这个方法
List<ResolveInfo> result = mActivities.queryIntent(
                        intent, resolvedType, flags, userId);


8、这是个内部类,mActivities 是这个内部类的一个实例
final class ActivityIntentResolver
            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo>


方法调用如下
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
                int userId) {
            if (!sUserManager.exists(userId)) return null;
            mFlags = flags;
            return super.queryIntent(intent, resolvedType,
                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
        }
根据刚才的flag (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0 这个值应该是个true == defaultOnly
又调用了父类的这个方法
9、IntentResolver.java
父类方法如下
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
            int userId)
其中
buildResolveList(intent, categories, debug, defaultOnly,
                    resolvedType, scheme, firstTypeCut, finalList, userId);


在这个方法里
 if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
                    final R oneResult = newResult(filter, match, userId);
                    if (oneResult != null) {
                        dest.add(oneResult);
                        if (debug) {
                            dumpFilter(logPrintWriter, "    ", filter);
                            logPrintWriter.flush();
                            filter.dump(logPrinter, "    ");
                        }
                    }
                } else {
                    hasNonDefaults = true;
                }


只有当filter中有Intent.CATEGORY_DEFAULT或者当defaultOnly == false,才会结果添加到list,因为这里defaultOnly已经是true了,如果没有这filiter中添加Intent.CATEGORY_DEFAULT不会添加到list中,因此在Mainfest中必须要添加。
<category android:name="android.intent.category.DEFAULT"/>
为什么要有这种机制,filter.hasCategory(Intent.CATEGORY_DEFAULT),返回值有很多false,是LAUNCH的启动的。
3)data
<data android:scheme="string"
                        android:host="string"
                        android:port="string"
                        android:path="string"
                        android:pathPattern="string"
                        android:pathPrefix="string"
                        android:mimeType="sting"
                        />


Uri的格式:scheme://host:port/path or pathPrefix or pathPattern
跟action类似 对应着下面的这个URI。
含义 scheme: 模式 http、file、content
host: 主机名
path:路径,pathPrefix 正则表达式 ,pathPattern含有通配符“*”的路径
 intent.setDataAndType
对应写上就可以了.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值