Android WebView 不支持 H5 input type="file" 解决方法

本文详细介绍了如何在Android WebView中实现文件选择功能,通过重写WebChromeClient,提供了适用于不同Android版本的解决方案,包括从Activity和Fragment中调用的方法。

最近因为赶项目进度,因此将本来要用原生控件实现的界面,自己做了H5并嵌入webview中。发现点击H5中 <input type="file"/>标签 不能打开android资源管理器。

通过网络搜索发现是因为 android webview 由于考虑安全原因屏蔽了 <input type="file"/> 这个功能 。

经过不懈的努力,以及google 翻译的帮助 在 stackoverflow 中找到了解决的方法。

具体可以理解为 重写webview 的WebChromeClient ,废话不多说直接贴代码:

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

webview.setWebChromeClient(new WebChromeClient(){

        // For 3.0+ Devices (Start)
        // onActivityResult attached before constructor
        protected void openFileChooser(ValueCallback uploadMsg, String acceptType)
        {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
        }


        // 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;
                Toast.makeText(getBaseContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
                return false;
            }
            return true;
        }

        //For Android 4.1 only
        protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
        {
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");
            startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
        }

        protected void openFileChooser(ValueCallback<Uri> uploadMsg)
        {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
        }

    });
}

@Override
public 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;
    }
    else
        Toast.makeText(getBaseContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show();
}





在 UniApp 中使用 `webview` 加载的 H5 页面中,如果页面包含 `<input type="file">` 标签,在安卓设备上点击该标签时,默认行为可能会仅显示相机选项,而无法直接访问文件管理器或相册。这个问题通常与安卓系统限制以及 `webview` 的权限配置有关。 ### 问题原因 安卓系统在不同版本中对 `webview` 中的文件访问权限进行了限制,尤其是在 Android 10 及以上版本中,系统默认不会直接允许 `webview` 访问本地文件系统。因此,当用户点击 `<input type="file">` 时,系统可能仅提供相机选项,而不显示文件选择器或相册[^4]。 ### 解决方案 #### 1. 配置权限请求 在原生 Android 层面,需要确保应用具有访问存储的权限。可以通过自定义 `Activity` 并在启动文件选择器之前请求权限[^4]。例如: ```java import io.dcloud.PandoraEntryActivity; public class YYPandoraEntryActivity extends PandoraEntryActivity { @Override public void startActivityForResult(Intent intent, int requestCode) { if (intent.getAction().equals("android.intent.action.GET_CONTENT")) { PermissionUtil.requestPermissions(YYPlatApplication.getCurrActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, new PermissionUtil.OnPermissionListener() { @Override public void onPermissionGranted() { runOnUiThread(() -> YYPandoraEntryActivity.super.startActivityForResult(intent, requestCode)); } @Override public void onPermissionDenied() { AbCenter.ME().postEvent("message", "permissionMessage,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE"); } }); } else { super.startActivityForResult(intent, requestCode); } } } ``` #### 2. 使用 `Intent` 启动文件选择器 在某些情况下,可以通过拦截 `Intent` 并手动启动文件选择器来绕过默认行为。例如: ```java Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, FILE_CHOOSER_RESULT_CODE); ``` #### 3. 使用 Hybrid 模式处理文件上传 在 `webview` 中,可以通过 Hybrid 模式实现文件上传功能。具体来说,可以在 H5 页面中监听 `<input type="file">` 的 `change` 事件,并通过 `uni.getFileSystemManager()` 获取文件的 `ArrayBuffer` 对象,然后上传到服务器[^2]。示例代码如下: ```javascript document.querySelector('input[type="file"]').addEventListener('change', function(event) { const file = event.target.files[0]; const reader = new FileReader(); reader.onload = function(e) { const blob = new Blob([e.target.result], { type: file.type }); const formData = new FormData(); formData.append('file', blob, file.name); // 使用 axios 或其他方式上传文件 axios.post('/file/api/Upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); }; reader.readAsArrayBuffer(file); }); ``` #### 4. 使用原生插件 如果需要更复杂的文件处理功能,可以考虑使用 UniApp 提供的原生插件。例如,某些插件可以直接返回 `File` 对象,而不是 `blob` 路径,从而简化文件上传流程[^1]。 ### 总结 在 UniApp 中使用 `webview` 加载的 H5 页面中,点击 `<input type="file">` 时在安卓设备上仅显示相机选项的问题,主要与权限配置和系统限制有关。通过请求存储权限、自定义 `Activity`、使用 Hybrid 模式或引入原生插件,可以有效解决这一问题。 ---
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值