45 votos

Entrada del archivo HTML en la vista web de Android (Android 4.4, kitkat)

Estaba usando el <input type="file"> en la web de Android. Lo conseguí gracias a este hilo: Subida de archivos en WebView

Pero la respuesta aceptada (o cualquier otra) ya no funciona con Android 4.4 kitkat webview.

¿Alguien sabe cómo arreglarlo?

Tampoco funciona con el objetivo 18.

He buscado algo de código fuente de Android 4.4 y parece que el WebChromeClient no ha cambiado, pero creo que el setWebChromeClient ya no funciona en la web de Kitkat, o al menos no la openFileChooser función.

30voto

jcesarmobile Puntos 6086

Actualización: Proyecto de muestra con el plugin Cesidio DiBenedetto https://github.com/jcesarmobile/FileBrowserAndroidTest

Abrí un número en el proyecto de código abierto de Android y la respuesta fue:

Estado: Trabajando según lo previsto

Desafortunadamente, openFileChooser no es una API pública. Estamos trabajando en una API pública en futuras versiones de Android.

Para aquellos que usen phonegap/cordova, esta solución fue publicada en el rastreador de bichos:

Cesidio DiBenedetto añadió un comentario - 28/Mar/14 01:27

Hola a todos, he estado experimentando este problema también, así que escribí un El plugin Cordova FileChooser para una "curita" por el momento. Básicamente, en Android 4.4(KitKat), como se mencionó en comentarios anteriores, el diálogo del archivo no se abre. Sin embargo, el evento onclick sigue siendo disparado para que puedas llamar al plugin FileChooser para abrir un diálogo de archivo y al seleccionarlo, puedes establecer una variable que contiene la ruta completa del archivo. En este punto, puedes usar el El plugin FileTransfer para subir a tu servidor y engancharse al en curso para mostrar el progreso. Este plugin está configurado principalmente para el Android 4.4, así que recomendaría seguir utilizando el nativo diálogos de archivos para versiones anteriores de Android. Puede haber problemas con el plugin, ya que no he probado completamente todos los escenarios posibles en muchos dispositivos, pero lo he instalado en un Nexus 5 y funcionó bien.

https://github.com/cdibened/filechooser

No lo probé porque construí mi propia solución

Un comentario de un desarrollador de cromo

Añadiremos una API pública a WebViewClient en el próximo gran para manejar las solicitudes de archivos.

Parece que ahora lo consideran un error y van a arreglarlo.

21voto

tobik Puntos 718

Me las arreglé para implementar el mencionado La solución de Cesidio DiBenedetto en mi aplicación. Funciona muy bien, pero para alguien que nunca ha usado PhoneGap/Cordove antes (como yo) puede ser un poco difícil. Así que aquí está un pequeño manual que he preparado mientras lo ponía en práctica.

Apache Cordova es una plataforma que te permite construir aplicaciones móviles multiplataforma utilizando sólo tecnologías web. La característica principal es que exporta la API nativa a JavaScript y, por lo tanto, proporciona una forma de comunicación entre el sitio web y la aplicación nativa. La típica aplicación PhoneGap/Cordova es un sitio web estático que está empaquetado junto con la capa de Córdova en un APK. Pero se puede usar Cordova para mostrar un sitio web remoto y ese es nuestro caso.

La solución funciona de la siguiente manera: En lugar del estándar WebView que usamos CordovaWebView para mostrar nuestra página web. Cuando el usuario hace clic para seleccionar un archivo, lo capturamos usando JavaScript estándar (jQuery...) y usando el API de Cordova activamos el plugin filechooser de Cesidio DiBenedetto en el lado nativo que abrirá un bonito navegador de archivos. Cuando el usuario selecciona un archivo, el archivo es enviado de vuelta al lado de JavaScript desde donde lo subimos a nuestro servidor web.

Lo importante es saber que tienes que añadir el soporte de Cordova a tu página web. Bien, ahora el verdadero cómo...

En primer lugar, tienes que añadir Cordova a tu aplicación existente. Seguí esta documentación . Algunos pasos no estaban claros para mí, así que trataré de explicarles más:

  1. Descarga y extrae Cordova en algún lugar fuera de tu aplicación y construye cordova-3.4.0.jar como se describe. Probablemente fallará por primera vez como propiedades locales El archivo ha desaparecido. En la salida de errores se te indicará cómo crearlo; sólo tienes que apuntarlo al SDK que usas para construir tu aplicación para Android.

  2. Copia el archivo jar compilado a tu aplicación lib y agregar el frasco como una biblioteca. Si usas el Estudio Android como yo, asegúrate de que tienes compile fileTree(dir: 'libs', include: ['*.jar', '*.aar']) en dependencies dentro de build.gradle . Entonces sólo golpea Sincronizar el proyecto con los archivos de grado y estarás bien.

  3. No tienes que crear el /res/xml/main.xml archivo. Puedes tratar el CordovaWebView de la misma manera que tratas el WebView estándar, así que puedes ponerlo directamente en tu archivo de diseño.

  4. Ahora sólo tienes que seguir los pasos 5-7 en la documentación original para armar tu propio Activity donde el CordobaWebView estará corriendo. Es una buena idea comprobar el /framework/src/org/apache/cordova/CordovaActivity.java en el paquete de Cordova que descargaste. Puede simplemente copiar la mayoría de los métodos que se requieren para ser implementados. El 6. paso es realmente crucial para nuestro propósito, ya que permitirá utilizar el plugin filechooser.

  5. No copie ningún archivo HTML y JavaScript en ningún lugar, lo añadiremos a su sitio web más tarde.

  6. No te olvides de copiar el config.xml archivo (no tienes que cambiarlo).

Para cargar su sitio web en el CordovaWebView simplemente pasa su url a cwv.loadUrl() en lugar de Config.getStartUrl() .

En segundo lugar, tienes que añadir el Plugin FileChooser a tu aplicación. Como no estamos usando la configuración estándar de Cordova no podemos simplemente golpear cordova plugin add como se indica en el léeme, tenemos que añadirlo manualmente.

  1. Descargue el repositorio y copie los archivos de origen en su aplicación. Asegúrate de que el contenido de res La carpeta va a tu aplicación res carpeta. Puedes ignorar el archivo JavaScript por ahora.

  2. Añade READ_EXTERNAL_STORAGE permiso para tu aplicación.

  3. Añade el siguiente código a /res/xml/config.xml :

    <feature name="FileChooser"> <param name="android-package" value="com.cesidiodibenedetto.filechooser.FileChooser" /> </feature>

Ahora es el momento de añadir el soporte de Cordova a su página web. Es más simple de lo que parece, sólo tienes que vincular cordova.JS a su sitio web, sin embargo, hay dos cosas que hay que saber.

Primero, cada plataforma (Android, iOS, WP) tiene su propia cordova.JS así que asegúrate de usar la versión Android (la puedes encontrar en el paquete de Cordova que descargaste en /framework/assets/www ).

En segundo lugar, si se va a acceder a su sitio web desde ambos CordovaWebView y los navegadores estándar (de escritorio o móviles) generalmente es una buena idea cargar cordova.JS sólo cuando la página se muestra en CordovaWebView . Encontré varias formas de detectar CordovaWebView pero el siguiente funcionó para mí. Aquí está el código completo de su sitio web:

function getAndroidVersion(ua) {
    var ua = ua || navigator.userAgent; 
    var match = ua.match(/Android\s([0-9\.]*)/);
    return match ? parseFloat(match[1]) : false;
};

if (window._cordovaNative && getAndroidVersion() >= 4.4) {
    // We have to use this ugly way to get cordova working
    document.write('<script src="/js/cordova.js" type="text/javascript"></script>');
}

Tengan en cuenta que también estamos revisando la versión para Android. Esta solución es necesaria sólo para KitKat.

En este punto debería ser capaz de invocar manualmente el FileChooser plugin de su sitio web.

var cordova = window.PhoneGap || window.Cordova || window.cordova;
cordova.exec(function(data) {}, function(data) {}, 'FileChooser', 'open', [{}]);

Esto debería abrir el navegador de archivos y permitirte elegir un archivo. Tenga en cuenta que esto sólo puede hacerse después de que el evento Deviceready se dispare. Para probarlo, sólo tienes que vincular este código a algún botón usando jQuery.

El paso final es juntar todo esto y hacer que el formulario de carga funcione. Para lograrlo, puedes simplemente seguir las instrucciones de Cesidio DiBenedetto descritas en el LÉANSE . Cuando el usuario elige el archivo en el FileChooser la ruta de archivo es devuelta al lado de JavaScript desde donde otro plugin de Cordova, Transferencia de archivos se utiliza para realizar la carga real. Eso significa que el archivo se sube en el lado nativo, no en CordovaWebView (si lo entiendo correctamente).

No me apetecía añadir otro plugin de Cordova a mi aplicación y tampoco estaba seguro de cómo funcionaría con las cookies (necesito enviar cookies con la solicitud porque sólo los usuarios autentificados pueden subir archivos) así que decidí hacerlo a mi manera. Modifiqué el FileChooser para que no devuelva la ruta sino el archivo completo. Así que cuando el usuario elige un archivo, leo su contenido, lo codifico usando base64 lo paso como JSON al lado del cliente donde lo decodifico y lo envío usando Javascript al servidor. Funciona, pero hay una desventaja obvia ya que base64 es bastante exigente con la CPU, por lo que la aplicación puede congelarse un poco cuando se suben archivos grandes.

Para hacerlo, primero agregue este método a FileUtils :

public static byte[] readFile(final Context context, final Uri uri) throws IOException {
    File file = FileUtils.getFile(context, uri);
    return org.apache.commons.io.FileUtils.readFileToByteArray(file);
}

Tenga en cuenta que utiliza Biblioteca de Apache Commons así que no olvides incluirlo o implementar la lectura de archivos de alguna otra forma que no requiera la biblioteca externa.

A continuación, modificar FileChooser.onActivityResultado para devolver el contenido del archivo en lugar de su ruta:

// Get the URI of the selected file
final Uri uri = data.getData();
Log.i(TAG, "Uri = " + uri.toString());
JSONObject obj = new JSONObject();
try {
    obj.put("filepath", FileUtils.getPath(this.cordova.getActivity(), uri));
    obj.put("name", FileUtils.getFile(this.cordova.getActivity(), uri).getName());
    obj.put("type", FileUtils.getMimeType(this.cordova.getActivity(), uri));

    // attach the actual file content as base64 encoded string
    byte[] content = FileUtils.readFile(this.cordova.getActivity(), uri);
    String base64Content = Base64.encodeToString(content, Base64.DEFAULT);
    obj.put("content", base64Content);

    this.callbackContext.success(obj);
} catch (Exception e) {
    Log.e("FileChooser", "File select error", e);
    this.callbackContext.error(e.getMessage());
}

Y finalmente, este es el código que usarás en tu sitio web (se requiere jQuery):

var cordova = window.PhoneGap || window.Cordova || window.cordova;
if (cordova) {
    $('form.fileupload input[type="file"]', context).on("click", function(e) {    
        cordova.exec(
            function(data) { 
                var url = $('form.fileupload', context).attr("action");

                // decode file from base64 (remove traling = first and whitespaces)
                var content = atob(data.content.replace(/\s/g, "").replace(/=+$/, ""));

                // convert string of bytes into actual byte array
                var byteNumbers = new Array(content.length);
                for (var i = 0; i < content.length; i++) {
                    byteNumbers[i] = content.charCodeAt(i);
                }
                var byteContent = new Uint8Array(byteNumbers);

                var formData = new FormData();
                var blob = new Blob([byteContent], {type: data.type}); 
                formData.append('file', blob, data.name);

                $.ajax({
                    url: url,
                    data: formData,
                    processData: false,
                    contentType: false,
                    type: 'POST',
                    success: function(data, statusText, xhr){
                        // do whatever you need
                    }
                });
            },
            function(data) { 
                console.log(data);
                alert("error");
            },
            'FileChooser', 'open', [{}]);
    });
}

Bueno, eso es todo. Me llevó varias horas hacer que esto funcionara, así que comparto mi conocimiento con la humilde esperanza de que pueda ayudar a alguien.

5voto

El selector de archivos en una vista web funciona ahora en la última versión de Android 4.4.3.

Lo intenté yo mismo usando el Nexus 5.

1voto

tounaobun Puntos 38

A pesar de que la versión de KitCat no es compatible con el campo de formulario de webview type=file, podríamos usar el método addJavascriptInterface de webview para realizar la tarea de subir archivos. El lado del servidor debería juzgar la versión de Android, si es inferior a 4.4, usar los métodos privados de WebViewChromeClient, si es superior a 4.4, dejar que el servidor llame al método de Android para comunicarse entre sí (por ejemplo, subir el contenido del archivo de forma asíncrona).

// código

webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");

Aquí hay un enlace que podría ayudar...

call-Android-methods-from-javascript

0voto

Igor Zinken Puntos 513

El nuevo navegador de archivos de Kitkat se está volviendo igualmente loco con el Cromo, viendo como WebView ahora usa el Cromo podría ser un problema relacionado. Encontré que subir archivos directamente desde la cámara funciona, pero no desde la carpeta "Imágenes". Si en cambio subes desde "Galería", se puede acceder a los mismos archivos. Gah.

Parece que un arreglo está listo pero esperando ser liberado:

https://code.google.com/p/chromium/issues/detail?id=278640

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X