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

如何在Android WebView中改用Photo Picker实现图片上传至服务器?

替换WebView图片选择器为Photo Picker(PickVisualMediaRequest)实现方案

问题背景

现有WebView上传图片的代码依赖传统文件选择器,因应用主功能并非处理图片,后续将无法获取READ_MEDIA_IMAGES权限,需替换为Android官方的Photo Picker(基于PickVisualMediaRequest)来实现图片选择。

实现步骤

1. 版本适配判断

Photo Picker仅在Android 13(API 33)及以上系统支持,低版本需保留原文件选择逻辑作为降级方案。

2. 修改文件选择回调逻辑

在onShowFileChooser方法中,根据系统版本切换图片选择方式:

  • API 33+:构建PickVisualMediaRequest并启动Photo Picker
  • 低版本:沿用原文件选择器逻辑

3. 处理选择结果

更新onActivityResult方法,分别接收Photo Picker和低版本文件选择器返回的图片Uri,传递给WebView的回调。

修改后的完整代码

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private ValueCallback<Uri[]> mFilePathCallback;
    private final static int FILECHOOSER_RESULTCODE = 1;
    private final static int PHOTO_PICKER_REQUEST_CODE = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());

        webView.setWebChromeClient(new WebChromeClient() {
            // Android 5.0+ 文件选择回调
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                // 清除未处理的旧回调
                if (mFilePathCallback != null) {
                    mFilePathCallback.onReceiveValue(null);
                }
                mFilePathCallback = filePathCallback;

                // 判断系统版本,选择对应图片选择方式
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    // 构建仅选择图片的Photo Picker请求
                    PickVisualMediaRequest request = new PickVisualMediaRequest.Builder()
                            .setMediaType(PickVisualMedia.ImageOnly.INSTANCE)
                            .build();
                    startActivityForResult(Intent.createChooser(request.getIntent(), "选择图片"), PHOTO_PICKER_REQUEST_CODE);
                } else {
                    // 低版本沿用原有文件选择逻辑
                    Intent intent = fileChooserParams.createIntent();
                    startActivityForResult(intent, FILECHOOSER_RESULTCODE);
                }

                return true;
            }
        });

        // 加载目标网页
        webView.loadUrl("https://site.html");
    }

    @SuppressLint("MissingSuperCall")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Uri[] result = null;
        // 处理Photo Picker返回结果
        if (requestCode == PHOTO_PICKER_REQUEST_CODE) {
            if (resultCode == RESULT_OK && data != null) {
                Uri selectedUri = data.getData();
                if (selectedUri != null) {
                    result = new Uri[]{selectedUri};
                }
            }
            mFilePathCallback.onReceiveValue(result);
            mFilePathCallback = null;
        } 
        // 处理低版本文件选择器返回结果
        else if (requestCode == FILECHOOSER_RESULTCODE) {
            if (resultCode == RESULT_OK && data != null) {
                String dataString = data.getDataString();
                if (dataString != null) {
                    result = new Uri[]{Uri.parse(dataString)};
                }
            }
            mFilePathCallback.onReceiveValue(result);
            mFilePathCallback = null;
        }
    }
}

关键说明

  • PickVisualMedia.ImageOnly.INSTANCE指定仅选择图片,若需限定特定格式,可改为PickVisualMedia.SingleMimeType("image/*")
  • Photo Picker无需申请READ_MEDIA_IMAGES权限,系统会自动授权临时访问选中的图片Uri
  • 如需支持多选图片,可在PickVisualMediaRequest中添加.setSelectionMode(PickVisualMediaSelectionMode.MULTIPLE),并在结果处理中批量获取Uri

内容的提问来源于stack exchange,提问作者Юрий Берека

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:31:03