如何从 webview Android 下载文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21864098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to download files from webview Android?
提问by Dritan Berna
My code below loads the url page fine and after searching for a song when I click on the download link it crashes. There aren't so much tutorials on how to get the download manager to work with a webview. What am I doing wrong?
我下面的代码可以很好地加载 url 页面,并且在我单击下载链接时搜索歌曲后崩溃了。关于如何让下载管理器使用 webview 的教程并不多。我究竟做错了什么?
import java.io.File;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class List1 extends Activity {
WebView ourBrow;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Use a custom layout file
setContentView(R.layout.list1);
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final File destinationDir = new File (Environment.getExternalStorageDirectory(), getPackageName());
if (!destinationDir.exists()) {
destinationDir.mkdir(); // Don't forget to make the directory if it's not there
}
ourBrow = (WebView) findViewById(R.id.wvBrowser);
ourBrow.getSettings().setJavaScriptEnabled(true);
ourBrow.setInitialScale(50);
ourBrow.getSettings().setUseWideViewPort(true);
ourBrow.setVerticalScrollBarEnabled(false);
ourBrow.setHorizontalScrollBarEnabled(false);
ourBrow.loadUrl("http://www.degjo.com");
ourBrow.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
boolean shouldOverride = false;
// We only want to handle requests for mp3 files, everything else the webview
// can handle normally
if (url.endsWith(".mp3")) {
shouldOverride = true;
Uri source = Uri.parse(url);
// Make a new request pointing to the mp3 url
DownloadManager.Request request = new DownloadManager.Request(source);
// Use the same file name for the destination
File destinationFile = new File (destinationDir, source.getLastPathSegment());
request.setDestinationUri(Uri.fromFile(destinationFile));
// Add it to the manager
manager.enqueue(request);
}
return shouldOverride;
}
});
}
}
LogCat
日志猫
02-18 19:45:44.891: E/AndroidRuntime(357): at android.content.ContentProviderProxy.insert(ContentProviderNative.java:408)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.content.ContentResolver.insert(ContentResolver.java:604)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.app.DownloadManager.enqueue(DownloadManager.java:750)
02-18 19:45:44.891: E/AndroidRuntime(357): at com.example.androidbuttonsactivities.List1.shouldOverrideUrlLoading(List1.java:78)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java:216)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:323)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.os.Handler.dispatchMessage(Handler.java:99)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.os.Looper.loop(Looper.java:123)
02-18 19:45:44.891: E/AndroidRuntime(357): at android.app.ActivityThread.main(ActivityThread.java:3683)
02-18 19:45:44.891: E/AndroidRuntime(357): at java.lang.reflect.Method.invokeNative(Native Method)
02-18 19:45:44.891: E/AndroidRuntime(357): at java.lang.reflect.Method.invoke(Method.java:507)
02-18 19:45:44.891: E/AndroidRuntime(357): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-18 19:45:44.891: E/AndroidRuntime(357): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-18 19:45:44.891: E/AndroidRuntime(357): at dalvik.system.NativeStart.main(Native Method)
02-18 19:45:48.401: I/Process(357): Sending signal. PID: 357 SIG: 9
回答by Brendon
It may be depends on the android build version problem, the below code will work successfully on 2.3+ builds, check this out,
这可能取决于 android 构建版本问题,以下代码将在 2.3+ 构建上成功运行,请查看,
ourBrow.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Log.d("WEB_VIEW_TEST", "error code:" + errorCode + " - " + description);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// handle different requests for different type of files
// this example handles downloads requests for .apk and .mp3 files
// everything else the webview can handle normally
if (url.endsWith(".apk")) {
Uri source = Uri.parse(url);
// Make a new request pointing to the .apk url
DownloadManager.Request request = new DownloadManager.Request(source);
// appears the same in Notification bar while downloading
request.setDescription("Description for the DownloadManager Bar");
request.setTitle("YourApp.apk");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
// save the file in the "Downloads" folder of SDCARD
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "SmartPigs.apk");
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
else if(url.endsWith(".mp3")) {
// if the link points to an .mp3 resource do something else
}
// if there is a link to anything else than .apk or .mp3 load the URL in the webview
else view.loadUrl(url);
return true;
}
});
回答by Wei WANG
Did you add DownloadManager Permission in your manifest file?
您是否在清单文件中添加了 DownloadManager 权限?
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
-----EDIT-----
- - -编辑 - - -
I'm copying some code snippet for your reference from Android stock browser on starting a download task:
在开始下载任务时,我正在从 Android 股票浏览器复制一些代码片段供您参考:
import android.net.WebAddress;
// java.net.URI is a lot stricter than KURL so we have to encode some
// extra characters. Fix for b 2538060 and b 1634719
WebAddress webAddress;
try {
webAddress = new WebAddress(url);
webAddress.setPath(encodePath(webAddress.getPath()));
} catch (Exception e) {
// This only happens for very bad urls, we want to chatch the
// exception here
Log.e(LOGTAG, "Exception trying to parse url:" + url);
return;
}
String addressString = webAddress.toString();
Uri uri = Uri.parse(addressString);
final DownloadManager.Request request;
try {
request = new DownloadManager.Request(uri);
} catch (IllegalArgumentException e) {
Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
return;
}
request.setMimeType(mimetype);
// set downloaded file destination to /sdcard/Download.
// or, should it be set to one of several Environment.DIRECTORY* dirs depending on mimetype?
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
// let this downloaded file be scanned by MediaScanner - so that it can
// show up in Gallery app, for example.
request.allowScanningByMediaScanner();
request.setDescription(webAddress.getHost());
// XXX: Have to use the old url since the cookies were stored using the
// old percent-encoded url.
String cookies = CookieManager.getInstance().getCookie(url, privateBrowsing);
request.addRequestHeader("cookie", cookies);
request.addRequestHeader("User-Agent", userAgent);
request.addRequestHeader("Referer", referer);
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
if (mimetype == null) {
if (TextUtils.isEmpty(addressString)) {
return;
}
// We must have long pressed on a link or image to download it. We
// are not sure of the mimetype in this case, so do a head request
new FetchUrlMimeType(activity, request, addressString, cookies,
userAgent).start();
} else {
final DownloadManager manager
= (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
new Thread("Browser download") {
public void run() {
manager.enqueue(request);
}
}.start();
}
Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
.show();
回答by Ibrahim
try this out
试试这个
mWebView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "Name of your downloadble file goes here, example: Mathematics II ");
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "Downloading File", //To notify the Client that the file is being downloaded
Toast.LENGTH_LONG).show();
}
});
Also don't forget to add the below code to the manifest.xml file,its very important this will give it permission for save to storage just like giving it Internet permission for the weview.
另外不要忘记将下面的代码添加到 manifest.xml 文件中,这非常重要,这将授予它保存到存储的权限,就像授予它对 weview 的 Internet 权限一样。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />