该项目涉及修改Android以阻止/拒绝启动特定应用程序。因此,如果用户尝试以任何方式启动任何预先列出的应用程序,则该应用程序不应启动。
我将修改Android源代码。有什么不同的方法呢?欢迎提出建议。
我认为其中一种可能的方法是修改Process.java
中的frameworks/base/core/java/android/os
。
该类具有start
函数,该函数接收uid
作为输入参数。我想从这个参数我们可以知道正在创建哪个应用程序新进程。这是正确的方法吗?
此外,由于使用意图启动应用程序,是否可以(通过修改任何类)删除特定意图?
答案 0 :(得分:2)
通常,当应用程序(其活动,服务)可以处理意图时,用户更喜欢该应用程序来处理它。 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将在resolveIntent
中致电PackageManagerService
以获取要开始的活动。对于服务,调用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
,可以轻松地从ResolveInfo获取ApplicationInfo。
对于接收器来说,它更复杂,因为在AndroidManifest.xml和registerReceiver(...)
中注册的接收器是不同的。如果broadcastIntent中的intent没有设置标志FLAG_RECEIVER_REGISTERED_ONLY(常见情况),则解析结果将是监听该广播的接收器列表,其可以包含两种接收器。对于那些在AndroidManifest.xml中的人,Ams将调用queryIntentReceiver
中的PackageManagerService
来获取收听广播的接收者列表。对于registerReciever(...)
动态注册的用户,它们由ActivityManagerService
而非PackageManagerService
管理,因此Ams将直接呼叫mReceiverResolver.queryIntent
以获取这些接收者。 mReceiverResolver
定义为:
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...
}
因此,您需要做的是覆盖queryIntent方法以过滤掉应用程序中的接收器。对于ContentProvider,该方法在resolveContentProvider
中为PackageManagerService
。处理它的方式相同。