深入剖析 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/plain
、image/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 :调用
startService
或bindService
方法启动或绑定一个 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 时,最终会调用到 ActivityManagerService
的 startActivity
方法。在这个过程中,如果是隐式 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
方法时,经过一系列调用,最终会在 ActivityStackSupervisor
的 startActivityLocked
方法中进行 Intent 解析。如果没有传入 ResolveInfo
对象,则会调用 PackageManager
的 resolveActivity
方法进行解析。
4.3.2 PackageManager 的 resolveActivity 方法
PackageManager
的 resolveActivity
方法是 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
对象中,包含了匹配到的组件的信息。在 ActivityStackSupervisor
的 startActivityLocked
方法中,会根据解析结果获取 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 的启动处理流程。在 ActivityStackSupervisor
的 startActivityLocked
方法中,会创建 ActivityRecord
对象,并调用 ActivityStack
的 startActivityLocked
方法进行 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 的启动并显示在屏幕上。
在ActivityManagerService
的startActivityResume
方法中:
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.thread
(ApplicationThread
对象,是应用进程和 AMS 之间通信的桥梁)调用scheduleResumeActivity
方法,将启动 Activity 的请求传递到应用进程。
在ActivityThread
的scheduleResumeActivity
方法中:
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
方法,最终会调用到ActivityManagerService
的startService
方法:
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 尚未请求启动,则通知应用进程通过ActivityThread
的scheduleCreateService
方法创建并启动 Service。
绑定 Service 时,应用中调用bindService
方法,最终会调用到ActivityManagerService
的bindService
方法:
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
方法,最终会调用到ActivityManagerService
的broadcastIntent
方法:
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,并通过getStringExtra
、getIntExtra
等方法获取相应的数据。
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");
// 处理获取到的数据
}
}
在ActivityStackSupervisor
的startActivityLocked
方法中创建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
实例,这样在Activity
的onCreate
等生命周期方法中就可以通过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 创建和绑定的方法中,如scheduleCreateService
和scheduleBindService
,会将 Intent 传递给 Service 的创建和绑定逻辑,进而在onStartCommand
和onBind
方法中使用。
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 支持传递基本数据类型及其数组、
String
、Parcelable
和Serializable
类型的数据。如果传递的对象不属于这些类型,会导致传递失败。 - 序列化与反序列化问题 :对于复杂对象,如自定义类,需要实现
Parcelable
或Serializable
接口进行序列化和反序列化。如果接口实现不正确,会导致数据传递错误。 - 数据大小限制:Intent 传递的数据大小是有限制的,如果传递的数据过大,可能会导致数据丢失或传递失败。
6.2.3 解决方案
-
使用支持的数据类型 :确保传递的数据类型是 Intent 支持的。如果需要传递自定义对象,将其转换为基本数据类型或实现
Parcelable
、Serializable
接口。 -
正确实现序列化接口 :如果传递自定义对象,实现
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 的standard
、singleTop
、singleTask
、singleInstance
模式),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 应用。