在Android Market上有一款非常實用的小軟體:Download Crutch。
它解決的基本問題是這樣:Android的預設瀏覽器,在下載檔案時,會驗證MimeType,如果這個MimeType不被“識別”,那麼Download Manager會拒絕對其進行下載。Download Crutch可以讓Download Manager不管是否是可識別的MimeType都進行下載。
凡是掛入系統的應用,走讓人覺得很神奇。而Download Crutch這個小軟體,更是實現的非常巧妙,理論上講,它可以一行代碼都不寫就實現這個功能。
想要探究Download Crutch的工作原理,我們就要從Browser和Download Manager的工作原理說起。
Browser的核心是WebView組件,它負責處理所有WebView可以接受(或者說顯示)的檔案類型。比如HTML頁面,或者各種Image。當WebView遇到一個他不認識的MimeType時,比如application/zip,它就會把它提交給DownloadManager,請求DownloadManager進行下載。
DownloadManager在接收到下載請求的時候,並會立即啟動HTTP線程進行下載,它先會構造一個Intent,詢問系統內是否有某個應用程式對這個要下載的檔案類型該興趣(或者說,可以在下載後處理這種檔案類型)。如果回應的結果是沒有哪個應用程式處理這個MimeType,那麼DownloadManager會拒絕下載這個檔案。關鍵代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * file: DownloadService.java * package: com.android.providers.downloads */ Intent mimetypeIntent = new Intent(Intent.ACTION_VIEW); mimetypeIntent.setDataAndType(Uri.fromParts("file", "", null), info.mimetype); ResolveInfo ri = getPackageManager().resolveActivity(mimetypeIntent, PackageManager.MATCH_DEFAULT_ONLY); //如果找不到ResolveInfo,則認為沒有應用程式可以處理這種mimetype。 //下載工作將被終止 if (ri == null) { …… return; } |
所以,要想解決DownloadManager拒絕下載的問題,只需要編寫一個應用程式,告訴系統所有的MimeType我都能處理,你就儘管下吧。於是就誕生了DownloadCrutch。
要實現DownloadCrutch的功能,只需要建立一個Android Project,編寫一個空的Activity,命名為DownloadCrutch,並且在AndroidManifest.xml裡進行註冊。關鍵代碼如下
1 2 3 4 5 6 7 8 |
<activity android:name=".DownloadCrutch"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:mimeType="*/*" /> </intent-filter> </activity> |
其中,android:scheme標記對file://xxxxx的URI結構進行處理,android:mimeType標記可以處理任意類型的檔案。
怎麼樣,一行java代碼都不用寫,就可以實現這個功能吧。但是DownloadCrutch也寫了一些Java代碼,這也是一種很無奈的選擇,因為DownloadManager在現在完成後,會拉起能處理此MimeType的應用程式來處理該檔案,如果你一行代碼也不寫,那麼會拉起一個黑視窗的Activity,使用者體驗太差,所以DownloadCrutch在代碼裡加了個小Toast,提示使用者:“俺只管讓它下載下來,怎麼處理你自己解決吧”。