WebView基于H5的上传和和下载

xiaoxiao2021-02-28  10

现在混合开发APP已经成为了一种趋势,某些功能用H5解决的就用H5来做了,最近遇到一个需求,就是在H5界面里面有一个图片上传功能,还有附件下载功能,安卓的webView如果不通过一些设置的话是不可以的。下面要说的就是用H5来打开手机的图库,并进行图片上传功能,还有下载功能。 首先是要继承WebChromeClient这个类,WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等。 class MyWebChromeClient extends WebChromeClient { // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { if (mUploadMessage != null) return; mUploadMessage = uploadMsg; selectImage(RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP); } // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooser(uploadMsg, ""); } // For Android > 4.1.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android 5.0+ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; selectImage(RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP); return true; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } } openFileChooser和onShowFileChooser方法,当网络上页面点击了 <input type="file"/> 的标签时,不同版本的SDK调用openFileChooser或者onShowFileChooser。 选择完图片后,进入onActivityResult,根据不同的requestCode值区分开AndroidSDK 5.0以上和5.0以下,5.0以下传回Uri对象,5.0以上传回Uri数组。其中处理下onActivityResult传回来的意图数据,将Intent数据转换乌里分类中翻译。 /**选择后,回传值*/ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mUploadMessage == null && mUploadCallbackAboveL == null) { return; } Uri uri = null; switch (requestCode) { case RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP: uri = afterChosePic(data); if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null; } break; case RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP: try { uri = afterChosePic(data); if (uri == null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { }); mUploadCallbackAboveL = null; break; } if (mUploadCallbackAboveL != null && uri != null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { uri }); mUploadCallbackAboveL = null; } } catch (Exception e) { mUploadCallbackAboveL = null; e.printStackTrace(); } break; } } ** 下面把完整的代码贴上来: ** WebViewActivity.java package com.lwd.webviewupimg; import java.io.File; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore.Images.ImageColumns; import android.view.KeyEvent; import android.view.View; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView; import android.webkit.WebViewClient; /** * @author lwd * @create 2016年8月17日 */ @SuppressLint("SetJavaScriptEnabled") public class WebViewActivity extends Activity{ private WebView webview; private ValueCallback<Uri> mUploadMessage; private ValueCallback<Uri[]> mUploadCallbackAboveL; private final int RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP = 1; private final int RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP = 2; private String url = "";//这里添加含有图片上传功能的H5页面访问地址即可。 String compressPath = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_welcome); initData(); } public void initData() { webview = (WebView) findViewById(R.id.webview); initWebView(); webview.loadUrl(url); } @SuppressWarnings("deprecation") private void initWebView(){ webview.setScrollBarStyle(View.GONE); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.getSettings().setDomStorageEnabled(false); webview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); webview.getSettings().setPluginState(WebSettings.PluginState.ON); webview.getSettings().setAllowFileAccess(true); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL); webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webview.getSettings().setUseWideViewPort(true); webview.getSettings().setLoadWithOverviewMode(true); webview.getSettings().setAllowContentAccess(true); webview.requestFocus(); webview.setWebViewClient(new WebClient()); webview.setWebChromeClient(new MyWebChromeClient()); } /**选择后,回传值*/ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mUploadMessage == null && mUploadCallbackAboveL == null) { return; } Uri uri = null; switch (requestCode) { case RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP: uri = afterChosePic(data); if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null; } break; case RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP: try { uri = afterChosePic(data); if (uri == null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { }); mUploadCallbackAboveL = null; break; } if (mUploadCallbackAboveL != null && uri != null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { uri }); mUploadCallbackAboveL = null; } } catch (Exception e) { mUploadCallbackAboveL = null; e.printStackTrace(); } break; } } /** * 选择照片后结束 * @param data */ private Uri afterChosePic(Intent data) { if (data == null) { return null; } String path = getRealFilePath(data.getData()); String[] names = path.split("\\."); String endName = null; if (names != null) { endName = names[names.length - 1]; } if (endName != null) { compressPath = compressPath.split("\\.")[0] + "." + endName; } File newFile; try { newFile = FileUtils.compressFile(path, compressPath); } catch (Exception e) { newFile = null; } return Uri.fromFile(newFile); } /** * 根据Uri获取图片文件的绝对路径 */ public String getRealFilePath(final Uri uri) { if (null == uri) { return null; } final String scheme = uri.getScheme(); String data = null; if (scheme == null) { data = uri.getPath(); } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = getContentResolver().query(uri, new String[] { ImageColumns.DATA }, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndexOrThrow(ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; } @Override public void onBackPressed() { super.onBackPressed(); if(webview.canGoBack()){ webview.goBack(); }else{ finish(); } } private class WebClient extends WebViewClient { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } /**打开图库,同时处理图片(项目业务需要统一命名)*/ private void selectImage(int resultCode) { compressPath = Environment.getExternalStorageDirectory().getPath() + "/QWB/temp"; File file = new File(compressPath); if (!file.exists()) { file.mkdirs(); } compressPath = compressPath + File.separator + "compress.png"; File image = new File(compressPath); if (image.exists()) { image.delete(); } Intent intent = new Intent( Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, resultCode); } /** * 内部类 */ class MyWebChromeClient extends WebChromeClient { //openFileChooser(隐藏方法)仅适用android5.0以下的环境,android5.0及以上使用onShowFileChooser // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { if (mUploadMessage != null) return; mUploadMessage = uploadMsg; selectImage(RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP); } // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooser(uploadMsg, ""); } // For Android > 4.1.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android 5.0+ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; selectImage(RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP); return true; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } } } ● package com.lwd.webviewupimg; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.text.TextUtils; import android.util.Log; public class FileUtils { /** * 把图片压缩到200K * * @param oldpath * 压缩前的图片路径 * @param newPath * 压缩后的图片路径 * @return */ public static File compressFile(String oldpath, String newPath) { Bitmap compressBitmap = FileUtils.decodeFile(oldpath); Bitmap newBitmap = ratingImage(oldpath, compressBitmap); ByteArrayOutputStream os = new ByteArrayOutputStream(); newBitmap.compress(CompressFormat.PNG, 100, os); byte[] bytes = os.toByteArray(); File file = null ; try { file = FileUtils.getFileFromBytes(bytes, newPath); } catch (Exception e) { e.printStackTrace(); }finally{ if(newBitmap != null ){ if(!newBitmap.isRecycled()){ newBitmap.recycle(); } newBitmap = null; } if(compressBitmap != null ){ if(!compressBitmap.isRecycled()){ compressBitmap.recycle(); } compressBitmap = null; } } return file; } private static Bitmap ratingImage(String filePath,Bitmap bitmap){ int degree = readPictureDegree(filePath); return rotaingImageView(degree, bitmap); } /** * 旋转图片 * @param angle * @param bitmap * @return Bitmap */ public static Bitmap rotaingImageView(int angle , Bitmap bitmap) { //旋转图片 动作 Matrix matrix = new Matrix();; matrix.postRotate(angle); System.out.println("angle2=" + angle); // 创建新的图片 Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizedBitmap; } /** * 读取图片属性:旋转的角度 * @param path 图片绝对路径 * @return degree旋转的角度 */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 把字节数组保存为一个文件 * * @param b * @param outputFile * @return */ public static File getFileFromBytes(byte[] b, String outputFile) { File ret = null; BufferedOutputStream stream = null; try { ret = new File(outputFile); FileOutputStream fstream = new FileOutputStream(ret); stream = new BufferedOutputStream(fstream); stream.write(b); } catch (Exception e) { // log.error("helper:get file from byte process error!"); e.printStackTrace(); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // log.error("helper:get file from byte process error!"); e.printStackTrace(); } } } return ret; } /** * 图片压缩 * * @param fPath * @return */ public static Bitmap decodeFile(String fPath) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; opts.inDither = false; // Disable Dithering mode opts.inPurgeable = true; // Tell to gc that whether it needs free opts.inInputShareable = true; // Which kind of reference will be used to BitmapFactory.decodeFile(fPath, opts); final int REQUIRED_SIZE = 200; int scale = 1; if (opts.outHeight > REQUIRED_SIZE || opts.outWidth > REQUIRED_SIZE) { final int heightRatio = Math.round((float) opts.outHeight / (float) REQUIRED_SIZE); final int widthRatio = Math.round((float) opts.outWidth / (float) REQUIRED_SIZE); scale = heightRatio < widthRatio ? heightRatio : widthRatio;// } Log.i("scale", "scal ="+ scale); opts.inJustDecodeBounds = false; opts.inSampleSize = scale; Bitmap bm = BitmapFactory.decodeFile(fPath, opts).copy(Config.ARGB_8888, false); return bm; } /** * 创建目录 * @param path */ public static void setMkdir(String path) { File file = new File(path); if(!file.exists()) { file.mkdirs(); Log.e("file", "目录不存在 创建目录 "); }else{ Log.e("file", "目录存在"); } } /** * 获取目录名称 * @param url * @return FileName */ public static String getFileName(String url) { int lastIndexStart = url.lastIndexOf("/"); if(lastIndexStart!=-1) { return url.substring(lastIndexStart+1, url.length()); }else{ return null; } } /** * 删除该目录下的文件 * * @param path */ public static void delFile(String path) { if (!TextUtils.isEmpty(path)) { File file = new File(path); if (file.exists()) { file.delete(); } } } } 上面介绍了webView的上传,下面来介绍一下WebView的下载功能, WebView控制调用相应的WEB页面进行展示。当碰到页面有下载链接的时候,点击上去是一点反应都没有的。原来是因为WebView默认没有开启文件下载的功能,如果要实现文件下载的功能,需要设置WebView的DownloadListener,通过实现自己的DownloadListener来实现文件的下载。具体操作如下:  1、设置WebView的DownloadListener:      webView.setDownloadListener(new MyWebViewDownLoadListener());  2、实现MyWebViewDownLoadListener这个类,具体可以如下这样:   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进行一系列设置。  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; } //内部类 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); } } 经过上面的操作就完成了webView的上传和下载功能了。本人亲自测试过了,是有效果的,

大家都有了以上相同的教程,但是人和人之间的区别在于:别人有颗更强大的内心,可怕的是比你聪明的人比你还要更努力!!

当你下定决心,准备前行的时候,剩下的只有坚持了。。。

如果大家觉得我写的还可以的话,请关注我的微信公众号:

转载请注明原文地址: https://www.6miu.com/read-1150355.html

最新回复(0)