Falta el nombre de archivo para openFileChooser Android 4.4.4

Objetivo: poder adjuntar un archivo de cualquier tipo a un <input type="file" /> en una vista webview en Android 4.1+ . (Android 5+ está bien)

He establecido openFileChooser como he visto en función de los pocos ejemplos que he encontrado. Funciona en 4.1 pero no en 4.4.4 donde los archivos adjuntos no tienen su nombre de archivo correctamente establecido .
En lugar de ello, se establece como nombre de archivo la última ruta de acceso de la dirección intent.mData a onActivityResult , .eg, para un valor mData de content://com.android.providers.downloads.documents/document/2 , el nombre de archivo será 2 -without Extensión de supuesto-mientras que el nombre debe ser image.png .

¿Que puedo hacer para arreglarlo? ¿Habría algún problema en mi código?

Hago mis pruebas en un emulador: Galaxy Nexus, API 19, target: Default
Vea el código abajo.

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

Intente usar aFileChooser para evitar complicaciones con compatibilidades de nivel de API (la biblioteca lo ha manejado):

AFileChooser es un proyecto de biblioteca de Android que simplifica el proceso de presentación de un selector de archivos en Android 2.1+.

Los intentos brindan la posibilidad de conectarse a componentes de aplicaciones de terceros para la selección de contenido. Esto funciona bien para los archivos multimedia, pero si desea que los usuarios puedan seleccionar cualquier archivo, deben tener instalada una aplicación "explorador de archivos" existente. Debido a que muchos dispositivos Android no tienen exploradores de archivo de archivo, el desarrollador debe instruir a menudo al usuario para instalar uno, o construir uno, ellos mismos. AFileChooser resuelve este problema.

caracteristicas:

 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+ 

Compruebe el readme.md en la página GitHub del repo para las instrucciones de instalación y uso.

El problema está en el método onActivityResult () para KitKat que devuelve el URI. Necesita obtener el realpath del archivo de imagen.

Observe cómo obtengo el Camino Real del IMG llamando a:

KitkatPath = Uri.parse ("file: //" + getPath (MobilestyxAppActivity.this, resultado)); En el onActivityResult ().

Debe agregar la cadena "file: //" para que funcione.

PS: He recopilado el código de varias fuentes y lo he modificado.

Mira mi código a continuación que funciona para Kitkat & Lolipop y otras versiones bajas de 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; } 

& Ahora en el 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); } 

Android 4.1 y 4.4 tienen diferentes funciones aquí desde que Storage Access Framework fue introducido en Android 4.4 (API nivel 19). Para recuperar el nombre del archivo, puede probar algo como esto:

 Uri uri = intent.getData(); File imageFile = new File(uri); if(imageFile.exists()){ String name = imageFile.getName(); } 
  • Android webview - solo línea javascript comentarios causando Uncaught SyntaxError errores?
  • DequeueBuffer: no se puede eliminar varios buffers sin establecer el contador de búfer
  • ¿Es posible acceder a la caché WebView?
  • Pantalla en blanco de Android en onBack en un archivo loadDataWithBaseURL
  • Appcache en Android Webview no descargar fuentes
  • ¿Hay una manera de pre-cache de una página web para ver con un Android WebView?
  • Cómo obtener la actividad de vista Web para desaparecer con PDF Link Action_view
  • Guardar / restaurar estado de android webview
  • Aplicación existente explotando con Android 3.0 XOOM. ¿Fugas de ZoomButtonsController?
  • Viewport ajusta el ancho de la pantalla y las grandes imágenes
  • Twitter Bootstrap no funciona en Android WebView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.