一般地,当意图可由应用程序(其活性,服务)来处理,并且用户更喜欢的应用来处理它。 Android框架中的ActivityManagerService(Ams)
将首先查看目标活动/服务的相应应用程序是否仍然存在。如果尚未开始或被杀死,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将拨打以获取要开始的活动。对于服务,这是调用PackageManagerService
中的resolveService
方法。所以你需要以不同的方式处理它们。但是,由于他们都会在其实现中获得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的ApplicationInfo如果你看一看ResolveInfo.java
。
对于接收者来说,它更加复杂,因为在AndroidManifest.xml和registerReceiver(...)
中注册的接收者是不同的。如果broadcastIntent中的intent没有设置标志FLAG_RECEIVER_REGISTERED_ONLY(普通情况),那么解析结果将是一个收听广播的接收者列表,它可能包含两种接收者。对于AndroidManifest.xml中的人员,Ams将拨打以获取收听广播的接收者列表。对于由registerReciever(...)
动态注册的用户,他们由ActivityManagerService
而不是PackageManagerService
管理,因此Ams将直接拨打mReceiverResolver.queryIntent
来获取这些接收者。该mReceiverResolver
定义为:
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...
}
所以,你需要做的就是重写queryIntent方法在你的应用程序来过滤接收器的东西。对于ContentProvider,该方法是PackageManagerService
中的resolveContentProvider
。同样的方式来处理它。
防止安装这些黑名单应用程序不是更好吗? – SimonSays 2013-04-25 18:56:40
阻塞只能在特定的时间段内完成(比如从早上9点到下午5点)。除了这个时间间隔,用户可以使用该应用程序。 – user1010 2013-04-25 19:56:50