Android大厂面试秘籍: Activity Intent 解析与处理模块(三)

深入剖析 Android Activity 意图(Intent)解析与处理模块

本人掘金号,欢迎点击关注:掘金号地址

本人公众号,欢迎点击关注:公众号地址

一、引言

在 Android 系统中,Activity 意图(Intent)是实现组件间通信和交互的关键机制。它不仅能够启动 Activity、Service 以及广播等组件,还能在组件之间传递数据。Intent 的解析与处理过程涉及多个系统服务和组件,其内部机制复杂且精妙。深入理解 Intent 的解析与处理模块,对于开发者优化应用性能、增强组件间通信的稳定性以及解决开发过程中遇到的各种问题都具有重要意义。本文将从源码级别对 Android Activity 意图的解析与处理模块进行全面而深入的分析。

二、Intent 基础概念

2.1 Intent 的定义与作用

Intent 是一个消息传递对象,它可以在不同组件(如 Activity、Service、BroadcastReceiver)之间传递信息。其主要作用包括:

  • 启动组件:通过指定组件的类名或通过匹配 Intent 的过滤器来启动相应的 Activity、Service 或发送广播。

  • 传递数据:可以在 Intent 中携带各种类型的数据,如字符串、整数、布尔值等,以便在组件之间共享信息。

  • 执行操作:指定要执行的动作,如查看网页、拨打电话等。

以下是一个简单的 Intent 示例,用于启动一个 Activity:

java

java 复制代码
// 创建一个 Intent 对象,指定当前上下文和要启动的 Activity 类
Intent intent = new Intent(this, TargetActivity.class);
// 启动 Activity
startActivity(intent);

2.2 Intent 的主要组成部分

2.2.1 组件名(Component Name)

组件名用于明确指定要启动的组件,它包含包名和类名。可以通过 ComponentName 类来创建一个组件名对象,并将其设置到 Intent 中。

java

java 复制代码
// 创建一个 ComponentName 对象,指定包名和类名
ComponentName componentName = new ComponentName("com.example.app", "com.example.app.TargetActivity");
// 创建 Intent 对象
Intent intent = new Intent();
// 设置组件名到 Intent 中
intent.setComponent(componentName);
2.2.2 动作(Action)

动作是一个字符串,用于描述要执行的操作。Android 系统预定义了许多常用的动作,如 Intent.ACTION_VIEW 用于查看数据,Intent.ACTION_SEND 用于发送数据等。也可以自定义动作。

java

java 复制代码
// 创建 Intent 对象并设置动作
Intent intent = new Intent(Intent.ACTION_VIEW);
2.2.3 数据(Data)

数据是一个 Uri 对象,用于指定要操作的数据。例如,要查看网页,可以将网页的 URL 作为数据设置到 Intent 中。

java

java 复制代码
// 创建 Intent 对象并设置动作和数据
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
2.2.4 类别(Category)

类别是一个字符串,用于进一步描述 Intent 的附加信息。例如,Intent.CATEGORY_LAUNCHER 表示该 Intent 是用于启动应用的主 Activity。

java

java 复制代码
// 创建 Intent 对象,设置动作和类别
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
2.2.5 类型(Type)

类型用于指定数据的 MIME 类型,如 text/plainimage/jpeg 等。如果设置了类型,系统会根据类型来匹配合适的组件。

java

java 复制代码
// 创建 Intent 对象,设置动作和类型
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("image/jpeg");
2.2.6 额外数据(Extras)

额外数据是一个键值对集合,用于在 Intent 中携带额外的信息。可以使用 putExtra 方法来添加额外数据。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent(this, TargetActivity.class);
// 添加额外数据
intent.putExtra("key", "value");

2.3 Intent 的分类

2.3.1 显式 Intent

显式 Intent 明确指定了要启动的组件的类名。在使用显式 Intent 时,系统会直接根据指定的类名启动相应的组件。

java

java 复制代码
// 创建显式 Intent,指定要启动的 Activity 类
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);
2.3.2 隐式 Intent

隐式 Intent 不明确指定要启动的组件,而是通过设置动作、数据、类别等信息,由系统根据这些信息在 AndroidManifest.xml 文件中匹配合适的组件。

java

java 复制代码
// 创建隐式 Intent,设置动作和数据
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
startActivity(intent);

三、Intent 的创建与设置

3.1 Intent 构造函数

Intent 类提供了多个构造函数,用于创建不同类型的 Intent 对象。

3.1.1 无参构造函数

java

java 复制代码
// 使用无参构造函数创建 Intent 对象
Intent intent = new Intent();

这种方式创建的 Intent 对象初始时没有设置任何动作、数据等信息,需要后续通过相应的方法进行设置。

3.1.2 带动作参数的构造函数

java

java 复制代码
// 使用带动作参数的构造函数创建 Intent 对象
Intent intent = new Intent(Intent.ACTION_VIEW);

该构造函数创建的 Intent 对象设置了指定的动作。

3.1.3 带动作和数据参数的构造函数

java

java 复制代码
// 使用带动作和数据参数的构造函数创建 Intent 对象
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));

此构造函数创建的 Intent 对象同时设置了动作和数据。

3.1.4 带上下文和组件类参数的构造函数

java

java 复制代码
// 使用带上下文和组件类参数的构造函数创建显式 Intent 对象
Intent intent = new Intent(this, TargetActivity.class);

该构造函数用于创建显式 Intent,明确指定了要启动的组件类。

3.2 设置 Intent 的属性

3.2.1 设置动作

可以使用 setAction 方法来设置 Intent 的动作。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent();
// 设置动作
intent.setAction(Intent.ACTION_SEND);
3.2.2 设置数据

使用 setData 方法来设置 Intent 的数据。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent();
// 设置数据
intent.setData(Uri.parse("content://com.example.provider/data"));
3.2.3 设置类型

使用 setType 方法来设置 Intent 的类型。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent();
// 设置类型
intent.setType("text/plain");
3.2.4 设置组件名

使用 setComponent 方法来设置 Intent 的组件名。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent();
// 创建 ComponentName 对象
ComponentName componentName = new ComponentName("com.example.app", "com.example.app.TargetActivity");
// 设置组件名
intent.setComponent(componentName);
3.2.5 添加类别

使用 addCategory 方法来添加类别。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent(Intent.ACTION_MAIN);
// 添加类别
intent.addCategory(Intent.CATEGORY_LAUNCHER);
3.2.6 添加额外数据

使用 putExtra 方法来添加额外数据。可以添加不同类型的数据,如字符串、整数、布尔值等。

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent(this, TargetActivity.class);
// 添加字符串类型的额外数据
intent.putExtra("string_key", "string_value");
// 添加整数类型的额外数据
intent.putExtra("int_key", 123);
// 添加布尔类型的额外数据
intent.putExtra("boolean_key", true);

3.3 Intent 的序列化与反序列化

在某些情况下,需要将 Intent 对象进行序列化,以便在不同进程或组件之间传递。Intent 类实现了 Parcelable 接口,因此可以通过 Parcel 进行序列化和反序列化。

3.3.1 序列化

java

java 复制代码
// 创建 Intent 对象
Intent intent = new Intent(this, TargetActivity.class);
// 创建 Parcel 对象
Parcel parcel = Parcel.obtain();
// 将 Intent 对象写入 Parcel 中
intent.writeToParcel(parcel, 0);
// 获取 Parcel 中的字节数组
byte[] bytes = parcel.marshall();
// 释放 Parcel 对象
parcel.recycle();
3.3.2 反序列化

java

java 复制代码
// 创建 Parcel 对象并从字节数组中恢复数据
Parcel parcel = Parcel.obtain();
parcel.unmarshall(bytes, 0, bytes.length);
parcel.setDataPosition(0);
// 从 Parcel 中读取 Intent 对象
Intent restoredIntent = Intent.CREATOR.createFromParcel(parcel);
// 释放 Parcel 对象
parcel.recycle();

四、Intent 的解析过程

4.1 解析的触发时机

Intent 的解析过程通常在以下几种情况下触发:

  • 启动 Activity :当调用 startActivity 方法启动一个 Activity 时,如果使用的是隐式 Intent,系统会对该 Intent 进行解析,以找到合适的 Activity 来处理。
  • 启动 Service :调用 startServicebindService 方法启动或绑定一个 Service 时,若使用隐式 Intent,同样需要进行解析。
  • 发送广播 :调用 sendBroadcast 等方法发送广播时,隐式 Intent 也会被解析以确定接收广播的组件。

4.2 解析的核心类与组件

4.2.1 PackageManagerService(PMS)

PackageManagerService 是 Android 系统中负责管理应用程序包的核心服务。它维护着系统中所有应用程序的信息,包括 Activity、Service、BroadcastReceiver 等组件的声明信息。在 Intent 解析过程中,PMS 会根据 Intent 的信息在其维护的组件列表中进行匹配。

4.2.2 ResolveInfo

ResolveInfo 类用于存储 Intent 解析的结果。它包含了匹配到的组件的信息,如组件的类名、优先级等。

4.3 解析流程的源码分析

4.3.1 从 startActivity 到解析的调用链

当调用 startActivity 方法启动一个 Activity 时,最终会调用到 ActivityManagerServicestartActivity 方法。在这个过程中,如果是隐式 Intent,会触发 Intent 的解析操作。

java

java 复制代码
// Activity 类中的 startActivity 方法
public void startActivity(Intent intent) {
    startActivity(intent, null);
}

// Activity 类中的 startActivity 方法重载
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

// Activity 类中的 startActivityForResult 方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

// Instrumentation 类中的 execStartActivity 方法
public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (options != null) {
        try {
            ActivityOptions.abort(options);
            intent.putExtra(ActivityManager.KEY_ACTIVITY_OPTIONS, options);
        } catch (ParcelableException e) {
            throw new RuntimeException(e);
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        // 调用 ActivityManagerNative.getDefault() 获取 ActivityManagerService 的代理对象
        int result = ActivityManagerNative.getDefault()
           .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null? target.mEmbeddedID : null,
                requestCode, 0, null, referrer);
        checkStartActivityResult(result, intent);
        return null;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}

// ActivityManagerService 类中的 startActivity 方法
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

// ActivityManagerService 类中的 startActivityAsUser 方法
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    // 检查调用者是否有权限启动 Activity
    if (callingPackage == null || callingPackage.length() == 0) {
        callingPackage = getCallingPackage(caller);
    }
    // 检查 Intent 是否合法
    if (intent == null) {
        throw new IllegalArgumentException("Intent must not be null");
    }
    // 获取 ActivityStackSupervisor 对象
    ActivityStackSupervisor mStackSupervisor = mActivityStackSupervisor;
    // 调用 startActivityMayWait 方法开始启动 Activity 的流程
    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, 0, 0, null, null, startFlags, false, profilerInfo,
            null, null, bOptions, userId, null, null);
}

// ActivityStackSupervisor 类中的 startActivityMayWait 方法
final int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, WaitResult outResult, int configChanges,
        boolean waitResult, boolean onlyIfNeeded, ProfilerInfo inProfilerInfo,
        Bundle bOptions, int userId, IActivityContainer iContainer,
        TaskRecord inTask) {
    // 检查调用者是否有权限启动 Activity
    enforceCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS,
            "startActivity");
    // 检查是否允许跨用户启动 Activity
    if (callingUid >= UserHandle.USER_MIN && callingUid <= UserHandle.USER_MAX) {
        if (callingUid != userId) {
            enforceCrossUserPermission(callingUid, userId, false, "startActivity");
        }
    }
    // 获取当前用户的 ActivityStack
    ActivityStack stack = getFocusedStack();
    if (stack == null) {
        throw new RuntimeException("no stack");
    }
    // 调用 startActivityLocked 方法进行进一步处理
    return startActivityLocked(caller, intent, resolvedType, null, null, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, null, null, null,
            configChanges, onlyIfNeeded, userId, inTask, iContainer, bOptions);
}

// ActivityStackSupervisor 类中的 startActivityLocked 方法
private int startActivityLocked(IApplicationThread caller, Intent intent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, TaskRecord inTask,
        ActivityRecord[] outActivity, int configChanges, boolean onlyIfNeeded,
        int userId, TaskRecord taskToAffiliate, IActivityContainer iContainer,
        Bundle bOptions) {
    // 获取当前用户的 ActivityStack
    ActivityStack stack = getFocusedStack();
    // 获取 Activity 启动模式
    int launchMode = aInfo != null? aInfo.launchMode : -1;
    // 如果没有传入 ResolveInfo 对象,则进行 Intent 解析
    if (rInfo == null) {
        rInfo = mService.getPackageManager().resolveActivity(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY |
                ActivityManagerService.STOCK_PM_FLAGS, userId);
    }
    // 根据解析结果获取 ActivityInfo 对象
    if (rInfo != null) {
        aInfo = rInfo.activityInfo;
    }
    // 其他处理逻辑...
    return ActivityManager.START_SUCCESS;
}

从上述代码可以看出,当调用 startActivity 方法时,经过一系列调用,最终会在 ActivityStackSupervisorstartActivityLocked 方法中进行 Intent 解析。如果没有传入 ResolveInfo 对象,则会调用 PackageManagerresolveActivity 方法进行解析。

4.3.2 PackageManager 的 resolveActivity 方法

PackageManagerresolveActivity 方法是 Intent 解析的核心方法之一,它会调用 PackageManagerService 中的相应方法进行实际的解析操作。

java

java 复制代码
// PackageManager 类中的 resolveActivity 方法
public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);

// PackageManagerService 类中的 resolveActivity 方法
@Override
public ResolveInfo resolveActivity(Intent intent, String resolvedType, int flags, int userId) {
    // 调用 resolveIntent 方法进行解析
    return resolveIntent(intent, resolvedType, flags, userId, false);
}

// PackageManagerService 类中的 resolveIntent 方法
private ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId, boolean allowDynamic) {
    // 检查 Intent 是否为显式 Intent
    if (intent.getComponent() != null) {
        // 显式 Intent 处理逻辑
        return resolveExplicitIntent(intent, resolvedType, flags, userId);
    }

    // 隐式 Intent 处理逻辑
    List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
    if (query != null && query.size() > 0) {
        // 对解析结果进行排序
        ResolveInfo best = chooseBestActivity(intent, resolvedType, flags, query, userId);
        return best;
    }
    return null;
}

// PackageManagerService 类中的 resolveExplicitIntent 方法
private ResolveInfo resolveExplicitIntent(Intent intent, String resolvedType, int flags, int userId) {
    ComponentName comp = intent.getComponent();
    if (comp == null) {
        return null;
    }
    // 从 PackageManagerService 维护的组件列表中查找匹配的 ActivityInfo
    ActivityInfo ai = getActivityInfo(comp, flags, userId);
    if (ai != null) {
        ResolveInfo ri = new ResolveInfo();
        ri.activityInfo = ai;
        return ri;
    }
    return null;
}

// PackageManagerService 类中的 queryIntentActivities 方法
public List<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) {
    // 获取所有符合条件的 ActivityInfo 列表
    List<ActivityInfo> activities = getActivitiesForIntent(intent, resolvedType, flags, userId);
    if (activities == null) {
        return null;
    }
    List<ResolveInfo> ris = new ArrayList<>(activities.size());
    for (ActivityInfo ai : activities) {
        ResolveInfo ri = new ResolveInfo();
        ri.activityInfo = ai;
        // 计算匹配得分
        ri.match = calculateMatch(ai, intent, resolvedType, flags);
        ris.add(ri);
    }
    // 对解析结果进行排序
    Collections.sort(ris, mResolvePrioritySorter);
    return ris;
}

// PackageManagerService 类中的 getActivitiesForIntent 方法
private List<ActivityInfo> getActivitiesForIntent(Intent intent, String resolvedType, int flags, int userId) {
    // 从 PackageManagerService 维护的组件列表中查找所有可能匹配的 ActivityInfo
    List<ActivityInfo> result = new ArrayList<>();
    // 遍历所有包信息
    for (PackageParser.Package pkg : mPackages.values()) {
        if (!isPackageEnabledForUser(pkg, userId)) {
            continue;
        }
        // 遍历包中的所有 Activity 信息
        for (PackageParser.Activity a : pkg.activities) {
            if (a.info == null) {
                continue;
            }
            // 检查 Activity 是否匹配 Intent
            if (isActivityResolvedTo(intent, resolvedType, flags, a, userId)) {
                result.add(a.info);
            }
        }
    }
    return result;
}

// PackageManagerService 类中的 isActivityResolvedTo 方法
private boolean isActivityResolvedTo(Intent intent, String resolvedType, int flags, PackageParser.Activity a, int userId) {
    // 检查动作是否匹配
    if (intent.getAction() != null) {
        boolean actionMatch = false;
        for (String action : a.intentFilters.keySet()) {
            if (action.equals(intent.getAction())) {
                actionMatch = true;
                break;
            }
        }
        if (!actionMatch) {
            return false;
        }
    }

    // 检查类别是否匹配
    if (intent.getCategories() != null) {
        for (String category : intent.getCategories()) {
            boolean categoryMatch = false;
            for (IntentFilter filter : a.intentFilters.values()) {
                if (filter.hasCategory(category)) {
                    categoryMatch = true;
                    break;
                }
            }
            if (!categoryMatch) {
                return false;
            }
        }
    }

    // 检查数据和类型是否匹配
    if (intent.getData() != null || resolvedType != null) {
        boolean dataMatch = false;
        for (IntentFilter filter : a.intentFilters.values()) {
            if (filter.matchData(intent.getData(), resolvedType) >= 0) {
                dataMatch = true;
                break;
            }
        }
        if (!dataMatch) {
            return false;
        }
    }

    return true;
}

// PackageManagerService 类中的 calculateMatch 方法
private int calculateMatch(ActivityInfo ai, Intent intent, String resolvedType, int flags) {
    int match = 0;
    // 根据动作、类别、数据等匹配情况计算匹配得分
    // 动作匹配加分
    if (intent.getAction() != null) {
        for (IntentFilter filter : ai.intentFilters) {
            if (filter.hasAction(intent.getAction())) {
                match += 100;
                break;
            }
        }
    }
    // 类别匹配加分
    if (intent.getCategories() != null) {
        for (String category : intent.getCategories()) {
            for (IntentFilter filter : ai.intentFilters) {
                if (filter.hasCategory(category)) {
                    match += 10;
                    break;
                }
            }
        }
    }
    // 数据和类型匹配加分
    if (intent.getData() != null || resolvedType != null) {
        for (IntentFilter filter : ai.intentFilters) {
            if (filter.matchData(intent.getData(), resolvedType) >= 0) {
                match += 10;
                break;
            }
        }
    }
    return match;
}

// PackageManagerService 类中的 chooseBestActivity 方法
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int userId) {
    if (query.size() == 1) {
        return query.get(0);
    }
    // 选择匹配得分最高的 ResolveInfo
    ResolveInfo best = null;
    int bestMatch = -1;
    for (ResolveInfo ri : query) {
        if (ri.match > bestMatch) {
            best = ri;
            bestMatch = ri.match;
        }
    }
    return best;
}

resolveIntent 方法中,首先检查 Intent 是否为显式 Intent。如果是显式 Intent,则调用 resolveExplicitIntent 方法,直接根据组件名查找匹配的 ActivityInfo。如果是隐式 Intent,则调用 queryIntentActivities 方法查找所有可能匹配的 ActivityInfo,并计算匹配得分,最后调用 chooseBestActivity 方法选择匹配得分最高的 ResolveInfo 作为解析结果。

4.4 解析结果的处理

4.4.1 ResolveInfo 的使用

解析结果存储在 ResolveInfo 对象中,包含了匹配到的组件的信息。在 ActivityStackSupervisorstartActivityLocked 方法中,会根据解析结果获取 ActivityInfo 对象,然后进行后续的 Activity 启动操作。

java

java 复制代码
// ActivityStackSupervisor 类中的 startActivityLocked 方法
private int startActivityLocked(IApplicationThread caller, Intent intent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, TaskRecord inTask,
        ActivityRecord[] outActivity, int configChanges, boolean onlyIfNeeded,
        int userId, TaskRecord taskToAffiliate, IActivityContainer iContainer,
        Bundle bOptions) {
    // 获取当前用户的 ActivityStack
    ActivityStack stack = getFocusedStack();
    // 获取 Activity 启动模式
    int launchMode = aInfo != null? aInfo.launchMode : -1;
    // 如果没有传入 ResolveInfo 对象,则进行 Intent 解析
    if (rInfo == null) {
        rInfo = mService.getPackageManager().resolveActivity(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY |
                ActivityManagerService.STOCK_PM_FLAGS, userId);
    }
    // 根据解析结果获取 ActivityInfo 对象
    if (rInfo != null) {
        aInfo = rInfo.activityInfo;
    }
    // 创建 ActivityRecord 对象
    ActivityRecord r = new ActivityRecord(stack.mService, callerApp, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession,
            voiceInteractor, profilerInfo, clientVisible, clientForeground);
    // 后续的 Activity 启动操作...
    return ActivityManager.START_SUCCESS;
}
4.4.2 解析失败的处理

如果 Intent 解析失败,resolveActivity 方法会返回 null。在调用 startActivity 等方法时,如果解析失败,可能会抛出异常或给出相应的提示信息。

java

java 复制代码
// ActivityStackSupervisor 类中的 startActivityLocked 方法
private int startActivityLocked(IApplicationThread caller, Intent intent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, TaskRecord inTask,
        ActivityRecord[] outActivity, int configChanges, boolean onlyIfNeeded,
        int userId, TaskRecord taskToAffiliate, IActivityContainer iContainer,
        Bundle bOptions) {
    // 获取当前用户的 ActivityStack
    ActivityStack stack = getFocusedStack();
    // 获取 Activity 启动模式
    int launchMode = aInfo != null? aInfo.launchMode : -1;
    // 如果没有传入 ResolveInfo 对象,则进行 Intent 解析
    if (rInfo == null) {
        rInfo = mService.getPackageManager().resolveActivity(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY |
                ActivityManagerService.STOCK_PM_FLAGS, userId);
    }
    // 根据解析结果获取 ActivityInfo 对象
    if (rInfo != null) {
        aInfo = rInfo.activityInfo;
    } else {
        // 解析失败,返回相应的错误码
        return ActivityManager.START_TARGET_NOT_FOUND;
    }
    // 后续的 Activity 启动操作...
    return ActivityManager.START_SUCCESS;
}

五、Intent 的处理过程

5.1 处理的触发时机

当 Intent 解析完成后,会触发相应组件的处理过程。如果解析结果是一个 Activity,会启动该 Activity;如果是一个 Service,会启动或绑定该 Service;如果是一个 BroadcastReceiver,会发送广播并调用相应的 onReceive 方法。

5.2 处理的核心类与组件

5.2.1 ActivityManagerService(AMS)

ActivityManagerService 是 Android 系统中负责管理 Activity 生命周期和任务栈的核心服务。在 Intent 处理过程中,AMS 会根据解析结果启动相应的 Activity,并管理其生命周期。

5.2.2 ActivityThread

ActivityThread 是应用进程的主线程类,负责处理 Activity 的创建、生命周期管理等操作。当 AMS 通知应用进程启动一个 Activity 时,ActivityThread 会进行实际的 Activity 创建和启动操作。

5.3 处理流程的源码分析

5.3.1 Activity 的启动处理

当 Intent 解析结果是一个 Activity 时,会触发 Activity 的启动处理流程。在 ActivityStackSupervisorstartActivityLocked 方法中,会创建 ActivityRecord 对象,并调用 ActivityStackstartActivityLocked 方法进行 Activity 的启动。

java

java 复制代码
// ActivityStackSupervisor 类中的 startActivityLocked 方法
private int startActivityLocked(IApplicationThread caller, Intent intent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, TaskRecord inTask,
        ActivityRecord[] outActivity, int configChanges, boolean onlyIfNeeded,
        int userId, TaskRecord taskToAffiliate, IActivityContainer iContainer,
        Bundle bOptions) {
    // 获取当前用户的 ActivityStack
    ActivityStack stack = getFocusedStack();
    // 获取 Activity 启动模式
    int launchMode = aInfo != null? aInfo.launchMode : -1;
    // 如果没有传入 ResolveInfo 对象,则进行 Intent 解析
    if (rInfo == null) {
        rInfo = mService.getPackageManager().resolveActivity(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY |
                ActivityManagerService.STOCK_PM_FLAGS, userId);
    }
    // 根据解析结果获取 ActivityInfo 对象
    if (rInfo != null) {
        aInfo = rInfo.activityInfo;
    } else {
        // 解析失败,返回相应的错误码
        return ActivityManager.START_TARGET_NOT_FOUND;
    }
    // 创建 ActivityRecord 对象
    ActivityRecord r = new ActivityRecord(stack.mService, callerApp, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession,
            voiceInteractor, profilerInfo, clientVisible, clientForeground);
    // 调用 ActivityStack 的 startActivityLocked 方法启动 Activity
    stack.startActivityLocked(r, newTask, doResume);
    return ActivityManager.START_SUCCESS;
}

// ActivityStack 类中的 startActivityLocked 方法
final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
    TaskRecord task = r.task;
    if (newTask) {
        // 如果是新任务,将任务栈移动到前台
        boolean isTop = moveTaskToFrontLocked(task, r, newTask, doResume,
                keepCurTransition, options);
        if (isTop) {
            // 将 Activity 添加到任务栈顶部
            task.addActivityToTop(r);
            r.putInHistory();
        }
    } else {
        // 如果不是新任务,将 Activity 添加到当前任务栈的合适位置
        ActivityRecord last = task.getTopActivity();
        task.addActivityToTop(r);
        r.putInHistory();
        if (last != null) {
            // 暂停当前任务栈的栈顶 Activity
            mService.setActivityPausedLocked(last, true);
        }
    }

    if (doResume) {
        // 如果需要恢复 Activity,调用 resumeTopActivityLocked 方法
        resumeTopActivityLocked(null, r, options);
    }
}

// ActivityStack 类中的 resumeTopActivityLocked 方法
final boolean resumeTopActivityLocked(ActivityRecord prev, ActivityRecord next,
        Bundle options) {
    if (next == null) {
        // 如果没有要恢复的 Activity,返回 false
        return false;
    }

    if (mPausingActivity != null) {
        // 如果有正在暂停的 Activity,等待其暂停完成
        return false;
    }

    // 获取当前聚焦的 Activity
    ActivityRecord top = getTopActivity();
    if (top != null && top != next) {
        // 如果当前聚焦的 Activity 不是要恢复的 Activity,暂停当前聚焦的 Activity
5.3.1 Activity 的启动处理

java

java 复制代码
// ActivityStack类中的resumeTopActivityLocked方法
final boolean resumeTopActivityLocked(ActivityRecord prev, ActivityRecord next,
        Bundle options) {
    if (next == null) {
        // 如果没有要恢复的Activity,返回false
        return false;
    }

    if (mPausingActivity != null) {
        // 如果有正在暂停的Activity,等待其暂停完成
        return false;
    }

    // 获取当前聚焦的Activity
    ActivityRecord top = getTopActivity();
    if (top!= null && top!= next) {
        // 如果当前聚焦的Activity不是要恢复的Activity,暂停当前聚焦的Activity
        pauseTopActivityLocked(top, next, false);
        return false;
    }

    // 检查是否需要等待其他操作完成
    if (mService.isSleepingOrShuttingDownLocked()
            &&!next.isHomeActivity()) {
        return false;
    }

    // 将Activity的状态设置为RESUMED
    next.state = ActivityState.RESUMED;

    // 调用Activity的onResume方法
    mService.startActivityResume(next, options);

    return true;
}

resumeTopActivityLocked方法中,首先判断是否有正在暂停的 Activity 以及当前聚焦的 Activity 是否是要恢复的 Activity,如果不符合条件则进行相应处理。确认无误后,将目标 Activity 的状态设置为RESUMED,并通过ActivityManagerService调用 Activity 的onResume方法,完成 Activity 的启动并显示在屏幕上。

ActivityManagerServicestartActivityResume方法中:

java

java 复制代码
// ActivityManagerService类中的startActivityResume方法
void startActivityResume(ActivityRecord r, Bundle options) {
    try {
        r.app.thread.scheduleResumeActivity(r.token, r.isForward,
                r.configChangeFlags, options);
    } catch (RemoteException e) {
        // 处理远程异常
    }
}

这里通过r.app.threadApplicationThread对象,是应用进程和 AMS 之间通信的桥梁)调用scheduleResumeActivity方法,将启动 Activity 的请求传递到应用进程。

ActivityThreadscheduleResumeActivity方法中:

java

java 复制代码
// ActivityThread类中的scheduleResumeActivity方法
public final void scheduleResumeActivity(IBinder token, boolean isForward,
        int configChanges, Bundle options) {
    updateProcessState(false, false);
    // 创建一个ResumeActivityData对象
    ResumeActivityData args = new ResumeActivityData();
    args.token = token;
    args.isForward = isForward;
    args.configChanges = configChanges;
    args.options = options;
    // 将启动Activity的任务发送到主线程的消息队列中
    sendMessage(H.RESUME_ACTIVITY, args);
}

此方法创建了一个ResumeActivityData对象来封装启动相关参数,并通过sendMessage方法将启动 Activity 的任务发送到主线程的消息队列中,由主线程进行处理。当主线程处理到该消息时,会调用handleResumeActivity方法:

java

java 复制代码
// ActivityThread类中的handleResumeActivity方法
public void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    // 从ActivityRecord中获取Activity对象
    ActivityClientRecord r = mActivities.get(token);
    if (r!= null) {
        // 执行一些准备工作,如检查Activity状态等
        if (!r.activity.mFinished) {
            r.activity.performResume();
            r.stopped = false;
            // 其他处理逻辑,如发送Activity已恢复的通知等
        }
    }
}

handleResumeActivity方法中,获取对应的ActivityClientRecord(它与ActivityRecord相对应,是应用进程中对 Activity 的记录),然后调用 Activity 的performResume方法,在performResume方法内部会调用 Activity 的onResume生命周期方法,从而完成 Activity 的启动显示过程。

5.3.2 Service 的启动与绑定处理

当 Intent 解析结果是一个 Service 时,有启动 Service 和绑定 Service 两种处理方式。

启动 Service 时,在应用中调用startService方法,最终会调用到ActivityManagerServicestartService方法:

java

java 复制代码
// Activity类中的startService方法
public ComponentName startService(Intent service) {
    return startServiceCommon(service, false, mUser);
}
// Activity类中的startServiceCommon方法
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        // 通过ActivityManagerNative获取ActivityManagerService的代理对象并调用startService方法
        ComponentName cn = ActivityManagerNative.getDefault()
               .startService(
                        mMainThread.getApplicationThread(), service,
                        service.resolveTypeIfNeeded(getContentResolver()),
                        requireForeground, getOpPackageName(), user.getIdentifier());
        if (cn!= null) {
            // 检查返回的组件名是否合法等逻辑
        }
        return cn;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}
// ActivityManagerService类中的startService方法
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId) {
    // 检查权限等操作
    enforceNotIsolatedCaller("startService");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startService", null);
    // 调用startServiceLocked方法进行实际的启动操作
    return startServiceLocked(caller, service, resolvedType, requireForeground,
            callingPackage, userId);
}
// ActivityManagerService类中的startServiceLocked方法
private ComponentName startServiceLocked(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId) {
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    userId, true, callerFg);
    ServiceRecord r = res.record;
    if (r!= null) {
        // 处理已存在的Service,如检查是否需要启动等
        if (!r.startRequested) {
            r.startRequested = true;
            r.callStart = true;
            try {
                // 通知应用进程启动Service
                r.app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        requireForeground);
            } catch (RemoteException e) {
                // 处理远程异常
            }
        }
    }
    // 返回启动的Service的组件名等操作
    return new ComponentName(r.serviceInfo.packageName, r.name);
}

在上述流程中,首先进行权限检查,然后通过retrieveServiceLocked方法查找对应的ServiceRecord(与 Activity 的ActivityRecord类似,是对 Service 的记录)。如果找到且该 Service 尚未请求启动,则通知应用进程通过ActivityThreadscheduleCreateService方法创建并启动 Service。

绑定 Service 时,应用中调用bindService方法,最终会调用到ActivityManagerServicebindService方法:

java

java 复制代码
// Activity类中的bindService方法
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    return bindServiceCommon(service, conn, flags, null, mUser);
}
// Activity类中的bindServiceCommon方法
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
        @Nullable String instanceName, UserHandle user) {
    try {
        validateServiceIntent(service);
        IBinder binder = ActivityManagerNative.getDefault()
               .bindService(mMainThread.getApplicationThread(), getActivityToken(), service,
                        service.resolveTypeIfNeeded(getContentResolver()),
                        conn, flags, instanceName, getOpPackageName(), user.getIdentifier());
        if (binder!= null) {
            // 处理绑定成功的情况,如创建ServiceDispatcher等
            ServiceDispatcher sd = new ServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);
            sd.attach(binder);
            return true;
        }
        return false;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}
// ActivityManagerService类中的bindService方法
public IBinder bindService(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, int flags,
        String instanceName, String callingPackage, int userId) {
    // 检查权限等操作
    enforceNotIsolatedCaller("bindService");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "bindService", null);
    // 调用bindServiceLocked方法进行实际的绑定操作
    return bindServiceLocked(caller, token, service, resolvedType, connection,
            flags, instanceName, callingPackage, userId);
}
// ActivityManagerService类中的bindServiceLocked方法
private IBinder bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, int flags,
        String instanceName, String callingPackage, int userId) {
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    userId, true, callerFg);
    ServiceRecord r = res.record;
    if (r!= null) {
        // 处理Service绑定逻辑,如创建ConnectionRecord记录绑定信息等
        ConnectionRecord c = new ConnectionRecord(callingPackage,
                connection, flags, token, false, callerFg, userId);
        r.connections.add(c);
        // 通知应用进程创建Service(如果未创建)并进行绑定相关操作
        try {
            if (!r.created) {
                r.app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        false);
            }
            r.app.thread.scheduleBindService(r, c, flags, instanceName);
        } catch (RemoteException e) {
            // 处理远程异常
        }
    }
    // 返回绑定的Service的代理对象等操作
    return r!= null? r.getIBinder() : null;
}

在绑定 Service 的流程中,同样先进行权限检查,查找对应的ServiceRecord。然后创建ConnectionRecord记录绑定信息,通知应用进程创建 Service(如果未创建)并调用scheduleBindService方法进行绑定操作。

5.3.3 BroadcastReceiver 的广播处理

当发送广播时,例如调用sendBroadcast方法,最终会调用到ActivityManagerServicebroadcastIntent方法:

java

java 复制代码
// ContextWrapper类中的sendBroadcast方法
public void sendBroadcast(Intent intent) {
    mBase.sendBroadcast(intent);
}
// ContextImpl类中的sendBroadcast方法
@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess(this);
        // 通过ActivityManagerNative获取ActivityManagerService的代理对象并调用broadcastIntent方法
        ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId());
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}
// ActivityManagerService类中的broadcastIntent方法
public final int broadcastIntent(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean serialized, boolean sticky, int userId) {
    // 检查权限等操作
    enforceNotIsolatedCaller("broadcastIntent");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "broadcastIntent", null);
    // 调用broadcastIntentLocked方法进行实际的广播发送操作
    return broadcastIntentLocked(caller, intent, resolvedType, resultTo,
            resultCode, resultData, resultExtras, requiredPermissions, appOp,
            bOptions, serialized, sticky, userId);
}
// ActivityManagerService类中的broadcastIntentLocked方法
final int broadcastIntentLocked(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean serialized, boolean sticky, int userId) {
    // 解析广播Intent,获取匹配的BroadcastReceiver列表
    List receivers = collectReceiverComponents(intent, resolvedType,
            userId, true, resolvedType, requiredPermissions);
    // 创建BroadcastRecord记录广播信息
    BroadcastRecord r = new BroadcastRecord(mService, intent, callerApp,
            resolvedType, requiredPermissions, appOp, bOptions,
            receivers, resultTo, resultCode, resultData, resultExtras,
            serialized, sticky, false, userId);
    // 将广播添加到广播队列中
    if (serialized) {
        mFgBroadcastQueue.enqueueBroadcastLocked(r);
    } else {
        mBgBroadcastQueue.enqueueBroadcastLocked(r);
    }
    // 处理广播队列,发送广播给匹配的BroadcastReceiver
    if (!serialized) {
        mBgBroadcastQueue.scheduleBroadcastsLocked();
    } else {
        mFgBroadcastQueue.scheduleBroadcastsLocked();
    }
    return ActivityManager.BROADCAST_SUCCESS;
}

在广播发送流程中,首先进行权限检查,然后通过collectReceiverComponents方法解析广播 Intent,获取匹配的BroadcastReceiver组件列表。接着创建BroadcastRecord记录广播相关信息,并根据广播是否为有序广播(serialized标志)将其添加到前台广播队列(mFgBroadcastQueue)或后台广播队列(mBgBroadcastQueue)中。最后通过scheduleBroadcastsLocked方法处理广播队列,将广播发送给匹配的BroadcastReceiver。当BroadcastReceiver接收到广播时,会在其onReceive方法中进行相应处理。

5.4 处理过程中的数据传递与处理

5.4.1 Activity 间的数据传递

在启动 Activity 时,可以通过 Intent 的putExtra方法传递数据。在目标 Activity 中,可以通过getIntent方法获取传递过来的 Intent,并通过getStringExtragetIntExtra等方法获取相应的数据。

java

java 复制代码
// 启动Activity并传递数据
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("key", "value");
startActivity(intent);

// 在目标Activity中获取数据
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_target);
    Intent receivedIntent = getIntent();
    if (receivedIntent!= null) {
        String data = receivedIntent.getStringExtra("key");
        // 处理获取到的数据
    }
}

ActivityStackSupervisorstartActivityLocked方法中创建ActivityRecord时,会将 Intent 信息保存到ActivityRecord中:

java

java 复制代码
// ActivityStackSupervisor类中的startActivityLocked方法
private int startActivityLocked(IApplicationThread caller, Intent intent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle options, TaskRecord inTask,
        ActivityRecord[] outActivity, int configChanges, boolean onlyIfNeeded,
        int userId, TaskRecord taskToAffiliate, IActivityContainer iContainer,
        Bundle bOptions) {
    // 获取当前用户的ActivityStack
    ActivityStack stack = getFocusedStack();
    // 获取Activity启动模式
    int launchMode = aInfo!= null? aInfo.launchMode : -1;
    // 如果没有传入ResolveInfo对象,则进行Intent解析
    if (rInfo == null) {
        rInfo = mService.getPackageManager().resolveActivity(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY |
                ActivityManagerService.STOCK_PM_FLAGS, userId);
    }
    // 根据解析结果获取ActivityInfo对象
    if (rInfo!= null) {
        aInfo = rInfo.activityInfo;
    }
    // 创建ActivityRecord对象,保存Intent等信息
    ActivityRecord r = new ActivityRecord(stack.mService, callerApp, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession,
            voiceInteractor, profilerInfo, clientVisible, clientForeground);
    // 后续的Activity启动操作...
    return ActivityManager.START_SUCCESS;
}

ActivityThread创建并启动 Activity 时,会将ActivityRecord中的 Intent 传递给 Activity:

java

java 复制代码
// ActivityThread类中的handleLaunchActivity方法
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    // 调用performLaunchActivity方法创建和启动Activity
    Activity a = performLaunchActivity(r, customIntent);
    if (a!= null) {
        // 调用handleResumeActivity方法,将Activity置于恢复状态
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished &&!r.startsNotResumed, r.lastProcessedSeq, reason);
    }
}

// ActivityThread类中的performLaunchActivity方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 获取ActivityInfo,包含Activity的各种信息
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        // 加载应用的包信息
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    // 获取Activity的类名
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    if (r.activityInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        r.activityInfo.applicationInfo.targetSdkVersion = r.activityInfo.targetSdkVersion;
    }

    // 类加载器加载Activity类
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    Activity activity = null;
    try {
        // 使用类加载器创建Activity实例
        java.lang.Class<?> aClass = cl.loadClass(aInfo.name);
        activity = mInstrumentation.newActivity(cl, aInfo.name, r.intent);
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }

    try {
        // 创建Application对象(如果还未创建)
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity!= null) {
            // 创建Context对象
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig!= null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            // 调用Activity的attach方法,将Activity与上下文、窗口等进行关联
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);

            if (customIntent!= null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            // 调用Activity的onCreate方法
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme!= 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            mInstrumentation.callActivityOnCreate(activity, r.state);
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                // 调用Activity的onStart方法
                activity.performStart();
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                if (r.state!= null) {
                    // 恢复Activity的状态
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                // 调用Activity的onPostCreate方法
                mInstrumentation.callActivityOnPostCreate(activity, r.state);
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;
        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }

    return activity;
}

performLaunchActivity方法中,通过activity.attach方法将包含传递数据的Intent对象传递给Activity实例,这样在ActivityonCreate等生命周期方法中就可以通过getIntent获取并处理数据。

5.4.2 Service 与 Activity 间的数据传递

在启动或绑定 Service 时,也可以通过 Intent 传递数据给 Service。在 Service 中,通过onStartCommand(启动 Service 时)或onBind(绑定 Service 时)方法中的 Intent 参数获取数据。

java

java 复制代码
// 启动Service并传递数据
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("service_key", "service_value");
startService(serviceIntent);

// 在Service中获取数据
public class MyService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent!= null) {
            String data = intent.getStringExtra("service_key");
            // 处理获取到的数据
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        if (intent!= null) {
            String data = intent.getStringExtra("service_key");
            // 处理获取到的数据
        }
        return null;
    }
}

ActivityManagerService通知应用进程启动或绑定 Service 时,会将携带数据的 Intent 传递给应用进程中的ActivityThread。在ActivityThread处理 Service 创建和绑定的方法中,如scheduleCreateServicescheduleBindService,会将 Intent 传递给 Service 的创建和绑定逻辑,进而在onStartCommandonBind方法中使用。

5.4.3 广播中的数据传递

发送广播时,可以在 Intent 中添加额外数据,接收广播的BroadcastReceiver通过onReceive方法中的 Intent 参数获取数据。

java

java 复制代码
// 发送广播并传递数据
Intent broadcastIntent = new Intent("com.example.MY_BROADCAST");
broadcastIntent.putExtra("broadcast_key", "broadcast_value");
sendBroadcast(broadcastIntent);

// 接收广播并获取数据
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent!= null && "com.example.MY_BROADCAST".equals(intent.getAction())) {
            String data = intent.getStringExtra("broadcast_key");
            // 处理获取到的数据
        }
    }
}

ActivityManagerService广播 Intent 的流程中,BroadcastRecord会保存包含数据的 Intent。当广播被发送到匹配的BroadcastReceiver时,onReceive方法会接收到这个 Intent,从而获取其中的数据进行处理。

六、Intent 解析与处理中的常见问题及解决方案

6.1 解析失败问题

6.1.1 问题表现

在使用隐式 Intent 时,可能会出现解析失败的情况,导致无法启动预期的组件。例如,应用中发送一个用于分享文本的隐式 Intent,但系统找不到匹配的分享应用,从而无法实现分享功能。

6.1.2 原因分析
  • Intent 配置错误:可能是动作、数据、类别等配置不完整或不匹配。比如,设置了一个自定义动作,但没有任何组件声明能处理该动作。
  • 权限问题:某些组件可能需要特定权限才能被隐式 Intent 启动,如果应用没有获取相应权限,解析会失败。
  • 组件未安装或不可用:目标组件所在的应用可能未安装在设备上,或者由于某些原因(如应用被禁用)不可用。
6.1.3 解决方案
  • 检查 Intent 配置 :仔细检查 Intent 的动作、数据、类别等设置,确保与目标组件的<intent-filter>配置相匹配。例如,分享文本的 Intent,动作应设置为Intent.ACTION_SEND,数据类型设置为text/plain,并添加相应的类别。

java

java 复制代码
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "分享的文本内容");
startActivity(Intent.createChooser(shareIntent, "选择分享应用"));
  • 权限处理:在 AndroidManifest.xml 文件中声明所需权限,并在运行时请求必要的权限(对于 Android 6.0 及以上系统)。例如,如果要启动一个需要读取联系人权限的组件,需在 Manifest 中声明:

xml

java 复制代码
<uses-permission android:name="android.permission.READ_CONTACTS" />

在代码中请求权限:

java

java 复制代码
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
       != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);
} else {
    // 执行启动组件的操作
}
  • 检查组件可用性 :在发送隐式 Intent 之前,可以通过PackageManager检查是否有能处理该 Intent 的组件。例如:

java

java 复制代码
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(shareIntent, 0);
if (activities.size() > 0) {
    startActivity(Intent.createChooser(shareIntent, "选择分享应用"));
} else {
    // 提示用户没有可用的分享应用
}

6.2 数据传递问题

6.2.1 问题表现

在通过 Intent 传递数据时,可能会出现数据丢失、类型不匹配或传递复杂对象失败等问题。比如,传递一个自定义对象时,在接收端无法正确解析。

6.2.2 原因分析
  • 数据类型不支持 :Intent 支持传递基本数据类型及其数组、StringParcelableSerializable类型的数据。如果传递的对象不属于这些类型,会导致传递失败。
  • 序列化与反序列化问题 :对于复杂对象,如自定义类,需要实现ParcelableSerializable接口进行序列化和反序列化。如果接口实现不正确,会导致数据传递错误。
  • 数据大小限制:Intent 传递的数据大小是有限制的,如果传递的数据过大,可能会导致数据丢失或传递失败。
6.2.3 解决方案
  • 使用支持的数据类型 :确保传递的数据类型是 Intent 支持的。如果需要传递自定义对象,将其转换为基本数据类型或实现ParcelableSerializable接口。

  • 正确实现序列化接口 :如果传递自定义对象,实现Parcelable接口通常比Serializable接口效率更高。以实现Parcelable接口为例:

java

java 复制代码
import android.os.Parcel;
import android.os.Parcelable;

public class MyData implements Parcelable {
    private String data;

    public MyData(String data) {
        this.data = data;
    }

    protected MyData(Parcel in) {
        data = in.readString();
    }

    public static final Creator<MyData> CREATOR = new Creator<MyData>() {
        @Override
        public MyData createFromParcel(Parcel in) {
            return new MyData(in);
        }

        @Override
        public MyData[] newArray(int size) {
            return new MyData[size];
        }
    };

    public String getData() {
        return data;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(data);
    }
}

然后在传递和接收数据时:

java

java 复制代码
// 传递数据
MyData myData = new MyData("示例数据");
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("my_data_key", myData);
startActivity(intent);

// 接收数据
MyData receivedData = getIntent().getParcelableExtra("my_data_key");
  • 处理大数据量传递:如果数据量较大,可以考虑使用其他方式传递,如将数据存储在本地文件或数据库中,然后在接收端通过文件路径或数据库查询获取数据。

6.3 组件启动模式与 Intent 交互问题

6.3.1 问题表现

在不同的组件启动模式下(如 Activity 的standardsingleTopsingleTasksingleInstance模式),Intent 的处理结果可能不符合预期。例如,在singleTop模式下,当 Activity 位于栈顶时,新的 Intent 可能没有正确触发onNewIntent方法。

6.3.2 原因分析
  • 对启动模式理解不深入 :不同的启动模式有不同的 Intent 处理逻辑,如果没有正确理解这些逻辑,就容易出现问题。例如,singleTop模式只有当 Activity 位于栈顶且新的 Intent 与栈顶 Activity 匹配时,才会调用onNewIntent方法。
  • Intent 标志位与启动模式冲突 :在设置 Intent 标志位时,如果与组件的启动模式不兼容,可能会导致异常行为。比如,在使用FLAG_ACTIVITY_NEW_TASK标志位启动 Activity 时,如果与singleInstance模式结合,可能会出现意想不到的任务栈变化。
6.3.3 解决方案
  • 深入理解启动模式 :仔细研究不同启动模式下 Intent 的处理机制。对于singleTop模式,确保在需要处理新 Intent 时,Activity 确实位于栈顶且匹配。在 Activity 中可以通过重写onNewIntent方法来处理新的 Intent:

java

java 复制代码
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
    // 处理新的Intent数据
}
  • 合理使用 Intent 标志位 :在设置 Intent 标志位时,充分考虑组件的启动模式。例如,如果要在新任务栈中启动 Activity,可以使用FLAG_ACTIVITY_NEW_TASK标志位,但要注意与 Activity 的启动模式协同工作。如果 Activity 是singleTask模式,使用FLAG_ACTIVITY_NEW_TASK时要确保任务栈的创建和管理符合预期。

七、总结与展望

7.1 总结

Android Activity 意图(Intent)解析与处理模块是实现组件间通信和交互的基石,其功能强大且机制复杂。从 Intent 的基础概念,包括组件名、动作、数据、类别、类型和额外数据等组成部分,到其创建、设置、序列化与反序列化操作,我们逐步深入了解了 Intent 的基本特性和使用方式。

在解析过程中,隐式 Intent 通过 PackageManagerService 进行复杂的匹配操作,依据动作、类别、数据等信息在系统维护的组件列表中寻找最佳匹配的组件,解析结果存储在 ResolveInfo 中,而显式 Intent 则直接根据组件名快速定位。解析完成后,根据解析结果,ActivityManagerService、ActivityThread 等核心组件协同工作,完成 Activity、Service、BroadcastReceiver 等组件的启动、绑定或广播接收处理,同时在处理过程中实现了数据在组件间的传递。

然而,在实际开发中,我们也遇到了诸如解析失败、数据传递问题以及组件启动模式与 Intent 交互异常等常见问题。通过深入分析这些问题的原因,我们找到了对应的解决方案,如检查 Intent 配置、处理权限、正确实现序列化接口、合理使用启动模式和 Intent 标志位等。

7.2 展望

随着 Android 系统的持续演进,Intent 解析与处理模块也将不断发展。从性能优化角度看,未来可能会进一步提升解析速度,减少资源消耗,特别是在设备配置多样化、应用数量剧增的情况下,更高效的解析算法将成为关键。在功能拓展方面,随着新的交互模式和应用场景的出现,Intent 可能会支持更多的数据类型或传递方式,以满足开发者更复杂的组件通信需求。

此外,随着 Android Jetpack 等架构组件的推广,Intent 的使用方式可能会与这些组件深度融合,为开发者提供更简洁、高效且安全的组件间通信方案。例如,借助 ViewModel 等组件,可以更好地管理通过 Intent 传递的数据与应用状态的关系,减少数据丢失和不一致问题。开发者也需要持续关注系统更新,深入理解 Intent 机制的变化,以便在开发中充分利用新特性,构建更优质、稳定的 Android 应用。

相关推荐
jiet_h1 小时前
使用 Ktor 构建现代 Android 应用的后端服务
android
深漂阿碉3 小时前
Android studio2024的第一个安卓项目
android
zilong_zzz4 小时前
文件IO4(提高LCD显示效率/BMP图像原理与应用)
android
_一条咸鱼_4 小时前
大厂Android面试秘籍:Activity 窗口管理模块(四)
android·面试·android jetpack
黑客老李5 小时前
面试经验分享 | 成都渗透测试工程师二面面经分享
经验分享·面试·职场和发展
狂炫一碗大米饭5 小时前
快刷每日面经😋
前端·面试
无极程序员7 小时前
远程主机可能不符合glibc和libstdc++ VS Code服务器的先决条件
android·java·运维·服务器·php
Yharim8 小时前
AllData数据中台源码分析
java·面试
快乐1018 小时前
Mac下FFmpeg编译和集成
android
就是我8 小时前
3种必须知道的JavaScript异步编程模型
前端·javascript·面试