You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求Android SDK33-34版本WebView文件上传功能的实现方案

适配SDK33-34的WebView文件上传实现方案

1. 声明并动态申请权限

SDK33及以上版本,文件读取权限拆分为媒体类型权限,需在配置和代码中做对应处理:

  • 在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- 兼容SDK32及以下版本 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
  • 在Activity/Fragment中动态申请权限:
private static final int PERMISSION_REQUEST_CODE = 1001;

private void requestMediaPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        String[] permissions = {
                Manifest.permission.READ_MEDIA_IMAGES,
                Manifest.permission.READ_MEDIA_VIDEO,
                Manifest.permission.READ_MEDIA_AUDIO
        };
        if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
        }
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{permission}, PERMISSION_REQUEST_CODE);
        }
    }
}

在Activity启动时调用requestMediaPermissions(),确保用户授权后再启用文件上传功能。

2. 配置WebChromeClient处理文件选择回调

WebView的文件上传依赖WebChromeClient的onShowFileChooser方法,SDK33+下直接使用官方提供的FileChooserParams构建Intent即可:

private ValueCallback<Uri[]> mFilePathCallback;
private static final int FILE_CHOOSER_REQUEST_CODE = 1000;

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        mFilePathCallback = filePathCallback;
        Intent intent = fileChooserParams.createIntent();
        try {
            startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
        } catch (ActivityNotFoundException e) {
            mFilePathCallback = null;
            Toast.makeText(MainActivity.this, "无法打开文件选择器", Toast.LENGTH_SHORT).show();
            return false;
        }
        return true;
    }
});

3. 处理文件选择结果

根据你使用的Android版本,选择对应的结果处理方式:

方式1:使用onActivityResult(兼容旧版)

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode != FILE_CHOOSER_REQUEST_CODE || mFilePathCallback == null) {
        return;
    }

    Uri[] results = null;
    if (resultCode == RESULT_OK && data != null) {
        ClipData clipData = data.getClipData();
        if (clipData != null) {
            results = new Uri[clipData.getItemCount()];
            for (int i = 0; i < clipData.getItemCount(); i++) {
                results[i] = clipData.getItemAt(i).getUri();
            }
        } else {
            results = new Uri[]{data.getData()};
        }
    }

    mFilePathCallback.onReceiveValue(results);
    mFilePathCallback = null;
}

方式2:使用registerForActivityResult(AndroidX推荐)

在Activity的onCreate中注册结果回调:

private ActivityResultLauncher<Intent> fileChooserLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (mFilePathCallback == null) return;

            Uri[] results = null;
            if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                Intent data = result.getData();
                ClipData clipData = data.getClipData();
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        results[i] = clipData.getItemAt(i).getUri();
                    }
                } else {
                    results = new Uri[]{data.getData()};
                }
            }
            mFilePathCallback.onReceiveValue(results);
            mFilePathCallback = null;
        }
);

然后修改onShowFileChooser中的启动代码:

fileChooserLauncher.launch(intent);

4. 配置WebSettings基础参数

确保WebView启用必要的设置以支持文件上传:

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // 文件上传控件依赖JS
webSettings.setAllowFileAccess(true);
webSettings.setAllowContentAccess(true);
// SDK30+允许本地文件跨域访问
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    webSettings.setAllowFileAccessFromFileURLs(true);
    webSettings.setAllowUniversalAccessFromFileURLs(true);
}

内容的提问来源于stack exchange,提问作者Jeremy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:33:28