Android WebView 支持H5图片上传<input type="file">

本文介绍如何在Android应用中使用WebView组件实现H5页面文件上传功能。针对不同Android版本提供了具体的代码示例,包括如何处理文件选择器回调及兼容性问题。

webview

在android的组件webview中是不能用H5上传文件了的。但是有时候我们需要用H5去调用上传文件,因此需要支持这项功能。

代码示例

有不同的额版本适配方法 3.0 4.0 5.0 6.0

public class PlayActivity extends AppCompatActivity {

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    /**
     * Called when the activity is first created.
     */

    WebView web;

    private ValueCallback<Uri> mUploadMessage;
    public ValueCallback<Uri[]> uploadMessage;
    public static final int REQUEST_SELECT_FILE = 100;
    private final static int FILECHOOSER_RESULTCODE = 1;

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    Intent intent) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (requestCode == REQUEST_SELECT_FILE) {
                if (uploadMessage == null)
                    return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
                uploadMessage = null;
            }
        } else if (requestCode == FILECHOOSER_RESULTCODE) {
            if (null == mUploadMessage)
                return;
            // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
            // Use RESULT_OK only if you're implementing WebView inside an Activity
            Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_play);

        web = (WebView) findViewById(R.id.webview01);

        web = new WebView(this);
        web.getSettings().setJavaScriptEnabled(true);
        web.loadUrl("http://10.0.0.82:1346/hot/7516063/A1035B1ECD35AA7F0FAE050007F01000209");
        web.setWebViewClient(new myWebClient());
        web.setWebChromeClient(new WebChromeClient() {
            //The undocumented magic method override
            //Eclipse will swear at you if you try to put @Override here
            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {

                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                PlayActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);

            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                openFileChooser(uploadMsg);
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                openFileChooser(uploadMsg);
            }

            // For Lollipop 5.0+ Devices
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                if (uploadMessage != null) {
                    uploadMessage.onReceiveValue(null);
                    uploadMessage = null;
                }

                uploadMessage = filePathCallback;

                Intent intent = fileChooserParams.createIntent();
                try {
                    startActivityForResult(intent, REQUEST_SELECT_FILE);
                } catch (ActivityNotFoundException e) {
                    uploadMessage = null;
                    return false;
                }
                return true;
            }


        });


        setContentView(web);


    }

    public class myWebClient extends WebViewClient {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            // TODO Auto-generated method stub
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // TODO Auto-generated method stub

            view.loadUrl(url);
            return true;

        }

        @Override
        public void onPageFinished(WebView view, String url) {
            // TODO Auto-generated method stub
            super.onPageFinished(view, url);

        }
    }

    //flipscreen not loading again
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

}
<template> <view class="container"> <!-- 显示加载状态 --> <view v-if="loading" class="loading"> <text>正在加载支付页面...</text> </view> <!-- Webview 容器 --> <web-view v-if="htmlContent" :src="webviewUrl" @message="handleWebviewMessage" @onPostMessage="handlePostMessage"></web-view> </view> </template> <script setup> import { ref, onMounted } from 'vue'; import { onLoad } from '@dcloudio/uni-app'; const loading = ref(true); const htmlContent = ref(''); const webviewUrl = ref(''); onLoad(options => { console.log(options) console.log(options.cashierHtml) htmlContent.value = options.cashierHtml; prepareWebviewContent(); }); // 准备 Webview 内容 const prepareWebviewContent = () => { if (!htmlContent.value) return; // 1. 创建 Blob 对象 const blob = new Blob([htmlContent.value], { type: 'text/html' }); // 2. 生成临时 URL webviewUrl.value = URL.createObjectURL(blob); // 3. 设置 Webview 加载完成 loading.value = false; }; // 处理 Webview 消息 const handleWebviewMessage = (e) => { console.log('收到 Webview 消息:', e.detail); // 处理支付结果 // if (e.detail.data?.type === 'payment_result') { // uni.redirectTo({ // url: `/pages/payment/result?status=${e.detail.data.status}` // }); // } }; // 处理 PostMessage 事件 const handlePostMessage = (e) => { console.log('PostMessage 事件:', e); }; </script> <style scoped> .container { flex: 1; height: 100vh; } .loading { display: flex; justify-content: center; align-items: center; height: 100%; } </style>[Object] {"cashierHtml":"<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text...} at pages/bankPayment/index.vue:29 11:42:27.510 <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title></title></head><body onload="load()"><form id = "form" action="http://wap.dev.psbc.com/mobilebank/CashierDeskStart.do" method="post"><input type="hidden" name="MercName" id="MercName" value="徐州市铜山区大许镇阳光幼教幼儿园"/><input type="hidden" name="MercCode" id="MercCode" value="1100529319992199476"/><input type="hidden" name="TransAmt" id="TransAmt" value="1"/><input type="hidden" name="OrderNum" id="OrderNum" value="CPN034ez8rd7flkp10240002fzc001"/><input type="hidden" name="MercDtTm" id="MercDtTm" value="20250911114024"/><input type="hidden" name="MerCustId" id="MerCustId" value="26609"/><input type="hidden" name="Plain" id="Plain" value="{'PlatMercCode':'1100529319992199476','TransChannl':'01','InstType':'1111110','QpLtAcctType':'1110','GwLtAcctType':'111011','OlLtAcctType':'01','MercDtTm':'20250911114024','OrderNum':'CPN034ez8rd7flkp10240002fzc001','MercCode':'8299000007077701045','TransAmt':'1','MercUrl':'/esbHttpSrv/sendPostData/99100140001_OPSS_thirdpayLargeMerchants','ReSuccUrl':'http://openpayment.dev.psbc.com:8080/h5xctest/h5/#/paySuccess?out_trade_no=CPN034ez8rd7flkp10240002fzc001','OrderUrl':'','Remark1':'','Remark2':'','ValidTime':'30','MercName':'徐州市铜山区大许镇阳光幼教幼儿园','BizTp':'110001','OrderTitle':'2025年9月伙食费','OrderCount':'1','OrderDetail':[{'SubMercCode':'8299000007077701045','SubMercName':'徐州市铜山区大许镇阳光幼教幼儿园','TotalAmt':'1','TotalNum':'1','MerUnitDetail':'2025年9月伙食费^1^1'}],'PlfmNm':'','TrxDevcInf':'ABCD:EF01:2345:6789:ABCD:EF01:2345:6789|F0E1D2C3B4A5|010102020303040|01020304050 6070|00112233445566778899|5A4B3C2D1E0F|116.123456,-39.987654|','PyeeAcctIssrId':'C1040311005293','PyeeAcctTp':'05','PyeeAcctId':'4130130413015010001291000130','PyeeNm':'昆山市假日置业有限公司','TerminalIp':'127.0.0.1','MerCustId':'26609','PayEnv':'01','QpTranChnl':'0','GwTranChnl':'0','InterAcctno':'4415602000739195','InterAcctOrganCode':'44001483','DevOrganCode':'11005293','WchatAppId':'','OpenId':'','ReserveParam':'','CreditorWalletName':'内部业务钱包青岛分行医保社保','CreditorWalletId':'0082000020475894','CreditorWalletType':'WT10','CreditorWalletLevel':'WL01','MerCertType':'','MerCerId':'','TradeBizType':'206','TradeCategoryCode':'20600017','PhonePayEnv':'','AreaInfo':'120101','NativeFlag':'00','PageFlag':'1','AtvFlag':'0','AtvID':'','Reserve1':'','MerAcctTp':'0','MerAcctNo':'963011013000078213','MerAcctName':'测试客户合并','MerBankNo':'','MerBankName':'','QyFlag':'','BusinessLicense':'120101673864374'}"/><input type="hidden" name="Signature" id="Signature" value="042f03f10adb90f8256892536d185d3d6375be7e27d806d59efe3e86ebeb9115abc229659064cd7b7fc4b2871406c3973f0ffaa7d61ba958b8c61bd0f4be5781665854c9f1512c52c69fa774181db9e56b2ff20b045f0d8dce67e6d746850636222d17e0d063d19e2de1b98c487632cca80c6dbde3e77a12e2b060a094f5148b"/><input type="hidden" name="OpenFlag" id="OpenFlag" value="11111101111000000000000000000000000000000000000000"/><input type="hidden" name="PayChannel" id="PayChannel" value="11"/><input type="hidden" name="QPayChannel" id="QPayChannel" value="11"/><input type="hidden" name="Flag" id="Flag" value="110100"/><input type="hidden" name="MrchntNo" id="MrchntNo" value="010650082990000"/><input type="hidden" name="MerType" id="MerType" value="8299"/><input type="hidden" name="PayValidityTime" id="PayValidityTime" value="20250911121024"/><input type="hidden" name="GlobalBusiTrackNo" id="GlobalBusiTrackNo" value="20250911114025991001430039080665"/><input type="hidden" name="SubtxNo" id="SubtxNo" value="99100143003910000000000000000000"/><input type="hidden" name="SubMercCode" id="SubMercCode" value="8299000007077701045"/><input type="hidden" name="DctDetail" id="DctDetail" value="[]"/><input type="hidden" name="NativeFlag" id="NativeFlag" value="00"/><input type="hidden" name="PageFlag" id="PageFlag" value="1"/><input type="hidden" name="CdFlag" id="CdFlag" value="21"/><input type="hidden" name="ReductionInfo" id="ReductionInfo" value=""/><input type="hidden" name="GatewayFlag" id="GatewayFlag" value="03"/></form></body><script type="text/javascript">var formDom = document.getElementById('form');function load() { formDom.submit(); }</script></html> at pages/bankPayment/index.vue:30 11:42:27.510 [Vue warn]: Unhandled error during execution of onLoad at <Index__pageId=5__pagePath="pages/bankPayment/index"__pageQuery={"cashierHtml":"<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /><title></title></head><body onload=\"load()\"><form id = \"form\" action=\"http://wap.dev.psbc.com/mobilebank/CashierDeskStart.do\" method=\"post\"><input type=\"hidden\" name=\"MercName\" id=\"MercName\" value=\"徐州市铜山区大许镇阳光幼教幼儿园\"/><input type=\"hidden\" name=\"MercCode\" id=\"MercCode\" value=\"1100529319992199476\"/><input type=\"hidden\" name=\"TransAmt\" id=\"TransAmt\" value=\"1\"/><input type=\"hidden\" name=\"OrderNum\" id=\"OrderNum\" value=\"CPN034ez8rd7flkp10240002fzc001\"/><input type=\"hidden\" name=\"MercDtTm\" id=\"MercDtTm\" value=\"20250911114024\"/><input type=\"hidden\" name=\"MerCustId\" id=\"MerCustId\" value=\"26609\"/><input type=\"hidden\" name=\"Plain\" id=\"Plain\" value=\"{'PlatMercCode':'1100529319992199476','TransChannl':'01','InstType':'1111110','QpLtAcctType':'1110','GwLtAcctType':'111011','OlLtAcctType':'01','MercDtTm':'20250911114024','OrderNum':'CPN034ez8rd7flkp10240002fzc001','MercCode':'8299000007077701045','TransAmt':'1','MercUrl':'/esbHttpSrv/sendPostData/99100140001_OPSS_thirdpayLargeMerchants','ReSuccUrl':'http://openpayment.dev.psbc.com:8080/h5xctest/h5/#/paySuccess?out_trade_no=CPN034ez8rd7flkp10240002fzc001','OrderUrl':'','Remark1':'','Remark2':'','ValidTime':'30','MercName':'徐州市铜山区大许镇阳光幼教幼儿园','BizTp':'110001','OrderTitle':'2025年9月伙食费','OrderCount':'1','OrderDetail':[{'SubMercCode':'8299000007077701045','SubMercName':'徐州市铜山区大许镇阳光幼教幼儿园','TotalAmt':'1','TotalNum':'1','MerUnitDetail':'2025年9月伙食费^1^1'}],'PlfmNm':'','TrxDevcInf':'ABCD:EF01:2345:6789:ABCD:EF01:2345:6789|F0E1D2C3B4A5|010102020303040|01020304050 6070|00112233445566778899|5A4B3C2D1E0F|116.123456,-39.987654|','PyeeAcctIssrId':'C1040311005293','PyeeAcctTp':'05','PyeeAcctId':'4130130413015010001291000130','PyeeNm':'昆山市假日置业有限公司','TerminalIp':'127.0.0.1','MerCustId':'26609','PayEnv':'01','QpTranChnl':'0','GwTranChnl':'0','InterAcctno':'4415602000739195','InterAcctOrganCode':'44001483','DevOrganCode':'11005293','WchatAppId':'','OpenId':'','ReserveParam':'','CreditorWalletName':'内部业务钱包青岛分行医保社保','CreditorWalletId':'0082000020475894','CreditorWalletType':'WT10','CreditorWalletLevel':'WL01','MerCertType':'','MerCerId':'','TradeBizType':'206','TradeCategoryCode':'20600017','PhonePayEnv':'','AreaInfo':'120101','NativeFlag':'00','PageFlag':'1','AtvFlag':'0','AtvID':'','Reserve1':'','MerAcctTp':'0','MerAcctNo':'963011013000078213','MerAcctName':'测试客户合并','MerBankNo':'','MerBankName':'','QyFlag':'','BusinessLicense':'120101673864374'}\"/><input type=\"hidden\" name=\"Signature\" id=\"Signature\" value=\"042f03f10adb90f8256892536d185d3d6375be7e27d806d59efe3e86ebeb9115abc229659064cd7b7fc4b2871406c3973f0ffaa7d61ba958b8c61bd0f4be5781665854c9f1512c52c69fa774181db9e56b2ff20b045f0d8dce67e6d746850636222d17e0d063d19e2de1b98c487632cca80c6dbde3e77a12e2b060a094f5148b\"/><input type=\"hidden\" name=\"OpenFlag\" id=\"OpenFlag\" value=\"11111101111000000000000000000000000000000000000000\"/><input type=\"hidden\" name=\"PayChannel\" id=\"PayChannel\" value=\"11\"/><input type=\"hidden\" name=\"QPayChannel\" id=\"QPayChannel\" value=\"11\"/><input type=\"hidden\" name=\"Flag\" id=\"Flag\" value=\"110100\"/><input type=\"hidden\" name=\"MrchntNo\" id=\"MrchntNo\" value=\"010650082990000\"/><input type=\"hidden\" name=\"MerType\" id=\"MerType\" value=\"8299\"/><input type=\"hidden\" name=\"PayValidityTime\" id=\"PayValidityTime\" value=\"20250911121024\"/><input type=\"hidden\" name=\"GlobalBusiTrackNo\" id=\"GlobalBusiTrackNo\" value=\"20250911114025991001430039080665\"/><input type=\"hidden\" name=\"SubtxNo\" id=\"SubtxNo\" value=\"99100143003910000000000000000000\"/><input type=\"hidden\" name=\"SubMercCode\" id=\"SubMercCode\" value=\"8299000007077701045\"/><input type=\"hidden\" name=\"DctDetail\" id=\"DctDetail\" value=\"[]\"/><input type=\"hidden\" name=\"NativeFlag\" id=\"NativeFlag\" value=\"00\"/><input type=\"hidden\" name=\"PageFlag\" id=\"PageFlag\" value=\"1\"/><input type=\"hidden\" name=\"CdFlag\" id=\"CdFlag\" value=\"21\"/><input type=\"hidden\" name=\"ReductionInfo\" id=\"ReductionInfo\" value=\"\"/><input type=\"hidden\" name=\"GatewayFlag\" id=\"GatewayFlag\" value=\"03\"/></form></body><script type=\"text/javascript\">var formDom = document.getElementById('form');function load() { formDom.submit(); }</script></html>"} ...> 11:42:27.510 ReferenceError: Blob is not defined
最新发布
09-12
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值