目标:能够将任意类型的文件附加到<input type="file" />
webview
中的Android 4.1+
。 (Android 5+很好)
我根据我发现的几个例子设置了openFileChooser
。它适用于4.1
但不适用于4.4.4
,其中附加的文件未正确设置文件名。
相反,将intent.mData
的{{1}}的最后一个路径设置为onActivityResult
,。eg,mData
值为content://com.android.providers.downloads.documents/document/2
,文件名为2
- 没有扩展当然 - 名称应该是image.png
。
我该怎么做才能修复它?我的代码会有任何问题吗?
我在模拟器上进行测试:Galaxy Nexus,API 19,目标:默认
请参阅下面的代码。
webView.setWebChromeClient(new WebChromeClient() {
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
if (UseWebViewActivity.this.valueCallback != null) {
UseWebViewActivity.this.valueCallback.onReceiveValue(null);
}
UseWebViewActivity.this.valueCallback = valueCallback;
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");
startActivityForResult(Intent.createChooser(contentSelectionIntent,
getString(R.string.file_chooser_title)), INPUT_FILE_REQUEST_CODE);
}
});
// ...
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == INPUT_FILE_REQUEST_CODE && valueCallback != null) {
Uri result = null;
if (resultCode == Activity.RESULT_OK) {
result = intent.getData();
}
valueCallback.onReceiveValue(result);
valueCallback = null;
}
}
答案 0 :(得分:5)
问题出在KitKat的onActivityResult()方法中,它返回URI。你需要获得图像文件的真实路径。
请注意我如何通过调用以下方式获取IMG的真实路径:
KitkatPath = Uri.parse(&#34; file://&#34; + getPath(MobilestyxAppActivity.this,result));在onActivityResult()。
您必须添加字符串&#34; file://&#34;它的工作原理。
PS:我收集了各种来源的代码并对其进行了修改。
请查看下面的代码,该代码适用于Kitkat&amp; Lolipop和其他低版本的Android。
/** CODE FOR FILE UPLOAD*/
private static final int INPUT_FILE_REQUEST_CODE = 1;
private static final int FILECHOOSER_RESULTCODE = 1;
private ValueCallback<Uri> mUploadMessage;
private Uri mCapturedImageURI = null;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
Uri KitkatPath ;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null) {
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
}
else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
System.out.println("In KitKat Condition");
if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {
System.out.println("In != Null");
super.onActivityResult(requestCode, resultCode, data);
return;
}
if (requestCode == FILECHOOSER_RESULTCODE) {
System.out.println("requestCode == FileChooser ResultCode");
if (null == this.mUploadMessage) {
System.out.println("In null == this.mUploadMessage");
return;
}
Uri result = null;
try {
if (resultCode != RESULT_OK) {
result = null;
} else {
//newcode
// retrieve from the private variable if the intent is null
result = data == null ? mCapturedImageURI : data.getData();
KitkatPath = Uri.parse("file://"+getPath(MobilestyxAppActivity.this, result));
System.out.println("KitkatPath== "+KitkatPath);
System.out.println("result = "+result);
}
} catch (Exception e) {
// Toast.makeText(getApplicationContext(), "activity :" + e, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
// mUploadMessage.onReceiveValue(result);
mUploadMessage.onReceiveValue(KitkatPath);
System.out.println("mUploadMessage = "+mUploadMessage);
mUploadMessage = null;
}
}
return;
}
/** CODE FOR FILE UPLOAD*/
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(heightDiff));
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File imageFile = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return imageFile;
}
&安培;现在在WebViewChromeClient ---
browser.setWebChromeClient(new WebChromeClient() {
// For Android 5.0
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
System.out.println("in 5.0");
// Double check that we don't have any existing callbacks
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePath;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
// Log.e(TAG, "Unable to create Image File", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
return true;
}
// openFileChooser for Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
System.out.println("in 3.0+");
mUploadMessage = uploadMsg;
// Create AndroidExampleFolder at sdcard
// Create AndroidExampleFolder at sdcard
File imageStorageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
, "AndroidExampleFolder");
if (!imageStorageDir.exists()) {
// Create AndroidExampleFolder at sdcard
imageStorageDir.mkdirs();
}
// Create camera captured image file path and name
File file = new File(
imageStorageDir + File.separator + "IMG_"
+ String.valueOf(System.currentTimeMillis())
+ ".jpg");
mCapturedImageURI = Uri.fromFile(file);
//
// Camera capture image intent
final Intent captureIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
// Create file chooser intent
Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
// Set camera intent to file chooser
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
, new Parcelable[] { captureIntent });
// On select image call onActivityResult method of activity
startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
// openFileChooser for Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
System.out.println("in <3.0");
openFileChooser(uploadMsg, "");
}
// openFileChooser for other Android versions
public void openFileChooser(ValueCallback<Uri> uploadMsg,
String acceptType, String capture) {
System.out.println("in OTHER");
openFileChooser(uploadMsg, acceptType);
}
答案 1 :(得分:4)
尝试使用aFileChooser以避免API级别兼容性的复杂化(库已经处理完毕):
aFileChooser是一个简化流程的Android库项目 在Android 2.1 +上展示文件选择器。
Intent提供了挂钩第三方应用程序组件的功能 用于内容选择。这适用于媒体文件,但如果你 希望用户能够选择任何文件,他们必须具有现有文件 安装了“文件浏览器”应用程序。因为很多Android设备都没有 库存文件浏览器,开发人员必须经常指导用户 自己安装一个或构建一个。 aFileChooser解决了这个问题。
功能强>
Full file explorer Simplify GET_CONTENT Intent creation Hooks into Storage Access Framework Determine MIME data types Follows Android conventions (Fragments, Loaders, Intents, etc.) Supports API 7+
检查The repo's GitHub page上的readme.md
是否有设置和使用说明。
答案 2 :(得分:2)
Android 4.1和4.4在此处有不同的工作方式,因为Android 4.4(API级别19)中引入了Storage Access Framework。要检索文件名,您可以尝试以下方法:
Uri uri = intent.getData();
File imageFile = new File(uri);
if(imageFile.exists()){
String name = imageFile.getName();
}