该项目涉及修改Android以阻止/拒绝特定应用程序的启动。因此,如果用户尝试通过任何方式启动任何预先列出的应用程序,则该应用程序都不会启动。
我将修改Android源代码。有哪些不同的方法?欢迎提出建议。
我认为这样做的一种可能方法是在Process.java
中修改frameworks/base/core/java/android/os
。
此类具有start
函数,该函数接收uid
作为输入参数。我认为,通过此参数,我们可以了解正在为哪个应用创建新流程。这是正确的方法吗?
另外,由于使用意图启动应用程序,是否有可能(通过修改任何类)删除特定意图?
最佳答案
通常,当意图可以由应用程序(其活动,服务)处理,并且用户希望该应用程序来处理它时。 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中的意图未设置标志FLAG_RECEIVER_located_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
。处理方式相同。