2013-04-25 68 views
1

该项目涉及修改Android阻止/拒绝启动特定应用程序。因此,如果用户试图以任何方式启动任何预先列出的应用程序,则该应用程序不应启动。阻止Android中的特定应用程序(通过修改源代码)

我将修改Android源代码。有什么不同的方式来做到这一点?欢迎提出建议。

我认为可能的方法之一是修改Process.javaframeworks/base/core/java/android/os。 该类别具有start功能,它接收uid作为输入参数。我认为从这个参数我们可以知道哪些应用程序正在创建新的进程。这是做到这一点的正确方法吗?

另外,作为应用在使用意图启动,是否有可能(通过修改任何类),除去特别意图?

+1

防止安装这些黑名单应用程序不是更好吗? – SimonSays 2013-04-25 18:56:40

+0

阻塞只能在特定的时间段内完成(比如从早上9点到下午5点)。除了这个时间间隔,用户可以使用该应用程序。 – user1010 2013-04-25 19:56:50

回答

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框架需要确定哪个活动/服务可以处理这个意图。如果有多个选择,用户未设置任何偏好,然后会出现如下对话框:

Intent Handling

因此,它是可以修改的解析过程,让Android框架丢弃的事实,你的特定的应用程序能够处理该意图。我认为这也是一种完成工作的方式,但它更加复杂化,因为Android针对活动,服务和接收方以不同方式解决意图。对于活动,Ams将拨打以获取要开始的活动。对于服务,这是调用PackageManagerService中的resolveService方法。所以你需要以不同的方式处理它们。但是,由于他们都会在其实现中获得ResolveInfo的列表,因此您可以轻松筛选出您的应用程序。例如,在resolveIntentPackageManagerService

@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。同样的方式来处理它。

+0

哇,相当不错的解释!谢谢。读完这个之后,我认为在Ams中修改'Process'相关的函数更容易,而不是重写与意图相关的函数。 – user1010 2013-04-26 04:54:47