Android WebView APK文件上传下载功能失效问题求助
WebView APK 文件上传/下载功能失效问题
我用Android Studio将个人网站转换为WebView APK应用,整体运行正常,但文件上传与下载功能完全无法使用。已在AndroidManifest中添加所有必要权限,问题仍未解决。
MainActivity.java 代码
package com.example.eprepareacademy2o; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Window; import android.webkit.DownloadListener; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { String websiteURL = "xyz.com/"; // 设置网页地址 private WebView webview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if( ! CheckNetwork.isInternetAvailable(this)) // 检查网络是否可用 { setContentView(R.layout.activity_main); new AlertDialog.Builder(this) .setTitle("无网络连接") .setMessage("请检查移动数据或WiFi网络") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }) .show(); } else { // WebView配置 webview = findViewById(R.id.webView); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setAllowFileAccess(true); webview.getSettings().setAllowFileAccessFromFileURLs(true); webview.getSettings().setAllowUniversalAccessFromFileURLs(true); webview.setWebChromeClient(new WebChromeClient() { public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { // 未处理文件上传 return true; } }); webview.setDownloadListener(new DownloadListener() { public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { // 未处理文件下载 } }); webview.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView webView, String url) { if (url.endsWith(".pdf")) { // 未处理PDF下载 return true; } return false; } }); webview.loadUrl("xyz.com/"); webview.getSettings().setDomStorageEnabled(true); webview.setOverScrollMode(WebView.OVER_SCROLL_NEVER); webview.loadUrl(websiteURL); webview.setWebViewClient(new WebViewClientDemo()); webview.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { // 重复设置,未处理文件上传 return true; } }); } } private class WebViewClientDemo extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("http:") || url.startsWith("https:")) { view.loadUrl(url); return true; } else { view.loadUrl(websiteURL + url); return true; } } } @Override public void onBackPressed() { if (webview.isFocused() && webview.canGoBack()) { webview.goBack(); } else { new AlertDialog.Builder(this) .setTitle("退出应用") .setMessage("确定要关闭应用吗?") .setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }) .setNegativeButton("否", null) .show(); } } } class CheckNetwork { private static final String TAG = CheckNetwork.class.getSimpleName(); public static boolean isInternetAvailable(Context context) { NetworkInfo info = (NetworkInfo) ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); if (info == null) { Log.d(TAG,"无网络连接"); return false; } else { if(info.isConnected()) { Log.d(TAG,"网络连接正常"); return true; } else { Log.d(TAG,"网络连接异常"); return true; // 此处逻辑错误,未连接应返回false } } } // 未被使用的冗余内部类 private class WebViewClientDemo extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.loadUrl("javascript:(function() { " + "var videos = document.getElementsByTagName('video'); " + "for(var i=0;i<videos.length;i++) { " + "videos[i].setAttribute('webkit-playsinline', ''); " + "videos[i].setAttribute('playsinline', ''); " + "videos[i].setAttribute('controls', ''); " + "videos[i].setAttribute('style', 'max-width:100%; height:auto;'); " + "}" + "var iframes = document.getElementsByTagName('iframe');" + "for(var i=0;i<iframes.length;i++){" + "if(iframes[i].src.includes('youtube') || iframes[i].src.includes('vimeo')) {" + "iframes[i].setAttribute('frameborder', '0');" + "iframes[i].setAttribute('allowfullscreen', '');" + "iframes[i].setAttribute('webkitallowfullscreen', '');" + "iframes[i].setAttribute('mozallowfullscreen', '');" + "iframes[i].setAttribute('style', 'width:100%; height:100%;');" + "}" + "}" + ")()"); } } }
AndroidManifest.xml 权限配置
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET"/> <!-- 重复权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:usesCleartextTraffic="true" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@drawable/ic_launcher_foreground" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.EprepareAcademy2O" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="false" /> <activity android:name=".SplashActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
问题修复方案
1. 文件上传功能修复
原代码onShowFileChooser为空实现,需实现文件选择Intent跳转并处理结果:
- 添加全局变量:
private ValueCallback<Uri[]> mFilePathCallback; private static final int FILE_CHOOSER_REQUEST_CODE = 1000; - 重写
onShowFileChooser:webview.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (mFilePathCallback != null) { mFilePathCallback.onReceiveValue(null); mFilePathCallback = null; } mFilePathCallback = filePathCallback; Intent intent = fileChooserParams.createIntent(); try { startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE); } catch (ActivityNotFoundException e) { mFilePathCallback = null; Toast.makeText(MainActivity.this, "无法打开文件选择器", Toast.LENGTH_SHORT).show(); return false; } return true; } }); - 处理Activity结果:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_CHOOSER_REQUEST_CODE) { Uri[] results = null; if (resultCode == RESULT_OK && data != null) { String[] filePaths = WebChromeClient.FileChooserParams.parseResult(resultCode, data); if (filePaths != null && filePaths.length > 0) { results = new Uri[filePaths.length]; for (int i = 0; i < filePaths.length; i++) { results[i] = Uri.parse(filePaths[i]); } } else { results = new Uri[]{data.getData()}; } } if (mFilePathCallback != null) { mFilePathCallback.onReceiveValue(results); mFilePathCallback = null; } } }
2. 文件下载功能修复
实现DownloadListener调用系统下载管理器:
webview.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setMimeType(mimeType); String filename = URLUtil.guessFileName(url, contentDisposition, mimeType); request.setTitle(filename); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); if (downloadManager != null) { downloadManager.enqueue(request); } Toast.makeText(MainActivity.this, "开始下载", Toast.LENGTH_SHORT).show(); } });
3. 权限问题修复
- 移除Manifest中重复的
INTERNET权限 - Android 10+添加Scoped Storage适配或
MANAGE_EXTERNAL_STORAGE权限 - 动态申请危险权限:
private static final String[] PERMISSIONS = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA }; private static final int PERMISSION_REQUEST_CODE = 2000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions(PERMISSIONS, PERMISSION_REQUEST_CODE); } } // 后续逻辑... } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (!allGranted) { Toast.makeText(this, "需授予权限才能使用文件功能", Toast.LENGTH_SHORT).show(); } } }
4. 代码冗余修复
- 移除重复设置的
WebChromeClient和WebViewClient - 删除
CheckNetwork中未使用的WebViewClientDemo内部类 - 修复
CheckNetwork.isInternetAvailable逻辑错误,未连接时返回false
内容的提问来源于stack exchange,提问作者Cyber fahad
相关产品推荐
相关产品推荐

