Android 4.4 WebView selector de archivos no se abre?
Estamos creando una aplicación que usa webview y accederá 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 cargar no sucede nada. Esta funcionalidad funciona con versiones anteriores usando 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 manera de hacerlo en 4.4, pero no he tenido suerte. ¿Alguien ha logrado hacer esto?
8 answers
WebView funciona según lo previsto
Si entiendo correctamente lo que dice el enlace anterior, usted (yo y probablemente algunos cientos más desarrolladores) está buscando un hack
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-13 16:05:34
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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-01 06:13:46
Estaba trabajando en este tema también, 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, onActivityResult()
el método 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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-26 19:27:44
Echa un vistazo esto. Debido a la api 19 4.4, webview se ha migrado para usar Chromium, no WebChromeClient.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-30 08:23:07
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(...);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-18 10:07:04
Lo que he hecho para solucionar este problema es implementar CrossWalk en mi proyecto. Sé que el tamaño de CrossWalk es significativo (agrega Chromium a su proyecto), pero realmente necesitaba esto para funcionar bien dentro de una aplicación nativa. Documenté cómo implementé esto aquí: http://maurizionapoleoni.de/blog/implementing-a-file-input-with-camera-support-in-android-with-crosswalk/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-15 22:49:25
Necesita implementar una clase WebviewClient
. Puede comprobar estos ejemplo .
webview.setWebViewClient(new myWebClient());
The web.setWebChromeClient(new WebChromeClient() {
//
}
Cree la 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;
}
}
Descargar demo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-17 21:46:16
He probado el Selector de archivos en una vista web utilizando la última versión de Android 4.4.3, y está funcionando bien. Supongo que Google ha solucionado el problema.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-25 09:10:55