studio programacion móviles files example desarrollo curso aplicaciones java android webview android-4.4-kitkat

java - programacion - webview upload file example



¿El selector de archivos de Android 4.4 WebView no se abre? (8)

Echa un vistazo a this . Debido a que el api 19 4.4, webview se ha migrado para usar Chromium, ya no WebChromeClient.

Estamos creando una aplicación que utiliza la vista web y accederemos a una página donde el usuario necesita cargar un archivo. Estamos experimentando problemas con Android 4.4, donde el selector de archivos no se abre y al hacer clic en el botón de carga no ocurre nada. Esta funcionalidad funciona con versiones anteriores utilizando el método openFileChooser de la siguiente manera:

webview.setWebChromeClient(new WebChromeClient() { //The undocumented magic method override //Eclipse will swear at you if you try to put @Override here // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); } // For Android 3.0+ public void openFileChooser(ValueCallback uploadMsg, String acceptType) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); MainActivity.this.startActivityForResult( Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE); } //For Android 4.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), MainActivity.FILECHOOSER_RESULTCODE); } });

He pasado una buena cantidad de tiempo buscando una forma de hacerlo en 4.4, pero no he tenido suerte. ¿Alguien ha logrado hacer esto?


Encontré una solución que funcionó para mí. He añadido una regla más en proguard-android.txt :

-keepclassmembers class * extends android.webkit.WebChromeClient { public void openFileChooser(...); }


Este código funcionó para mí.

private class MyWebChromeClient extends WebChromeClient { //The undocumented magic method override //Eclipse will swear at you if you try to put @Override here // For Android 3.0+ public void openFileChooser(ValueCallback uploadMsg, String acceptType) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); MainActivity1.this.startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE); } //For Android 4.1+ only protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { mUploadMessage = uploadMsg; Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE); } protected void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); } // For Lollipop 5.0+ Devices public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (uploadMessage != null) { uploadMessage.onReceiveValue(null); uploadMessage = null; } uploadMessage = filePathCallback; Intent intent = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { intent = fileChooserParams.createIntent(); } try { startActivityForResult(intent, REQUEST_SELECT_FILE); } catch (ActivityNotFoundException e) { uploadMessage = null; Toast.makeText(getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show(); return false; } return true; } @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_SELECT_FILE) { if (uploadMessage == null) return; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data)); } uploadMessage = null; } else if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; // Use MainActivity.RESULT_OK if you''re implementing WebView inside Fragment // Use RESULT_OK only if you''re implementing WebView inside an Activity Uri result = data == null || resultCode != MainActivity.RESULT_OK ? null : data.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } }


He probado el Selector de archivos en una vista web con la última versión de Android 4.4.3, y está funcionando bien. Supongo que Google ha solucionado el problema.



Necesitas implementar una clase de WebviewClient . Puedes comprobar estos example .

webview.setWebViewClient(new myWebClient()); The web.setWebChromeClient(new WebChromeClient() { // }

Cree una clase llamada mywebClient y agregue el siguiente código para implementar la función onPageStarted() , la función shouldOvverideLoading() y la función onActivityresult() como se muestra a continuación.

public class myWebClient extends WebViewClient { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @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); } } //flipscreen not loading again @Override public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if(requestCode==FILECHOOSER_RESULTCODE){ if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } }

example


También estaba trabajando en este problema, y ​​el problema y aquí está mi solución

private class MyWebChromeClient extends WebChromeClient { /** * This is the method used by Android 5.0+ to upload files towards a web form in a Webview * * @param webView * @param filePathCallback * @param fileChooserParams * @return */ @Override public boolean onShowFileChooser( WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (mFilePathCallback != null) { mFilePathCallback.onReceiveValue(null); } mFilePathCallback = filePathCallback; Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); contentSelectionIntent.setType("image/*"); Intent[] intentArray = getCameraIntent(); Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); chooserIntent.putExtra(Intent.EXTRA_TITLE, "Seleccionar Fuente"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE); return true; } @Override public void onProgressChanged(WebView view, int newProgress) { mProgressBar.setVisibility(View.VISIBLE); WebActivity.this.setValue(newProgress); super.onProgressChanged(view, newProgress); } @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } /** * Despite that there is not a Override annotation, this method overrides the open file * chooser function present in Android 3.0+ * * @param uploadMsg * @author Tito_Leiva */ public void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = getChooserIntent(getCameraIntent(), getGalleryIntent("image/*")); i.addCategory(Intent.CATEGORY_OPENABLE); WebActivity.this.startActivityForResult(Intent.createChooser(i, "Selecciona la imagen"), FILECHOOSER_RESULTCODE); } public void openFileChooser(ValueCallback uploadMsg, String acceptType) { mUploadMessage = uploadMsg; Intent i = getChooserIntent(getCameraIntent(), getGalleryIntent("*/*")); i.addCategory(Intent.CATEGORY_OPENABLE); WebActivity.this.startActivityForResult( Intent.createChooser(i, "Selecciona la imagen"), FILECHOOSER_RESULTCODE); } /** * Despite that there is not a Override annotation, this method overrides the open file * chooser function present in Android 4.1+ * * @param uploadMsg * @author Tito_Leiva */ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { mUploadMessage = uploadMsg; Intent i = getChooserIntent(getCameraIntent(), getGalleryIntent("image/*")); WebActivity.this.startActivityForResult(Intent.createChooser(i, "Selecciona la imagen"), FILECHOOSER_RESULTCODE); } private Intent[] getCameraIntent() { // Determine Uri of camera image to save. Intent takePictureIntent = new Intent(WebActivity.this, CameraActivity.class); 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[] intentArray; if (takePictureIntent != null) { intentArray = new Intent[]{takePictureIntent}; } else { intentArray = new Intent[0]; } return intentArray; } private Intent getGalleryIntent(String type) { // Filesystem. final Intent galleryIntent = new Intent(); galleryIntent.setType(type); galleryIntent.addCategory(Intent.CATEGORY_OPENABLE); galleryIntent.setAction(Intent.ACTION_GET_CONTENT); return galleryIntent; } private Intent getChooserIntent(Intent[] cameraIntents, Intent galleryIntent) { // Chooser of filesystem options. final Intent chooserIntent = Intent.createChooser(galleryIntent, "Seleccionar Fuente"); // Add the camera options. chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents); return chooserIntent; } }

Un problema que resolví es que el uri entregado para el método onActivityResult() no tiene extensión. Para resolver esto utilizo este método.

public static Uri savePicture(Context context, Bitmap bitmap, int maxSize) { int cropWidth = bitmap.getWidth(); int cropHeight = bitmap.getHeight(); if (cropWidth > maxSize) { cropHeight = cropHeight * maxSize / cropWidth; cropWidth = maxSize; } if (cropHeight > maxSize) { cropWidth = cropWidth * maxSize / cropHeight; cropHeight = maxSize; } bitmap = ThumbnailUtils.extractThumbnail(bitmap, cropWidth, cropHeight, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); File mediaStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name) ); if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { return null; } } String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile = new File( mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg" ); // Saving the bitmap try { ByteArrayOutputStream out = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); FileOutputStream stream = new FileOutputStream(mediaFile); stream.write(out.toByteArray()); stream.close(); } catch (IOException exception) { exception.printStackTrace(); } // Mediascanner need to scan for the image saved Intent mediaScannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri fileContentUri = Uri.fromFile(mediaFile); mediaScannerIntent.setData(fileContentUri); context.sendBroadcast(mediaScannerIntent); return fileContentUri; }

Finalmente, el método onActivityResult() es

@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (resultCode == RESULT_OK) { // This is for Android 4.4.4- (JellyBean & KitKat) if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) { super.onActivityResult(requestCode, resultCode, intent); return; } final boolean isCamera; if (intent == null) { isCamera = true; } else { final String action = intent.getAction(); if (action == null) { isCamera = false; } else { isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); } } Uri selectedImageUri; if (isCamera) { selectedImageUri = mOutputFileUri; mUploadMessage.onReceiveValue(selectedImageUri); mUploadMessage = null; return; } else { try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData()); selectedImageUri = intent == null ? null : ImageUtility.savePicture(this, bitmap, 1400); mUploadMessage.onReceiveValue(selectedImageUri); mUploadMessage = null; return; } catch (IOException e) { e.printStackTrace(); } } // And this is for Android 5.0+ (Lollipop) } else if (requestCode == INPUT_FILE_REQUEST_CODE) { Uri[] results = null; // Check that the response is a good one if (resultCode == Activity.RESULT_OK) { if (intent == null) { // If there is not data, then we may have taken a photo if (mCameraPhotoPath != null) { results = new Uri[]{Uri.parse(mCameraPhotoPath)}; } } else { Bitmap bitmap = null; try { bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData()); } catch (IOException e) { e.printStackTrace(); } Uri dataUri = ImageUtility.savePicture(this, bitmap, 1400); if (dataUri != null) { results = new Uri[]{dataUri}; } } } mFilePathCallback.onReceiveValue(results); mFilePathCallback = null; return; } } else { super.onActivityResult(requestCode, resultCode, intent); return; } }