如何在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,提问作者Юрий Берека
相关产品推荐
相关产品推荐

