日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

使用Android内部的DownloadProvider下载文件,并获取cache权限 .

發(fā)布時間:2025/4/5 Android 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Android内部的DownloadProvider下载文件,并获取cache权限 . 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Android內(nèi)部提供了一個DownloadProvider,是一個非常完整的下載工具,提供了很好的外部接口可以被其他 應(yīng)用程序調(diào)用,來完成下載工作。同時也提供和很好的下載、通知、存儲等機制。
在Android的Browser等工具里面都用到了這個DownloadProvider。

但是很遺憾的是,這個DownloadProvider不對app開發(fā)人員開放,只作為內(nèi)部使用。

我們現(xiàn)在去探究如何將DownloadProvider拿來給自己用。

讓我們先找到DownloadProvider不能用的原因:
先找到它的源代碼,在這個位置:/packages/providers/DownloadProvider
打開AndroidManifest.xml文件,里面有幾個自定義的權(quán)限

??? <!-- Allows access to the Download Manager -->
??? <permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"
??????? android:label="@string/permlab_downloadManager"
??????? android:description="@string/permdesc_downloadManager"
??????? android:protectionLevel="signatureOrSystem" />

??? <!-- Allows advanced access to the Download Manager -->
??? <permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED"
??????? android:label="@string/permlab_downloadManagerAdvanced"
??????? android:description="@string/permdesc_downloadManagerAdvanced"
??????? android:protectionLevel="signatureOrSystem" />

??? <!-- Allows filesystem access to /cache -->
??? <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
??????? android:label="@string/permlab_cacheFilesystem"
??????? android:description="@string/permdesc_cacheFilesystem"
??????? android:protectionLevel="signature" />

??? <!-- Allows to send download completed intents -->
??? <permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
??????? android:label="@string/permlab_downloadCompletedIntent"
??????? android:description="@string/permdesc_downloadCompletedIntent"
??????? android:protectionLevel="signature" />

這幾個權(quán)限里面都是android:protectionLevel="signatureOrSystem" 或者?? android:protectionLevel="signature", 這個意思是只有你的app擁有system權(quán)限,或者和系統(tǒng)一樣的簽名,才能調(diào)用它。

這里是問題的關(guān)鍵。那我們有兩種思路:
一種思路是:將這個protectionLevel改成normal,重新編譯DownloadProvider工程,讓其他app可以直接調(diào)用。
另一種思路是:將你自己的app弄成system權(quán)限或者和系統(tǒng)一樣的簽名。

前一種思路已經(jīng)完全成功了,第二種思路驗證了一部分。

先看第一種思路的辦法:
1)先將上面幾個權(quán)限都改成:android:protectionLevel="normal"
2)重新編譯DownloadProvider
?? mmm packages/providers/DownloadProvider
3) 將編譯后的apk替換現(xiàn)有的apk
?? 因為DownloadProvider.apk是系統(tǒng)app,你可以先給/system以root權(quán)限,然后將這個app替換掉。 (作為一個用戶app安裝也可以,不過重啟以后就沒有了)
?? 使用類似 # mount -t ubifs -o remount ubi0:system /system?? 或者? # mount -o remount ubi0:system /system? 給/system rw權(quán)限。
?? 然后通過adb push 將DownloadProvider.apk push到 /system/app/下。系統(tǒng)會自動替換這個app。

4)寫一個工程來使用DownloadProvider.
?? 直接貼源碼了:
?? DownloadActivity.Java


package com.xxxx.usedownload;
?
import java.io.FileNotFoundException;
import java.NET.URI;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.URLUtil;

/**
?* @author lixinso
?* 使用DownloadProvider
?*/
public class DownloadActivity extends Activity {
???? @Override
??? public void onCreate(Bundle savedInstanceState) {
??????? super.onCreate(savedInstanceState);
??????? setContentView(R.layout.main);
???????
??????? //String url = "http://192.168.200.76:8080/webserver/dancing-skeleton.3gp";
??????? String contentDisposition = "attachment; filename=/"dancing-skeleton.3gp/"";
??????? String mimetype = "video/3GPP";
???????
??????? String filename = URLUtil.guessFileName(url,contentDisposition, mimetype);
???????
??????? URI uri = null;
????????
??????? try {
??????????? // Undo the percent-encoding that KURL may have done.
??????????? String newUrl = new String(URLUtil.decode(url.getBytes()));
??????????? // Parse the url into pieces
??????????? WebAddress w = new WebAddress(newUrl);
??????????? String frag = null;
??????????? String query = null;
??????????? String path = w.mPath;
??????????? // Break the path into path, query, and fragment
??????????? if (path.length() > 0) {
??????????????? // Strip the fragment
??????????????? int idx = path.lastIndexOf('#');
??????????????? if (idx != -1) {
??????????????????? frag = path.substring(idx + 1);
??????????????????? path = path.substring(0, idx);
??????????????? }
??????????????? idx = path.lastIndexOf('?');
??????????????? if (idx != -1) {
??????????????????? query = path.substring(idx + 1);
??????????????????? path = path.substring(0, idx);
??????????????? }
??????????? }
??????????? uri = new URI(w.mScheme, w.mAuthInfo, w.mHost, w.mPort, path,
??????????????????? query, frag);
??????? } catch (Exception e) {
??????????? //Log.e(LOGTAG, "Could not parse url for download: " + url, e);
??????????? return;
??????? }
???????
??????? ContentValues values = new ContentValues();
??????? values.put("uri", uri.toString());
??????? values.put("useragent", "Mozilla/5.0 (linux; U; Android 1.5; en-us; SDK Build/CUPCAKE) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1");
??????? values.put("notificationpackage", getPackageName());
??????? values.put("notificationclass", "HelloWorld");
??????? values.put("visibility", 1);
??????? values.put("mimetype", mimetype);
??????? values.put("hint", filename);
??????? values.put("description", uri.getHost());
??????? values.put("total_bytes", 1349528);
??????? values.put("destination", 1);
???????
???????
????????
??????? //這些參數(shù)參考:DownloadProvider工程中的:Helpers.java
??????? //public static DownloadFileInfo generateSaveFile(
??????? //??????? Context context,
??????? //????? String url,
??????? //??????? String hint,
??????? //??????? String contentDisposition,
??????? //??????? String contentLocation,
??????? //??????? String mimeType,
??????? //??????? int destination,
??????? //??????? int contentLength) throws FileNotFoundException {
??????? //以及:? framework里的Downloads.java;
???????
???????
??????? ContentResolver mResolver = getContentResolver();
??????? mResolver.insert(Uri.parse("content://downloads/download"), values);
???????
??? }
}

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
????? package="com.xxxx.usedownload"
????? android:versionCode="1"
????? android:versionName="1.0">
??? <application android:icon="@drawable/icon" android:label="@string/app_name">
??????? <activity android:name=".DownloadActivity"
????????????????? android:label="@string/app_name">
??????????? <intent-filter>
??????????????? <action android:name="android.intent.action.MAIN" />
??????????????? <category android:name="android.intent.category.LAUNCHER" />
??????????? </intent-filter>
??????? </activity>
?
??? </application>
??? <uses-sdk android:minSdkVersion="7" />
???
??? <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
??? <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
??? <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
??? <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" />
??? <uses-permission android:name="android.permission.ACCESS_DRM" />
???? <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
??? <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
??? <uses-permission android:name="android.permission.INTERNET" />
??? <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
??? <uses-permission android:name="android.permission.INSTALL_DRM" />
???
</manifest>

代碼里面引用了ParseException和WebAddress兩個類,可以從Android源代碼里找到copy進來,在這里frameworks/base/core/java/android/net。

代碼里面有幾個地方比較重要的:
a) 通過往DownloadProvider提供的ContentProvider “content://downloads/download” 中插入數(shù)據(jù)就能觸發(fā)DownloadProvider的執(zhí)行。
b) values.put("destination", 1); 是下載文件存儲在什么地方, 如果沒有這個參數(shù),默認保存在sdcard的download 下面 (Constants.java 中的 DEFAULT_DL_SUBDIR = "/download" )
?? 如果指定為1,是往內(nèi)存的 /cache目錄下存東西 (在/frameworks/base/core/java/android/provider/Downloads.java中定義, public static final int DESTINATION_CACHE_PARTITION = 1; )
b) 注意Manifest中的一堆權(quán)限: ACCESS_DOWNLOAD_MANAGER是最基本的權(quán)限,這樣可以使用DownloadProvider下載。
?? 如果需要destination=1,則需要 ACCESS_DOWNLOAD_MANAGER權(quán)限。(Downloads.java中的注釋 : All file types are allowed, and only the initiating
???? application can access the file (indirectly through a content provider). This requires the android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED permission.)

如果沒有這個權(quán)限,在往 content://downloads/download插入的時候有權(quán)限問題報錯:
09-16 17:16:38.062: ERROR/DatabaseUtils(763): Writing exception to parcel
09-16 17:16:38.062: ERROR/DatabaseUtils(763): java.lang.SecurityException: unauthorized destination code
09-16 17:16:38.062: ERROR/DatabaseUtils(763):???? at com.android.providers.downloads.DownloadProvider.insert(DownloadProvider.java:277)
09-16 17:16:38.062: ERROR/DatabaseUtils(763):???? at android.content.ContentProvider$Transport.insert(ContentProvider.java:150)
09-16 17:16:38.062: ERROR/DatabaseUtils(763):???? at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:140)
09-16 17:16:38.062: ERROR/DatabaseUtils(763):???? at android.os.Binder.execTransact(Binder.java:287)
09-16 17:16:38.062: ERROR/DatabaseUtils(763):???? at dalvik.system.NativeStart.run(Native Method)
09-16 17:16:38.102: DEBUG/AndroidRuntime(4086): Shutting down VM

因為DownloadProvider.java中有這段代碼:
??????? if (dest != null) {
??????????? if (getContext().checkCallingPermission(Downloads.PERMISSION_ACCESS_ADVANCED)
??????????????????? != PackageManager.PERMISSION_GRANTED
??????????????????? && dest != Downloads.DESTINATION_EXTERNAL
??????????????????? && dest != Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE) {
??????????????? throw new SecurityException("unauthorized destination code");
??????????? }
所以:要往/cache目錄下存東西,一定要記得這個權(quán)限哦。

實際運行起來,只加這個權(quán)限往/cache下存東西還不夠,就又把其他一堆權(quán)限都加上了,具體哪些有用還沒細看。

5) 將這個app直接以普通app安裝上去,運行,可以看到下載成功到/cache里了。


第二種思路就是想辦法獲得system權(quán)限或者簽名:
這樣不修改DownloadProvider的代碼,不動它。
而是將自己編寫的app做完以后放到/packages/app目錄下和整個系統(tǒng)一起編譯,將其編譯到img中的系統(tǒng)app下 這樣編譯完成以后運行,使用編譯的img運行模擬器。在模擬器中啟動自己寫的調(diào)用DownloadProvider的app,發(fā)現(xiàn)竟然也是可以調(diào)用的。
不過這種方法在模擬器上成功了,但是在真機上沒成功,可能還有些問題沒解決。第一種方法是完全成功的。

總結(jié)

以上是生活随笔為你收集整理的使用Android内部的DownloadProvider下载文件,并获取cache权限 .的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美日韩美女 | 打美女白嫩屁屁网站 | 青青草免费观看 | 蜜桃av影视 | 亚洲射射射 | 91亚洲精品国偷拍 | 久久久av一区二区三区 | 色婷婷综合久久久久中文字幕 | 精品在线观看一区 | 超碰66| 国产三级一区二区三区 | 天天看天天干 | 精品久久久99 | 欧美日本一道 | videos另类灌满极品另类 | 中文免费视频 | 久久噜 | 美女涩涩视频 | 国产成人77亚洲精品www | 天天操网站 | 99精品久久久久久中文字幕 | ww成人| 久久最新 | 国产伦精品一区二区三区视频我 | 日p视频在线观看 | 波多野结衣50连登视频 | 久久97精品久久久久久久不卡 | 日韩av在线一区二区 | 欧美性生活一区二区三区 | 91在线视频免费看 | 爱爱的网站 | 伊人365| 精品婷婷色一区二区三区蜜桃 | 国产精品久久久久久久久久久久 | 日韩视频一区二区三区四区 | 一区二区三区在线观看免费视频 | 国产蜜臀在线 | 精品国产精品国产偷麻豆 | 老司机在线精品视频 | 欧美午夜理伦三级在线观看 | www国产成人| 在线免费a视频 | 亚洲av成人片色在线观看高潮 | 雪花飘电影在线观看免费高清 | 国产综合图片 | 日本黄色一级视频 | 香蕉蜜桃视频 | www黄色com| 免费在线色 | a国产免费| 爱草av | 亚洲视频自拍 | 超碰一区二区 | 麻豆久久久9性大片 | 天堂网ww| av日韩在线播放 | 蜜桃精品一区二区 | 悟空影视大全免费高清观看在线 | 亚洲爱情岛论坛永久 | 久久久久玖玖 | www久久久久久 | 夜夜草天天干 | 色哟哟精品一区 | 美日韩丰满少妇在线观看 | 色呦呦一区| 男女啪啪网站 | www.av88 | 精品一区在线视频 | 亚洲精品一卡二卡 | 国产精品羞羞答答 | 成人音影 | 97超碰福利 | 欧美 日本 国产 | 日本黄色一级视频 | 国产三级日本三级在线播放 | 欧美成人亚洲 | 蜜臀久久99精品久久久 | 国产亚洲av综合人人澡精品 | 少妇高潮av久久久久久 | 国产欧美激情在线观看 | 中文有码在线播放 | 青青草视频污 | 日韩视频在线观看免费 | 99精品人妻无码专区在线视频区 | 98国产精品| 国产精品高潮呻吟av | 桃色网站在线观看 | 国产精品69久久久久 | 天堂av官网 | 亚洲精品久久夜色撩人男男小说 | 免费在线播放av | 尹人综合| 少妇高潮av| 最新av免费在线观看 | 日韩视频欧美视频 | 欧美国产日本在线 | 欧美影视一区二区 | 波多野结衣视频在线观看 | 国产成人毛毛毛片 |