Android app嵌套H5<input type=“file“ />相册选择照片,拍照照片,打开文件管理器上传文件

539 阅读3分钟

公司项目嵌套了一个H5链接,链接中有上传图片跟上传文件的功能, 开始以为直接用webView加载就直接可以了,因为调的是系统的,而且同样一个链接IOS可以,什么都不用兼容,微信打开浏览器也可以,但是如果你单纯的以为webView加载就能完成此功能,那你就真的错了,大坑等着你一点一点填呢 首先先上图公司的需求

1691224060465.png

开始我也以为就是简单的给权限就行,既然是H5自己上传,还需要我们改什么啊,但是后来怎么也都不能实现,后来一查是因为webView不支持上传图片需要监听他的事件,一顿猛操作以后渐入佳境,虽然满足了公司的需求,但是有几点疑惑我也不知道为什么呢

啥也不说直接贴代码

webView.setWebChromeClient(new WebChromeClient() {//监听网页加载
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                L.e("点击1");
                L.e("监听点击按钮");
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                L.e("点击3---acceptType==" + acceptType);
                openFileChooser(uploadMsg);
                L.e("点击3");
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                openFileChooser(uploadMsg);
                L.e("点击4", "4");
            }

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                L.e("onShowFileChooser");
                String acceptType = fileChooserParams.getAcceptTypes()[0];
                L.e("onShowFileChooser---acceptType=" + acceptType);
                if (acceptType.contains("image/*")) {
                    if (uploadMessage != null) {
                        uploadMessage.onReceiveValue(null);
                        uploadMessage = null;
                    }
                    uploadMessage = filePathCallback;
                    ImgUtil.choicePhoto(WebViewH5PublicActivity.this);
                } else {
                    uploadMessageAboveL = filePathCallback;

//                    openImageChooserActivity(fileChooserParams.getAcceptTypes());

//                    Uri uri = Uri.parse("content://com.android.externalstorage.documents/document/primary:Download%2fWeiXin");
//                    L.e("uri.getPath===" + uri.getPath());
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    intent.setType("*/*");
//                    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI);
                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    startActivityForResult(intent, FILE_CHOOSER_RESULT_CODE);
                }


                return true;
            }

        });
        
        
     
     
     ```
     
     
     
     
     
     疑惑一      我有个疑惑不知道为什么第三方的H5链接再点击相册照片的时候跟选择文件的时候事件是一样的,同时调用onShowFileChooser,而且acceptType 在文件上传的时候他返回的参数居然是空,选择照片的时候没有问题

acceptType返回image/* 所以我这样区分了一下然后跳转不同的操作



回调代码

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

    super.onActivityResult(requestCode, resultCode, intent);
    if (resultCode == RESULT_OK) {//正确返回
        switch (requestCode) {

            case ImgUtil.FILE_CHOOSER_RESULT_CODE://选择文件
                if (intent != null) {
                    if (null == uploadMessage1 && null == uploadMessageAboveL) return;
                    Uri resultDoc = intent == null || resultCode != RESULT_OK ? null : intent.getData();
                    if (uploadMessageAboveL != null) {
                        onActivityResultAboveL(requestCode, resultCode, intent);
                    } else if (uploadMessage != null) {
                        uploadMessage1.onReceiveValue(resultDoc);
                        uploadMessage1 = null;
                    }

                } else {
                    clearUploadMessage();
                }
                break;
            case ImgUtil.TAKE_PHOTO://相机返回
                L.e("返回相机" + ImgUtil.imageUri.toString());

                //相机返回rui
                //Uri uriTake = ImgUtil.imageUri;
                Uri uriTake = null;
                try {
                    uriTake = ImgUtil.getCompressUri(WebViewH5PublicActivity.this, ImgUtil.imageUri);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //显示在页面
                if (uploadMessage == null) return;
                Uri[] imgTaskUris = {uriTake};
                uploadMessage.onReceiveValue(imgTaskUris);
                uploadMessage = null;
                if (null == mUploadMessage) return;
                Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : uriTake;
                mUploadMessage.onReceiveValue(result);
                mUploadMessage = null;

                break;
            case ImgUtil.CHOOSE_PHOTO://相册返回
                try {
                    if (intent != null) {
                        //相册返回
                        Log.e("返回", "intent2:" + intent.getData().toString() + "..." + uploadMessage);
                        //相册返回uri
                        //Uri uriChoose = intent.getData();
                        Uri uriChoose = ImgUtil.getCompressUri(WebViewH5PublicActivity.this, intent.getData());
                        //显示在页面
                        if (uploadMessage == null) return;
                        Uri[] imgChooseUris = {uriChoose};
                        uploadMessage.onReceiveValue(imgChooseUris);
                        //uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
                        uploadMessage = null;

                        Log.e("返回", "intent3:" + WebChromeClient.FileChooserParams.parseResult(resultCode, intent).toString());
                    }
                    break;
                } catch (Exception e) {
                    e.printStackTrace();

// ToastUtils.getToastEmail().ToastShowFail(this, "图片选择失败"); clearUploadMessage(); } break; } } else { clearUploadMessage(); // ToastUtils.getToastEmail().ToastShowFail(this, "图片选择失败"); } }

/*
   android 5.0
   多文件的结果返回处理
    */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
    Log.d("test1234", "onActivityResultAboveL");

    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;
}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case ImgUtil.REQUEST_CODE_ALBUM://相册存储权限
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                ImgUtil.openAlbum(this);
            } else {

                ToastUtils.getToastEmail().ToastShowFail(this, "选择图库需要同意权限");
            }
            break;
        case ImgUtil.REQUEST_CODE_CAMERA://相机拍照权限
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {//允许
                ImgUtil.openCamera(WebViewH5PublicActivity.this);
            } else {//拒绝

                ToastUtils.getToastEmail().ToastShowFail(this, "只有同意相机权限,才能使用扫码功能");
            }
            break;
        default:
    }
}

            clearUploadMessage();  这个方法是必须的以防止不选择文件或是图片的时候再次点击H5没反应
            
            
            
            为了兼容一些上传文件在H5链接里边不显示故而在shouldOverrideUrlLoading适配一下,让其跳转到
```系统浏览器去下载再查看
  public WebViewClient getWebViewClient() {
        return new WebViewClient() {

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String strUrl) {
                L.d("shouldOverrideUrlLoading---url:" + strUrl);

//                if (StrUrl.contains("city/list")) {
//                    L.d("city/list");
//                }

                if (strUrl.startsWith("tel:")) {
                    Intent intent = new Intent(Intent.ACTION_VIEW,
                            Uri.parse(strUrl));
                    startActivity(intent);
                    return true;
                }

                if (strUrl.contains(".doc") || strUrl.contains(".pdf") || strUrl.contains(".mp4")
                        || strUrl.contains(".xlsx") || strUrl.contains(".xls") || strUrl.contains(".docx")) {
                    CloseLockTipDialog closeLockTipDialog = new CloseLockTipDialog(WebViewH5PublicActivity.this, "");
                    closeLockTipDialog.show();

                    TextView cancle_info = closeLockTipDialog.findViewById(R.id.cancle_info);
                    TextView submit_info = closeLockTipDialog.findViewById(R.id.submit_info);
                    TextView text_two = closeLockTipDialog.findViewById(R.id.text_two);
                    text_two.setText("即将离开app,在浏览器中打开");
                    cancle_info.setText("取消");
                    cancle_info.setTextColor(Color.parseColor("#333333"));
                    submit_info.setText("允许");
                    cancle_info.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            closeLockTipDialog.dismiss();
                        }
                    });

                    submit_info.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Uri uri = Uri.parse(strUrl);
                            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                            startActivity(intent);
                            closeLockTipDialog.dismiss();
                        }
                    });
                }


                webView.loadUrl(strUrl);
                return false;
            }


            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);

            }


            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
                L.d("errorCode:" + errorCode + "|failingUrl:" + failingUrl);

            }


            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                super.onReceivedSslError(view, handler, error);
                handler.cancel();
                handler.proceed();

            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                MDialog.hideLoading();

            }
        };
    }
    
    
    此代码不是原创,有网上的其他博主的代码  有自己修改的添加的东西,写此文章只是为了记录一下,填坑的日子