WebView中实现文件下载功能

本文详细介绍了如何在WebView中实现文件下载功能,包括设置DownloadListener、下载文件到SD卡、自动打开文件等步骤,并通过一个具体项目的运用案例进行说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WebView控制调用相应的WEB页面进行展示。当碰到页面有下载链接的时候,点击上去是一点反应都没有的。原来是因为WebView默认没有开启文件下载的功能,如果要实现文件下载的功能,需要设置WebView的DownloadListener,通过实现自己的DownloadListener来实现文件的下载。具体操作如下:

1、设置WebView的DownloadListener:
    webView.setDownloadListener(new MyWebViewDownLoadListener());

2、实现MyWebViewDownLoadListener这个类,具体可以如下这样: 
Java代码 复制代码  收藏代码
  1. private class MyWebViewDownLoadListener implements DownloadListener{   
  2.   
  3.         @Override  
  4.         public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype,   
  5.                                     long contentLength) {              
  6.             Log.i("tag""url="+url);              
  7.             Log.i("tag""userAgent="+userAgent);   
  8.             Log.i("tag""contentDisposition="+contentDisposition);            
  9.             Log.i("tag""mimetype="+mimetype);   
  10.             Log.i("tag""contentLength="+contentLength);   
  11.             Uri uri = Uri.parse(url);   
  12.             Intent intent = new Intent(Intent.ACTION_VIEW, uri);   
  13.             startActivity(intent);              
  14.         }   
  15.     }  
private class MyWebViewDownLoadListener implements DownloadListener{

        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype,
                                    long contentLength) {        	
        	Log.i("tag", "url="+url);        	
        	Log.i("tag", "userAgent="+userAgent);
        	Log.i("tag", "contentDisposition="+contentDisposition);        	
        	Log.i("tag", "mimetype="+mimetype);
        	Log.i("tag", "contentLength="+contentLength);
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);        	 
        }
    }

  这只是调用系统中已经内置的浏览器进行下载,还没有WebView本身进行的文件下载,不过,这也基本上满足我们的应用场景了。

我在项目中的运用
项目要求这样:
1,需要使用WebView加载一个网页;
2,网页中有文件下载的链接,点击后需要下载文件到SDcard;
3,然后自动打开文件;
下面是具体解决办法
第一步,对WebView进行一系列设置。
Java代码 复制代码  收藏代码
  1. WebView webview=(WebView)layout.findViewById(R.id.webview);   
  2.                 webview.getSettings().setJavaScriptEnabled(true);   
  3.                 webview.setWebChromeClient(new MyWebChromeClient());   
  4.                 webview.requestFocus();   
  5. //              webview.loadUrl("file:///android_asset/risktest.html");   
  6.                 webview.loadUrl(jcrs_sub.get(position).addr);   
  7.                 // 设置web视图客户端   
  8.                 webview.setWebViewClient(new MyWebViewClient());   
  9.                 webview.setDownloadListener(new MyWebViewDownLoadListener());   
  10.   
  11. //内部类   
  12. public class MyWebViewClient extends WebViewClient {   
  13.         // 如果页面中链接,如果希望点击链接继续在当前browser中响应,   
  14.         // 而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。   
  15.         public boolean shouldOverviewUrlLoading(WebView view, String url) {   
  16.             L.i("shouldOverviewUrlLoading");   
  17.             view.loadUrl(url);   
  18.             return true;   
  19.         }   
  20.   
  21.         public void onPageStarted(WebView view, String url, Bitmap favicon) {   
  22.             L.i("onPageStarted");   
  23.             showProgress();   
  24.         }   
  25.   
  26.         public void onPageFinished(WebView view, String url) {   
  27.             L.i("onPageFinished");   
  28.             closeProgress();   
  29.         }   
  30.   
  31.         public void onReceivedError(WebView view, int errorCode,   
  32.                 String description, String failingUrl) {   
  33.             L.i("onReceivedError");   
  34.             closeProgress();   
  35.         }   
  36.     }   
  37.   
  38. // 如果不做任何处理,浏览网页,点击系统“Back”键,整个Browser会调用finish()而结束自身,   
  39.     // 如果希望浏览的网 页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该Back事件。   
  40.     public boolean onKeyDown(int keyCode, KeyEvent event) {   
  41.         // if((keyCode==KeyEvent.KEYCODE_BACK)&&webview.canGoBack()){   
  42.         // webview.goBack();   
  43.         // return true;   
  44.         // }   
  45.         return false;   
  46.     }  
WebView webview=(WebView)layout.findViewById(R.id.webview);
				webview.getSettings().setJavaScriptEnabled(true);
				webview.setWebChromeClient(new MyWebChromeClient());
				webview.requestFocus();
//				webview.loadUrl("file:///android_asset/risktest.html");
				webview.loadUrl(jcrs_sub.get(position).addr);
				// 设置web视图客户端
				webview.setWebViewClient(new MyWebViewClient());
				webview.setDownloadListener(new MyWebViewDownLoadListener());

//内部类
public class MyWebViewClient extends WebViewClient {
		// 如果页面中链接,如果希望点击链接继续在当前browser中响应,
		// 而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。
		public boolean shouldOverviewUrlLoading(WebView view, String url) {
			L.i("shouldOverviewUrlLoading");
			view.loadUrl(url);
			return true;
		}

		public void onPageStarted(WebView view, String url, Bitmap favicon) {
			L.i("onPageStarted");
			showProgress();
		}

		public void onPageFinished(WebView view, String url) {
			L.i("onPageFinished");
			closeProgress();
		}

		public void onReceivedError(WebView view, int errorCode,
				String description, String failingUrl) {
			L.i("onReceivedError");
			closeProgress();
		}
	}

// 如果不做任何处理,浏览网页,点击系统“Back”键,整个Browser会调用finish()而结束自身,
	// 如果希望浏览的网 页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该Back事件。
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// if((keyCode==KeyEvent.KEYCODE_BACK)&&webview.canGoBack()){
		// webview.goBack();
		// return true;
		// }
		return false;
	}


第二步,起线程开始下载文件。
Java代码 复制代码  收藏代码
  1. //内部类   
  2. private class MyWebViewDownLoadListener implements DownloadListener {   
  3.   
  4.         @Override  
  5.         public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype,   
  6.                                     long contentLength) {   
  7.             if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){   
  8.                 Toast t=Toast.makeText(mContext, "需要SD卡。", Toast.LENGTH_LONG);   
  9.                 t.setGravity(Gravity.CENTER, 00);   
  10.                 t.show();   
  11.                 return;   
  12.             }   
  13.             DownloaderTask task=new DownloaderTask();   
  14.             task.execute(url);   
  15.         }   
  16.   
  17.     }   
  18.     //内部类   
  19.     private class DownloaderTask extends AsyncTask<String, Void, String> {    
  20.   
  21.         public DownloaderTask() {    
  22.         }   
  23.   
  24.         @Override  
  25.         protected String doInBackground(String... params) {   
  26.             // TODO Auto-generated method stub   
  27.             String url=params[0];   
  28. //          Log.i("tag", "url="+url);   
  29.             String fileName=url.substring(url.lastIndexOf("/")+1);   
  30.             fileName=URLDecoder.decode(fileName);   
  31.             Log.i("tag""fileName="+fileName);   
  32.                
  33.             File directory=Environment.getExternalStorageDirectory();   
  34.             File file=new File(directory,fileName);   
  35.             if(file.exists()){   
  36.                 Log.i("tag""The file has already exists.");   
  37.                 return fileName;   
  38.             }   
  39.             try {     
  40.                 HttpClient client = new DefaultHttpClient();     
  41. //                client.getParams().setIntParameter("http.socket.timeout",3000);//设置超时   
  42.                 HttpGet get = new HttpGet(url);     
  43.                 HttpResponse response = client.execute(get);   
  44.                 if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){   
  45.                     HttpEntity entity = response.getEntity();   
  46.                     InputStream input = entity.getContent();   
  47.                        
  48.                     writeToSDCard(fileName,input);   
  49.                        
  50.                     input.close();   
  51. //                  entity.consumeContent();   
  52.                     return fileName;     
  53.                 }else{   
  54.                     return null;   
  55.                 }   
  56.             } catch (Exception e) {     
  57.                 e.printStackTrace();   
  58.                 return null;   
  59.             }   
  60.         }   
  61.   
  62.         @Override  
  63.         protected void onCancelled() {   
  64.             // TODO Auto-generated method stub   
  65.             super.onCancelled();   
  66.         }   
  67.   
  68.         @Override  
  69.         protected void onPostExecute(String result) {   
  70.             // TODO Auto-generated method stub   
  71.             super.onPostExecute(result);   
  72.             closeProgressDialog();   
  73.             if(result==null){   
  74.                 Toast t=Toast.makeText(mContext, "连接错误!请稍后再试!", Toast.LENGTH_LONG);   
  75.                 t.setGravity(Gravity.CENTER, 00);   
  76.                 t.show();   
  77.                 return;   
  78.             }   
  79.                
  80.             Toast t=Toast.makeText(mContext, "已保存到SD卡。", Toast.LENGTH_LONG);   
  81.             t.setGravity(Gravity.CENTER, 00);   
  82.             t.show();   
  83.             File directory=Environment.getExternalStorageDirectory();   
  84.             File file=new File(directory,result);   
  85.             Log.i("tag""Path="+file.getAbsolutePath());   
  86.                
  87.             Intent intent = getFileIntent(file);   
  88.                
  89.             startActivity(intent);   
  90.                    
  91.         }   
  92.   
  93.         @Override  
  94.         protected void onPreExecute() {   
  95.             // TODO Auto-generated method stub   
  96.             super.onPreExecute();   
  97.             showProgressDialog();   
  98.         }   
  99.   
  100.         @Override  
  101.         protected void onProgressUpdate(Void... values) {   
  102.             // TODO Auto-generated method stub   
  103.             super.onProgressUpdate(values);   
  104.         }    
  105.   
  106.            
  107.     }   
//内部类
private class MyWebViewDownLoadListener implements DownloadListener {

        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype,
                                    long contentLength) {
        	if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
        		Toast t=Toast.makeText(mContext, "需要SD卡。", Toast.LENGTH_LONG);
				t.setGravity(Gravity.CENTER, 0, 0);
				t.show();
				return;
        	}
			DownloaderTask task=new DownloaderTask();
			task.execute(url);
        }

    }
	//内部类
	private class DownloaderTask extends AsyncTask<String, Void, String> { 

	    public DownloaderTask() { 
	    }

		@Override
		protected String doInBackground(String... params) {
			// TODO Auto-generated method stub
			String url=params[0];
//			Log.i("tag", "url="+url);
			String fileName=url.substring(url.lastIndexOf("/")+1);
			fileName=URLDecoder.decode(fileName);
			Log.i("tag", "fileName="+fileName);
			
			File directory=Environment.getExternalStorageDirectory();
			File file=new File(directory,fileName);
			if(file.exists()){
				Log.i("tag", "The file has already exists.");
				return fileName;
			}
			try {  
                HttpClient client = new DefaultHttpClient();  
//                client.getParams().setIntParameter("http.socket.timeout",3000);//设置超时
                HttpGet get = new HttpGet(url);  
                HttpResponse response = client.execute(get);
                if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){
					HttpEntity entity = response.getEntity();
					InputStream input = entity.getContent();
					
					writeToSDCard(fileName,input);
					
					input.close();
//					entity.consumeContent();
					return fileName;  
                }else{
                	return null;
                }
            } catch (Exception e) {  
                e.printStackTrace();
                return null;
            }
		}

		@Override
		protected void onCancelled() {
			// TODO Auto-generated method stub
			super.onCancelled();
		}

		@Override
		protected void onPostExecute(String result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			closeProgressDialog();
			if(result==null){
				Toast t=Toast.makeText(mContext, "连接错误!请稍后再试!", Toast.LENGTH_LONG);
				t.setGravity(Gravity.CENTER, 0, 0);
				t.show();
				return;
			}
			
			Toast t=Toast.makeText(mContext, "已保存到SD卡。", Toast.LENGTH_LONG);
			t.setGravity(Gravity.CENTER, 0, 0);
			t.show();
			File directory=Environment.getExternalStorageDirectory();
			File file=new File(directory,result);
			Log.i("tag", "Path="+file.getAbsolutePath());
			
			Intent intent = getFileIntent(file);
			
			startActivity(intent);
				
		}

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			showProgressDialog();
		}

		@Override
		protected void onProgressUpdate(Void... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
		} 

		
	} 

第三步,实现一些工具方法。
Java代码 复制代码  收藏代码
  1. private ProgressDialog mDialog;   
  2.     private void showProgressDialog(){   
  3.         if(mDialog==null){   
  4.             mDialog = new ProgressDialog(mContext);     
  5.             mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);//设置风格为圆形进度条     
  6.             mDialog.setMessage("正在加载 ,请等待...");     
  7.             mDialog.setIndeterminate(false);//设置进度条是否为不明确     
  8.             mDialog.setCancelable(true);//设置进度条是否可以按退回键取消     
  9.             mDialog.setCanceledOnTouchOutside(false);   
  10.             mDialog.setOnDismissListener(new OnDismissListener() {   
  11.                    
  12.                 @Override  
  13.                 public void onDismiss(DialogInterface dialog) {   
  14.                     // TODO Auto-generated method stub   
  15.                     mDialog=null;   
  16.                 }   
  17.             });   
  18.             mDialog.show();   
  19.                
  20.         }   
  21.     }   
  22.     private void closeProgressDialog(){   
  23.         if(mDialog!=null){   
  24.             mDialog.dismiss();   
  25.             mDialog=null;   
  26.         }   
  27.     }   
  28.      public Intent getFileIntent(File file){   
  29. //       Uri uri = Uri.parse("http://m.ql18.com.cn/hpf10/1.pdf");   
  30.         Uri uri = Uri.fromFile(file);   
  31.         String type = getMIMEType(file);   
  32.         Log.i("tag""type="+type);   
  33.         Intent intent = new Intent("android.intent.action.VIEW");   
  34.         intent.addCategory("android.intent.category.DEFAULT");   
  35.         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   
  36.         intent.setDataAndType(uri, type);   
  37.         return intent;   
  38.       }   
  39.         
  40.     public void writeToSDCard(String fileName,InputStream input){   
  41.            
  42.         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){   
  43.             File directory=Environment.getExternalStorageDirectory();   
  44.             File file=new File(directory,fileName);   
  45. //          if(file.exists()){   
  46. //              Log.i("tag", "The file has already exists.");   
  47. //              return;   
  48. //          }   
  49.             try {   
  50.                 FileOutputStream fos = new FileOutputStream(file);   
  51.                 byte[] b = new byte[2048];   
  52.                 int j = 0;   
  53.                 while ((j = input.read(b)) != -1) {   
  54.                     fos.write(b, 0, j);   
  55.                 }   
  56.                 fos.flush();   
  57.                 fos.close();   
  58.             } catch (FileNotFoundException e) {   
  59.                 // TODO Auto-generated catch block   
  60.                 e.printStackTrace();   
  61.             } catch (IOException e) {   
  62.                 // TODO Auto-generated catch block   
  63.                 e.printStackTrace();   
  64.             }   
  65.         }else{   
  66.             Log.i("tag""NO SDCard.");   
  67.         }   
  68.     }   
  69.        
  70.     private String getMIMEType(File f){      
  71.       String type="";     
  72.       String fName=f.getName();     
  73.       /* 取得扩展名 */     
  74.       String end=fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase();   
  75.          
  76.       /* 依扩展名的类型决定MimeType */  
  77.       if(end.equals("pdf")){   
  78.           type = "application/pdf";//   
  79.       }   
  80.       else if(end.equals("m4a")||end.equals("mp3")||end.equals("mid")||     
  81.       end.equals("xmf")||end.equals("ogg")||end.equals("wav")){     
  82.         type = "audio/*";      
  83.       }     
  84.       else if(end.equals("3gp")||end.equals("mp4")){     
  85.         type = "video/*";     
  86.       }     
  87.       else if(end.equals("jpg")||end.equals("gif")||end.equals("png")||     
  88.       end.equals("jpeg")||end.equals("bmp")){     
  89.         type = "image/*";     
  90.       }     
  91.       else if(end.equals("apk")){      
  92.         /* android.permission.INSTALL_PACKAGES */      
  93.         type = "application/vnd.android.package-archive";    
  94.       }   
  95. //      else if(end.equals("pptx")||end.equals("ppt")){   
  96. //        type = "application/vnd.ms-powerpoint";    
  97. //      }else if(end.equals("docx")||end.equals("doc")){   
  98. //        type = "application/vnd.ms-word";   
  99. //      }else if(end.equals("xlsx")||end.equals("xls")){   
  100. //        type = "application/vnd.ms-excel";   
  101. //      }   
  102.       else{   
  103. //        /*如果无法直接打开,就跳出软件列表给用户选择 */     
  104.         type="*/*";   
  105.       }   
  106.       return type;   
  107.     }   
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值