我刚刚开始使用Android,但我过去使用过Java语言。
我已经在 android WebWiew 中加载了一个 Web 应用程序。应用程序已成功发布,但文件浏览按钮不起作用。我已经尝试搜索很多天了,但是我尝试过的大部分代码要么不起作用,要么已经过时了。
互联网上的相关答案也适用于旧的 Android 版本或多年前就已回答。例如,startActivityForResult() 现已弃用。
文件选择对话框确实打开,但选择文件后没有任何反应。 ActivityResult.getResultCode() 始终返回 0) 零。
这是结果的字符串版本:
ActivityResult{resultCode=RESULT_CANCELED,数据=null}
目前,我只希望浏览按钮文件选择起作用,以便这些文件与表单一起上传。
我已尝试更改权限,以及几乎所有我可以更改的内容。
目标SDK版本为33 最低 SDK 版本为 25
我发布了我尝试过的代码。为了进行测试,我用一个简单的 html 页面替换了该应用程序。我也尝试过accept='image/*' 属性。请让我知道我缺少什么?
public class MainActivity extends AppCompatActivity {
private WebView webView;
private static final int FILE_CHOOSER_ACTIVITY_CODE = 1;
private ValueCallback<Uri[]> filePath;
private ActivityResultLauncher<Intent> activityResultLauncher;
protected void onCreate(Bundle savedInstanceState) {
String webUrl = getString(R.string.hosting_url);
super.onCreate(savedInstanceState);
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webView.setWebViewClient(new CustomWebViewClient());
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setSupportZoom(false);
//webSettings.setAllowFileAccess(true);
//webSettings.setAllowContentAccess(true);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (filePath != null) {
filePath.onReceiveValue(null);
}
System.out.println(result);
Log.d("info", "Result code is " + result.getResultCode());
if (result.getResultCode() == FILE_CHOOSER_ACTIVITY_CODE) {
Uri[] results = null;
Log.d("Info", "Result code " + result.getResultCode());
//if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
//Uri uri = new Uri(data.getData());
if (data != null) {
if (null == filePath) {
return;
}
results = new Uri[]{data.getData()};
filePath.onReceiveValue(results);
System.out.println(results.toString());
}
//} else {
// filePath = null;
//}
}
}
}
);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
filePath = filePathCallback;
if (checkPermissions()) {
Intent getContent = new Intent(Intent.ACTION_GET_CONTENT);
//getContent.addCategory(Intent.CATEGORY_OPENABLE);
getContent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContent.setType("*/*");
//String[] mimeTypes = {"text/*", "image/"};
//getContent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
//getContent.createChooser(getContent, "Choose a File");
activityResultLauncher.launch(getContent);
return true;
} else {
Toast.makeText(MainActivity.this, "Permissions are required", Toast.LENGTH_SHORT);
}
return false;
}
});
}
public boolean checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
//|| ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
) {
String requiredPermissions[] = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
ActivityCompat.requestPermissions(MainActivity.this, requiredPermissions, 1);
return false;
} else {
return true;
}
}
....
....
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- <uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" /> -->
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.abc"
tools:targetApi="31"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
测试.html
<html>
<head>
<title>
Upload
</title>
</head>
<body>
<form method='post' enctype='multipart/form-data' action=''>
<input type="file"/>
<input type='submit' value='Upload Now' />
</form>
</body>
</html>
我能够解决这个问题。 @blackapps 提供的链接有帮助。这也允许文件下载,但我后来意识到这不起作用。这是部分代码:
public class MainActivity extends AppCompatActivity {
private WebView webView;
private ProgressBar progressBar;
private ValueCallback<Uri[]> filePath;
private ActivityResultLauncher<Intent> activityResultLauncher;
private static final int PERMISSIONS_REQUEST_CODE = 1;
protected void onCreate(Bundle savedInstanceState) {
String webUrl = getString(R.string.hosting_url);
super.onCreate(savedInstanceState);
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressBar);
webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webView.setWebViewClient(new CustomWebViewClient());
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setSupportZoom(false);
webView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Uri[] uris;
Intent data = result.getData();
if (data != null) {
if (data.getClipData() != null) { // more than one file
int totalFiles = data.getClipData().getItemCount();
uris = new Uri[totalFiles];
for (int i = 0; i < totalFiles; i++) {
Uri uri = data.getClipData().getItemAt(i).getUri();
uris[i] = uri;
}
} else { // one file
uris = new Uri[]{data.getData()};
}
filePath.onReceiveValue(uris);
}
} else {
filePath.onReceiveValue(null);
}
}
}
);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
filePath = filePathCallback;
if (checkPermissions()) {
Intent getContent = new Intent(Intent.ACTION_GET_CONTENT);
getContent.addCategory(Intent.CATEGORY_OPENABLE);
getContent.setType("*/*");
if (fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE) {
getContent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, getContent);
activityResultLauncher.launch(chooserIntent);
return true;
}
return false;
}
});
// .....
}
public boolean checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
) {
String[] requiredPermissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(MainActivity.this, requiredPermissions, MainActivity.PERMISSIONS_REQUEST_CODE);
return false;
} else {
return true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MainActivity.PERMISSIONS_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this, "Please click the browse button again.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Permission is required to upload files, otherwise browse button will not work.", Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "If permission was denied more than once, then from Settings, allow Media and file access permission for " + R.string.app_name, Toast.LENGTH_SHORT).show();
}
}
}
}
AndoidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
<!-- .... -->
</manifest>