如何在Android WebView应用中实现文件上传功能?
Android WebView 文件上传功能适配方案
你当前的代码缺少WebView文件上传必需的回调处理逻辑,按以下步骤修改即可实现文件上传功能。
第一步:修改AndroidManifest.xml配置
在<manifest>标签下添加所需权限:
<!-- 存储访问权限,选择本地文件需要 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 如需支持拍照上传可添加下面的权限 --> <uses-permission android:name="android.permission.CAMERA" />
同时在<application>标签中添加属性,适配非加密站点加载:
android:usesCleartextTraffic="true"
第二步:替换MainActivity.java代码
完整代码已添加关键注释,可直接替换使用:
import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private WebView webView; // 接收文件选择结果的回调对象 private ValueCallback<Uri[]> mUploadMessage; // 文件选择请求标识 private final static int FILE_CHOOSER_RESULT_CODE = 1; // 权限申请请求标识 private final static int PERMISSION_REQUEST_CODE = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webviewid); // 先申请运行时权限 checkAndRequestPermissions(); // 配置WebView基础参数 webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webView.getSettings().setDomStorageEnabled(true); webView.getSettings().setAllowFileAccess(true); // 处理页面加载逻辑 webView.setWebViewClient(new WebViewClient()); // 新增:处理文件上传、弹窗等交互逻辑 webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadMessage = filePathCallback; // 调用系统文件选择器 Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); // 可根据需求修改文件类型,*/*代表所有类型 intent.setType("*/*"); startActivityForResult(Intent.createChooser(intent, "选择文件"), FILE_CHOOSER_RESULT_CODE); return true; } }); // 所有配置完成后再加载页面 webView.loadUrl("https://www.google.com/"); } // 接收文件选择结果并回传给WebView @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_CHOOSER_RESULT_CODE) { if (mUploadMessage == null) return; Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, data); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } } // 动态申请Android 6.0以上所需的危险权限 private void checkAndRequestPermissions() { String[] permissions = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA }; if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "需要存储权限才能上传文件", Toast.LENGTH_SHORT).show(); } } } // 优化返回键逻辑,点击返回先退回上一级网页 @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } }
注意事项
- 不需要拍照上传的话,可以删除权限配置和申请逻辑中所有和CAMERA相关的代码
- 如果你的App目标SDK版本为33(Android 13)及以上,需要将READ_EXTERNAL_STORAGE替换为对应媒体权限,基础测试阶段可以先将目标SDK设为32避免额外适配
- 所有Web配置项必须放在loadUrl之前执行,避免配置未生效就加载页面导致功能异常
内容的提问来源于stack exchange,提问作者Ambiguous Turtle
相关产品推荐
相关产品推荐

