让Android的WebView支持html里面的文件上传
默认情况下,Android的webview是不支持<input type=file>的,点击没有任何反应,如果希望点击上传,弹出选择文件、图片的窗口,那就需要自定义一个WebChromeClient
public class MyChromeClient extends WebChromeClient { public ValueCallback<Uri> UploadMsg; public ValueCallback<Uri[]> UploadMsg2; private Activity activity; public static final int FILECHOOSER_RESULTCODE = 5173; public static String mCameraFilePath = ""; @SuppressWarnings("deprecation") public MyChromeClient(Activity cordova) { this.activity = cordova; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } // <input type="file" name="fileField" id="fileField" /> // Android > 4.1.1 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // TODO 自动生成的方法存根 UploadMsg2 = filePathCallback; this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE); return false; } @SuppressWarnings("static-access") public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { UploadMsg = uploadMsg; this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE); } // 3.0 + @SuppressWarnings("static-access") public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { UploadMsg = uploadMsg; this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE); } // Android < 3.0 @SuppressWarnings("static-access") public void openFileChooser(ValueCallback<Uri> uploadMsg) { UploadMsg = uploadMsg; this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE); } private Intent createDefaultOpenableIntent() { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); Intent chooser = createChooserIntent(createCameraIntent()/* * * , * * createCamcorderIntent * * (), * * createSoundRecorderIntent * * () */); chooser.putExtra(Intent.EXTRA_INTENT, i); return chooser; } private Intent createChooserIntent(Intent... intents) { Intent chooser = new Intent(Intent.ACTION_CHOOSER); chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents); chooser.putExtra(Intent.EXTRA_TITLE, "选择图片"); return chooser; } @SuppressWarnings("static-access") private Intent createCameraIntent() { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File externalDataDir = Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); File cameraDataDir = new File(externalDataDir.getAbsolutePath() + File.separator + "515aaa"); cameraDataDir.mkdirs(); String mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg"; this.mCameraFilePath = mCameraFilePath; cameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath))); return cameraIntent; } /* * * private Intent createCamcorderIntent() { return new * * Intent(MediaStore.ACTION_VIDEO_CAPTURE); } * * * * private Intent createSoundRecorderIntent() { return new * * Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); } */ public static Uri getImageContentUri(Context context, java.io.File imageFile) { String filePath = imageFile.getAbsolutePath(); Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ", new String[] { filePath }, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor .getColumnIndex(MediaStore.MediaColumns._ID)); Uri baseUri = Uri.parse("content://media/external/images/media"); return Uri.withAppendedPath(baseUri, "" + id); } else { if (imageFile.exists()) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, filePath); return context.getContentResolver().insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { return null; } } } }
然后指定webview使用这个client
webview.setWebChromeClient( new MyChromeClient (this));
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)