2013-04-25 66 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