Имя файла отсутствует для openFileChooser Android 4.4.4

Цель: уметь прикреплять файл любого типа к <input type="file" /> в webview в Android 4.1+ . (Android 5+ в порядке)

Я установил openFileChooser как я openFileChooser в соответствии с несколькими примерами, которые я нашел. Он работает на 4.1 но не на 4.4.4 где прикрепленные файлы не имеют правильного их имени файла .
Вместо этого в качестве имени файла intent.mData последний путь в intent.mData возвращаемый onActivityResult , .eg, для значения mData content://com.android.providers.downloads.documents/document/2 , имя файла будет 2 без Расширение курса – в то время как имя должно быть image.png .

Что я могу сделать, чтобы исправить это? Будут ли какие-либо проблемы в моем коде?

Я тестирую эмулятор: Galaxy Nexus, API 19, target: Default
См. Код ниже.

 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; } } 

Solutions Collecting From Web of "Имя файла отсутствует для openFileChooser Android 4.4.4"

Попробуйте использовать aFileChooser, чтобы избежать осложнений с совместимостью API-уровня (с обработкой библиотеки):

AFileChooser – это проект библиотеки Android, который упрощает процесс представления выбора файлов на Android 2.1+.

Intents предоставляют возможность подключаться к сторонним компонентам приложения для выбора контента. Это хорошо работает для медиафайлов, но если вы хотите, чтобы пользователи могли выбирать любой файл, у них должно быть установлено существующее приложение «File Explorer». Поскольку на многих устройствах Android нет файлов File Explorers, разработчик должен часто давать инструкции пользователю самостоятельно устанавливать или самостоятельно создавать. 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+ 

Проверьте readme.md на странице GitHub репо для инструкций по настройке и использованию.

Проблема заключается в методе onActivityResult () для KitKat, который возвращает URI. Вам нужно получить реальный путь к файлу изображения.

Обратите внимание, как я получаю реальный путь IMG, позвонив:

KitkatPath = Uri.parse ("file: //" + getPath (MobilestyxAppActivity.this, результат)); В onActivityResult ().

Вы должны добавить строку «file: //», чтобы она работала.

PS: Я собрал код из разных источников и модифицировал его.

Посмотрите мой код ниже, который работает для Kitkat & 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 (новый 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); } 

Android 4.1 и 4.4 имеют различные функции здесь, поскольку Storage Access Framework была представлена ​​в Android 4.4 (API уровня 19). Чтобы получить имя файла, вы можете попробовать что-то вроде этого:

 Uri uri = intent.getData(); File imageFile = new File(uri); if(imageFile.exists()){ String name = imageFile.getName(); }