WebView基于H5的上传和和下载

现在混合开发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的上传和下载功能了。本人亲自测试过了,是有效果的,

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

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


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

猜你喜欢

转载自blog.csdn.net/lixuce1234/article/details/78189046