通常,当应用程序(其活动、服务)可以处理意图并且用户更喜欢该应用程序来处理它时。在ActivityManagerService(Ams)
Android框架中会先看目标activity/service对应的应用是否还活着。如果尚未启动或终止,则 Ams 将通过调用startProcessLocked
方法启动该应用程序。
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated) {
//you can get the uid from ApplicationInfo.uid
...
startProcessLocked(app, hostingType, hostingNameStr);
...
}
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
//prepare its uid, gid, gids for starting that process
...
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
...
}
所以在那个方法中,它开始了一个新的过程。这Process.start
就是您在问题中提到的,它最终调用 Zygote 来分叉一个新进程。
我觉得在ams中截取应用程序启动过程是比较好的方法。您可以获得有关此应用程序的更多信息,它也是您Process.start
方法的上游。
更新:
刚刚注意到您正在考虑限制意图。一个意图可以由多个应用程序处理,因此我们不能限制应用程序发送特定的意图。但是我们可以修改解析过程。Resolving
意味着 Android 框架需要确定哪个活动/服务可以处理这个意图。如果有多个选择并且用户没有设置任何偏好,则会出现以下对话框:
因此,可以修改解析过程,让 Android 框架放弃您的特定应用程序能够处理该意图的事实。我认为这也是一种完成工作的方式,但它更加复杂,因为 Android 以不同的方式解析活动、服务和接收者的意图。对于活动,Ams 将调用resolveIntent
以PackageManagerService
获取要开始的活动。对于服务,它是get调用的resolveService
方法。PackageManagerService
所以你需要以不同的方式处理它们。但是因为他们都会在他们的实现中得到一个 ResolveInfo 的列表,所以你可以很容易地过滤掉你的应用程序。例如,在resolveIntent
中PackageManagerService
:
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
//filter out here!!!!
return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
如果您查看ResolveInfo.java
.
对于receiver来说就更复杂了,因为AndroidManifest.xml中注册的receiver和byregisterReceiver(...)
是不同的。如果broadcastIntent 中的intent 没有设置标志FLAG_RECEIVER_REGISTERED_ONLY(常见情况),那么解析结果将是一个收听该广播的接收者列表,其中可能包含两种接收者。对于 AndroidManifest.xml 中的那些,Ams 将调用queryIntentReceiver
以PackageManagerService
获取收听广播的接收者列表。对于由 动态注册的registerReciever(...)
,它们是由ActivityManagerService
not管理的PackageManagerService
,所以 Ams 会直接调用mReceiverResolver.queryIntent
来获取那些接收者。mReceiverResolver
定义为:
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...
}
因此,您需要做的是重写 queryIntent 方法以过滤掉应用程序中的接收者。对于 ContentProvider,该方法resolveContentProvider
位于PackageManagerService
. 同样的处理方式。