zoukankan      html  css  js  c++  java
  • 关于Android WebView上传文件的解决方案

    我们在开发需求的时候,难免会接入一下第三方的H5页面,有些H5页面是具有上传照片的功能,Android 中的 WebView是不能直接打开文件选择弹框的

    接下来我讲简单提供一下解决方案,先说一下思路

    1.接收WebView打开文件选择器的通知

    2.收到通知后,打开文件选择器等待用户选择需要上传的文件

    3.在onActivityResult中得到用户选择的文件的Uri

    4.然后把Uri传递给Html5

    这样就完成了一次H5选择文件的过程,下面我把代码贴出来自习看一下

    首先,WebView必须要支持JS交互,所以要打开JS交互

    mWebView.getSettings().setJavaScriptEnabled(true);

    当H5在调用上传文件的Api的时候,WebView会回调 openFileChooser和onShowFileChooser 方法来通知我们,我们这个时候要做的就是重写这个方法

    需要注意的是这个方法在不同的Api上会回调不同行参方法

    mWebView.setWebChromeClient(new WebChromeClient() {
    
    
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
                    if (newProgress == 100) {
                        mBar.setVisibility(View.GONE);
                    } else {
                        mBar.setVisibility(View.VISIBLE);
                        mBar.setProgress(newProgress);
                    }
                    super.onProgressChanged(view, newProgress);
                }
    
                //For Android API < 11 (3.0 OS)
                public void openFileChooser(ValueCallback<Uri> valueCallback) {
                    uploadMessage = valueCallback;
                    openImageChooserActivity();
                }
    
                //For Android API >= 11 (3.0 OS)
                public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                    uploadMessage = valueCallback;
                    openImageChooserActivity();
                }
    
                //For Android API >= 21 (5.0 OS)
                @Override
                public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                    uploadMessageAboveL = filePathCallback;
                    openImageChooserActivity();
                    return true;
                }
    
            });

    我们在openFileChooser方法中先保存了一下ValueCallback的回调对象,这个对象最后用来通知H5文件地址,我们之后在调用openFileChooser方法来打开文件选择器

     private void openImageChooserActivity() {
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
        }

    当用户选择完文件后,会调用onActivityResult方法,我们重写并等待回调

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == FILE_CHOOSER_RESULT_CODE) {
                if (null == uploadMessage && null == uploadMessageAboveL) return;
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (uploadMessageAboveL != null) {
                    onActivityResultAboveL(requestCode, resultCode, data);
                } else if (uploadMessage != null) {
                    uploadMessage.onReceiveValue(result);
                    uploadMessage = null;
                }
            }
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
            if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
                return;
            Uri[] results = null;
            if (resultCode == Activity.RESULT_OK) {
                if (intent != null) {
                    String dataString = intent.getDataString();
                    ClipData clipData = intent.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null)
                        results = new Uri[]{Uri.parse(dataString)};
                }
            }
            uploadMessageAboveL.onReceiveValue(results);
            uploadMessageAboveL = null;
        }

    onActivityResult就是用来通知H5用户选择的文件地址,在这个方法里,用我们之前保存的ValueCallback对象,调用onReceiveValue方法,H5就可以收到我们传递给它的地址信息了!

    一个被程序耽误的画手
  • 相关阅读:
    关于Python虚拟环境与包管理你应该知道的事
    你是否真的了解全局解析锁(GIL)
    谈谈装饰器的实现原理
    快速了解Python并发编程的工程实现(下)
    快速了解Python并发编程的工程实现(上)
    简单了解一下事件循环(Event Loop)
    为何你还不懂得如何使用Python协程
    一文搞懂Python可迭代、迭代器和生成器的概念
    源码分析Retrofit请求流程
    一份程序猿单词列表(updating)
  • 原文地址:https://www.cnblogs.com/kezhuang/p/7580703.html
Copyright © 2011-2022 走看看