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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:54:05