web-dev-qa-db-fra.com

Saisie de fichier HTML dans la vue Web Android (Android 4.4, KitKat)

J'utilisais le <input type="file"> sur la vue Web Android . Je l'ai obtenu grâce à ce fil de discussion: File Upload in WebView

Mais la réponse acceptée (ou toute autre réponse) ne fonctionne plus avec la visualisation Web Android 4.4 KitKat.

Quelqu'un sait comment le réparer? 

Cela ne fonctionne pas avec la cible 18 non plus.

J'ai cherché du code source sous Android 4.4 et il semble que WebChromeClient n'a pas changé, mais je pense que la variable setWebChromeClient ne fonctionne plus sur la vue Web KitKat, ou du moins pas la fonction openFileChooser.

42
jcesarmobile

Mise à jour 2: Il existe un plugin plus simple à utiliser avec phonegap/cordova

https://github.com/MaginSoft/MFileChooser

Mise à jour: Exemple de projet avec le plugin Cesidio DiBenedetto

https://github.com/jcesarmobile/FileBrowserAndroidTest

J'ai ouvert un issue sur le projet open source Android et la réponse a été:

Statut: en cours

malheureusement, openFileChooser n'est pas une API publique. Nous travaillons sur une API publique dans les futures versions d'Android.

Pour ceux qui utilisent phonegap/cordova, cette solution de contournement a été publiée sur le gestionnaire de bogues:

Cesidio DiBenedetto a ajouté un commentaire - 28/Mar/14 01:27

Salut à tous, je suis aussi confronté à ce problème, alors j’ai écrit un Cordova FileChooser plugin à un "pansement" pour le moment . Fondamentalement, dans Android 4.4 (KitKat), comme mentionné dans les commentaires précédents, la boîte de dialogue de fichier n'est pas ouverte. Cependant, l'événement onclick est toujours déclenché afin que vous puissiez appeler le plug-in FileChooser à ouvrir une boîte de dialogue de fichier et lors de la sélection, vous pouvez définir une variable qui contient le chemin complet du fichier. À ce stade, vous pouvez utiliser le fichier FileTransfer plug-in à télécharger sur votre serveur et à connecter au fichier événement onprogress pour montrer les progrès. Ce plugin est principalement configuré pour Android 4.4 donc je recommanderais de continuer à utiliser le natif dialogues de fichiers pour les versions antérieures d'Android. Il pourrait y avoir des problèmes avec le plugin car je n’ai pas complètement testé tous les scénarios possibles sur de nombreux appareils, mais je l'ai installé sur un Nexus 5 et cela a bien fonctionné.

https://github.com/cdibened/filechooser

Non testé parce que j'ai construit ma propre solution de contournement

Un commentaire forme un développeur de chrome

Nous ajouterons une API publique à WebViewClient lors de la prochaine majeure release pour gérer les demandes de fichiers.

Il semble qu'ils le considèrent comme un bogue maintenant et qu'ils vont le réparer

30
jcesarmobile

J'ai réussi à mettre en œuvre la solution de contournement mentionnée de Cesidio DiBenedetto dans mon application. Cela fonctionne très bien, mais pour quelqu'un qui n'a jamais utilisé PhoneGap/Cordove avant (comme moi), cela risque d'être un peu délicat. Voici donc un peu comment j'ai mis en place lors de la mise en œuvre.

Apache Cordova est une plate-forme qui vous permet de créer des applications mobiles multiplateformes utilisant uniquement les technologies Web. La principale caractéristique est qu'il exporte l'API native vers JavaScript et fournit donc un moyen de communiquer entre le site Web et l'application native. L'application PhoneGap/Cordova typique est un site Web statique qui est fourni avec la couche Cordova en un APK. Mais vous pouvez utiliser Cordova pour afficher un site Web à distance et c'est notre cas.

La solution de contournement fonctionne comme suit: Au lieu de la variable standard WebView, nous utilisons CordovaWebView pour afficher notre site Web. Lorsque l'utilisateur clique sur Parcourir pour sélectionner un fichier, nous attrapons ce clic en utilisant le code JavaScript standard (jQuery ...) et en utilisant l'API Cordova, nous activons le plug-in filechooser de Cesidio DiBenedetto du côté natif qui ouvrira un navigateur de fichiers Nice. Lorsque l'utilisateur sélectionne un fichier, le fichier est renvoyé au côté JavaScript à partir duquel nous le téléchargeons sur notre serveur Web.

Ce qu'il est important de savoir, c'est que vous devez ajouter l'assistance de Cordova sur votre site Web. Ok, maintenant le howto réel ...

Tout d'abord, vous devez ajouter Cordova à votre application existante. J'ai suivi cette documentation . Certaines étapes n'étaient pas claires pour moi alors je vais essayer d'expliquer davantage:

  1. Téléchargez et extrayez Cordova quelque part en dehors de votre application et construisez cordova-3.4.0.jar comme décrit. Il échouera probablement pour la première fois car le fichier local.properties est manquant. Vous apprendrez à le créer dans la sortie d'erreur. il vous suffit de pointer vers le SDK que vous utilisez pour créer votre application Android. 

  2. Copiez le fichier JAR compilé dans le répertoire lib de votre application et ajoutez-le en tant que bibliothèque. Si vous utilisez Android Studio comme moi, assurez-vous que vous avez bien compile fileTree(dir: 'libs', include: ['*.jar', '*.aar']) dans dependencies dans build.gradle. Cliquez ensuite sur le bouton Sync projet avec les fichiers de gradation et tout ira bien.

  3. Il n'est pas nécessaire de créer le fichier /res/xml/main.xml. Vous pouvez traiter CordovaWebView de la même manière que WebView standard afin de pouvoir le placer directement dans votre fichier de mise en page. 

  4. Suivez maintenant les étapes 5 à 7 de la documentation d'origine pour créer votre propre variable Activity où la variable CordobaWebView sera exécutée. C'est une bonne idée de vérifier le /framework/src/org/Apache/cordova/CordovaActivity.Java dans le package Cordova que vous avez téléchargé. Vous pouvez simplement copier la plupart des méthodes requises pour être implémentées. La 6. étape est vraiment cruciale pour notre objectif car elle laissera utiliser le plugin filechooser.

  5. Ne copiez aucun fichier HTML et JavaScript où que ce soit, nous l'ajouterons à votre site Web ultérieurement.

  6. N'oubliez pas de copier le fichier config.xml (vous ne devez pas le changer).

Pour charger votre site Web dans la CordovaWebView, transmettez simplement son URL à cwv.loadUrl() au lieu de Config.getStartUrl()

Deuxièmement, vous devez ajouter le plugin FileChooser à votre application. Comme nous n'utilisons pas la configuration standard de Cordova, nous ne pouvons pas appuyer sur cordova plugin add comme indiqué dans le fichier Lisez-moi, nous devons l'ajouter manuellement.

  1. Téléchargez le référentiel et copiez les fichiers source dans votre application. Assurez-vous que le contenu du dossier res va dans le dossier de votre application res. Vous pouvez ignorer le fichier JavaScript pour l'instant.

  2. Ajoutez l'autorisation READ_EXTERNAL_STORAGE à votre application.

  3. Ajoutez le code suivant à /res/xml/config.xml:

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

Il est maintenant temps d'ajouter l'assistance de Cordova sur votre site Web. C'est plus simple qu'il n'y paraît, il vous suffit de relier cordova.js à votre site Web. Cependant, il y a deux choses à connaître.

Tout d’abord, chaque plate-forme (Android, iOS, WP) a son propre cordova.js, alors assurez-vous d’utiliser la version Android (vous pouvez la trouver dans le package Cordova que vous avez téléchargé dans / framework/actifs/www).

Deuxièmement, si vous souhaitez accéder à votre site Web à partir de CordovaWebView et des navigateurs standard (ordinateurs de bureau ou mobiles), il est généralement conseillé de charger cordova.js uniquement lorsque la page est affichée dans CordovaWebView. J'ai trouvé plusieurs façons de détecter CordovaWebView mais la suivante a fonctionné pour moi. Voici le code complet de votre site 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>');
}

Notez que nous vérifions également la version Android. Cette solution de contournement est requise uniquement pour KitKat.

À ce stade, vous devriez pouvoir appeler manuellement le plug-in FileChooser à partir de votre site Web.

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

Cela devrait ouvrir le navigateur de fichiers et vous permettre de choisir un fichier. Notez que cela ne peut être fait qu'après le déclenchement de l'événement deviceready. Pour le tester, il suffit de lier ce code à un bouton en utilisant jQuery.La dernière étape consiste à rassembler tout cela et à faire fonctionner le formulaire de téléchargement. Pour cela, il vous suffit de suivre les instructions de Cesidio DiBenedetto décrites dans le README. Lorsque l'utilisateur sélectionne le fichier dans FileChooser, le chemin du fichier est renvoyé du côté JavaScript à partir duquel un autre plug-in Cordova, FileTransfer, est utilisé pour effectuer le téléchargement. Cela signifie que le fichier est téléchargé du côté natif, pas dans CordovaWebView (si je le comprends bien).

Je n'avais pas envie d'ajouter un autre plugin Cordova à mon application et je ne savais pas non plus comment cela fonctionnerait avec les cookies (je dois envoyer des cookies avec la demande, car seuls les utilisateurs authentifiés sont autorisés à télécharger des fichiers). J'ai donc décidé de le faire. c'est ma façon. J'ai modifié le plugin FileChooser pour qu'il ne retourne pas le chemin mais le fichier entier. Ainsi, lorsque l'utilisateur sélectionne un fichier, je lis son contenu, l'encode à l'aide de base64, le transmet en tant que JSON au côté client où je le décode et l'envoie à l'aide de JavaScript au serveur. Cela fonctionne, mais il y a un inconvénient évident, car base64 est assez exigeant en ressources de traitement, donc l'application peut se figer un peu lorsque des fichiers volumineux sont téléchargés. 

Pour le faire, ajoutez d’abord cette méthode à 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); }

// 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());
}

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', [{}]);
    });
}

Well, that's all. It took me several hours to get this working so I'm sharing my knowledge with a humble hope that it might help somebody.

21
tobik

Si quelqu'un cherche toujours une solution pour archiver une entrée à l'aide d'une vue Web sur KitKat.

openFileChooser non appelé quand on clique sur Android 4.4
https://code.google.com/p/Android/issues/detail?id=62220

Une bibliothèque basée sur le chrome appelée Crosswalk peut être utilisée pour résoudre ce problème
https://crosswalk-project.org/documentation/downloads.html

Pas
1. Importez le projet Android xwalk_core_library téléchargé à partir du lien ci-dessus dans votre projet sous forme de bibliothèque.
2. Dans votre mise en page XML, ajoutez ce qui suit

       <org.xwalk.core.XWalkView
            Android:id="@+id/webpage_wv"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"          
        />

3. Dans la méthode onCreate de votre activité, procédez comme suit:

mXwalkView = (XWalkView) context.findViewById(R.id.webpage_wv);
mXwalkView.setUIClient(new UIClient(mXwalkView));
mXwalkView.load(navigateUrl, null); //navigate url is your page URL
  1. Ajouter des variables de classe d'activité 

    private ValueCallback mFilePathCallback; private XWalkView mXwalkView

  2. La boîte de dialogue de saisie de fichier devrait maintenant apparaître. Cependant, vous devrez fournir des rappels pour obtenir le fichier et l'envoyer au serveur.

  3. Vous devez remplacer onActivityResult de votre activité.

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
      super.onActivityResult(requestCode, resultCode, intent);
    
    if (mXwalkView != null) {
    
        if (mFilePathCallback != null) {
            Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
                    : intent.getData();
            if (result != null) {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback.onReceiveValue(uri);
            } else {
                mFilePathCallback.onReceiveValue(null);
            }
        }
    
        mFilePathCallback = null;
    }
    mXwalkView.onActivityResult(requestCode, resultCode, intent);
    
    }
    
  4. La classe MediaUtility peut être trouvée à 
    Obtenir le chemin réel de l’URI, nouvelle infrastructure d’accès au stockage pour Android KitKat
    Voir la réponse de Paul Burke

  5. Pour obtenir l'objet de données pour mFilePathCallback, créez une sous-classe dans votre activité.

    class UIClient extends XWalkUIClient {
    public UIClient(XWalkView xwalkView) {
        super(xwalkView);
    }
    
    public void openFileChooser(XWalkView view,
            ValueCallback<Uri> uploadFile, String acceptType, String capture) {
        super.openFileChooser(view, uploadFile, acceptType, capture);
    
        mFilePathCallback = uploadFile;
        Log.d("fchooser", "Opened file chooser.");
    }
    

    }

  6. Vous êtes tous fait Le fileupload devrait maintenant fonctionner… .. N'oubliez pas d'ajouter les autorisations requises par Crosswalk à votre manifeste.

    uses-permission Android: name = "Android.permission.ACCESS_FINE_LOCATION"
    utilise-permission Android: name = "Android.permission.ACCESS_NETWORK_STATE"
    utilise-permission Android: name = "Android.permission.ACCESS_WIFI_STATE"
    utilise-permission Android: name = "Android.permission.CAMERA" 
    utilise-permission Android: name = "Android.permission.INTERNET"
    utilise-permission Android: name = "Android.permission.MODIFY_AUDIO_SETTINGS"
    utilise-permission Android: name = "Android.permission.RECORD_AUDIO"
    utilise-permission Android: name = "Android.permission.WAKE_LOCK"
    utilise-permission Android: name = "Android.permission.WRITE_EXTERNAL_STORAGE" 

8
agomes

Le sélecteur de fichier dans une vue Web fonctionne maintenant dans la dernière version Android 4.4.3. 

Je l'ai essayé moi-même en utilisant Nexus 5.

5
A.Salam Alasaadi

J'ai construit ma propre solution à ce problème sans utiliser aucune bibliothèque, plug-in Cordova ou WebViews personnalisé, et cela fonctionne correctement dans toutes les versions d'Android.

Cette solution implique l'utilisation de Javascript très simple pour communiquer entre votre site Web dans WebView et l'application Android, ainsi que la sélection et le téléchargement de fichiers directement à partir de votre application Android, en supprimant tous les openFileChooser (), showFileChooser () et onShowFileChooser ()). Méthodes WebChromeClient.

La première étape consiste à déclencher un message de la console javascript du site Web lorsque l'utilisateur clique sur une entrée de fichier, écriture d'un code unique, qui sera utilisée pour télécharger le fichier avec un nom unique ou chemin. Par exemple, concaténer la date/heure complète avec un nombre aléatoire énorme:

<input type="file" name="user_file" onclick="console.log('app.upload=20170405173025_456743538912');">

Ensuite, votre application peut lire ces messages en remplaçant la méthode onConsoleMessage () de WebChromeClient, détecter ce message, lire le code et sélection du fichier de déclencheur:

webview.setWebChromeClient(new WebChromeClient() {
    // Overriding this method you can read messages from JS console.
    public boolean onConsoleMessage(ConsoleMessage message){          
        String messageText = message.message();
        // Check if received message is a file upload and get the unique code
        if(messageText.length()>11 && messageText.substring(0,11).equals("app.upload=")) {
           String code = messageText.substring(11);
           triggerFileUploadSelection(code);
           return true;
        }
        return false;
    }
});

(Pour la sélection de fichier}, vous pouvez simplement utiliser un simple Android {intention de ACTION_PICK} comme ceci:

public void triggerFileUploadSelection(String code){
    // For Android 6.0+ you must check for permissions in runtime to read from external storage
    checkOrRequestReadPermission();

    // Store code received from Javascript to use it later (code could also be added to the intent as an extra)
    fileUploadCode = code;

    // Build a simple intent to pick any file, you can replace "*/*" for "image/*" to upload only images if needed
    Intent filePickerIntent = new Intent(Intent.ACTION_PICK);
    filePickerIntent.setType("*/*");

    // FILE_UPLOAD_CODE is just any unique integer request code to identify the activity result when the user selects the file
    startActivityForResult( Intent.createChooser(filePickerIntent, getString(R.string.chooseFileToUpload) ), FILE_UPLOAD_CODE );
}

Une fois que l'utilisateur a sélectionné (ou non) un fichier, vous pouvez recevoir le fichier Uri, et le traduire en un chemin d'accès réel avec:

@Override
public void onActivityResult (int requestCode, int resultCode, Intent data) {
    if(requestCode==FILE_UPLOAD_CODE) {
        if(data != null && resultCode == RESULT_OK){
            // user selected a file
            try{
                Uri selectedFileUri = data.getData();
                if(selectedFileUri!=null) {
                    // convert file URI to a real file path with an auxiliary function (below)
                    String filePath = getPath(selectedFileUri);
                    if(filePath!=null) {
                        // I got the file path, I can upload the file to the server (I pass webview as an argument to be able to update it when upload is completed)
                        uploadSelectedFile(getApplicationContext(), filePath, fileUploadCode, webview);
                    }else{
                        showToastFileUploadError();
                    }
                }else{
                    showToastFileUploadError();
                }
            }catch (Exception e){
                e.printStackTrace();
                showToastFileUploadError();
            }
        }else{
            // user didn't select anything
        }
    }
}

// I used this method for images, and it uses MediaStore.Images so you should probably 
// use another method to get the path from the Uri if you are working with any kind of file
public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor==null)return null;
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

La méthode uploadSelectedFile crée simplement un objet contenant toutes les informations (filePath, fileUploadCode et WebView) et déclenche une AsyncTask qui télécharge le fichier à l'aide de ces informations et met à jour WebView à la fin de l'opération:

public static void uploadSelectedFile(Context c, String filePath, String code, WebView webView){
    // YOU CAN SHOW A SPINNER IN THE WEB VIEW EXECUTING ANY JAVASCRIPT YOU WANT LIKE THIS:
    webView.loadUrl("javascript: Element.show('my_upload_spinner');void 0"); 
    // void 0 avoids at the end avoids some browser redirection problems when executing javascript commands like this

    // CREATE A REQUEST OBJECT (you must also define this class with those three fields and a response field that we will use later):
    FileUploadRequest request = new FileUploadRequest(filePath, code, webView);

    // Trigger an async task to upload the file, and pass on the request object with all needed data
    FileUploadAsyncTask task = new FileUploadAsyncTask();
    task.execute(request);
}

AsyncTask reçoit l'objet de requête avec toutes les informations et utilise MultipartUtility pour créer une requête en plusieurs parties et l'envoyer au serveur facilement. Vous pouvez obtenir de nombreux utilitaires multi-parties Java de nombreux endroits, dont l’un se trouve ici: http://www.codejava.net/Java-se/networking/upload-files-by-sending-multipart-request-programmatically

public class FileUploadAsyncTask extends AsyncTask<FileUploadRequest, Void, FileUploadRequest> {
    @Override
    protected FileUploadRequest doInBackground(FileUploadRequest... requests) {
        FileUploadRequest request = requests[0];

        try {
            // Generate a multipart request pointing to the URL where you will receive uploaded file
            MultipartUtility multipart = new MultipartUtility("http://www.example.com/file_upload.php", "UTF-8");
            // Add a field called file_code, to send the code to the server script
            multipart.addFormField("file_code", request.code);
            // Add the file to the request
            multipart.addFilePart("file_path", new File(request.filePath));

            // Send the request to the server and get the response and save it back in the request object
            request.response = multipart.finish(); // response from server.
        } catch (IOException e) {
            request.response = "FAILED";
            e.printStackTrace();
        }
        return request;
    }

Maintenant, nous avons téléchargé le fichier sur le serveur et nous pouvons mettre à jour notre site web en utilisant à nouveau Javascript à partir de notre méthode onPostExecute dans notre AsyncTask. Le plus important est de définissez le code du fichier dans un champ masqué de votre formulaire} afin que vous puissiez obtenir ce code lorsque l'utilisateur envoie le formulaire. Vous pouvez également afficher un message sur le site ou même facilement afficher l'image téléchargée (s'il s'agit d'une image):

@Override
protected void onPostExecute(FileUploadRequest request) {
    super.onPostExecute(request);

    // check for a response telling everything if upload was successful or failed
    if(request.response.equals("OK")){
        // set uploaded file code field in a hidden field in your site form (ESSENTIAL TO ASSOCIATE THE UPLOADED FILE WHEN THE USER SENDS THE WEBSITE FORM)
        request.webView.loadUrl("javascript: document.getElementById('app_upload_code_hidden').value = '"+request.code+"';void 0");

        // Hide spinner (optional)
        //request.webView.loadUrl("javascript: Element.hide('my_upload_spinner');void 0");

        // show a message in the website, or the uploaded image in an image tag setting the src attribute 
        // to the URL of the image you just uploaded to your server. 
        // (you must implement your own fullUrl method in your FileUploadRequest class)
        // request.webView.loadUrl("javascript: document.getElementById('app_uploaded_image').src = '"+request.fullUrl()+"';void 0");
        // request.webView.loadUrl("javascript: Element.show('app_uploaded_image');void 0");
    }
}

Maintenant, la partie Android est terminée et vous devez travailler côté serveur pour recevoir le fichier que vous téléchargez via l'application Android AsyncTask et enregistrez-le où vous le souhaitez.

Vous devrez également traiter le formulaire de votre site Web lorsque l'utilisateur l'enverra} et faire tout ce dont vous aurez besoin avec le fichier que l'utilisateur a téléchargé à partir de l'application. Pour ce faire, vous obtiendrez le code de fichier sous la forme (nous l'avons complété dans un champ de onPostExecute ()), et vous devez utilisez ce code pour trouver le fichier que l'application a chargé} à votre serveur. Pour ce faire, vous pouvez enregistrer le fichier dans un chemin utilisant ce code en tant que nom de fichier ou enregistrer le code et le chemin où vous avez téléchargé le fichier dans une base de données.

Cette solution ne repose que sur des éléments disponibles et compatibles avec toutes les versions d'Android. Elle devrait donc fonctionner sur n'importe quel appareil (et les utilisateurs ne se sont plus plaints de cela).

Si vous avez plusieurs entrées de fichier dans la même page, vous pouvez envoyer un numéro de champ ou un identifiant supplémentaire ainsi que le code de fichier unique dans le message javascript initial, transmettez cet identifiant dans tous les cas. le code de l'application et utilisez-le pour mettre à jour les bons éléments dans onPostExecute ().

J'ai modifié un peu le code actuel ici, donc si quelque chose échoue, ce sera probablement une faute de frappe ou un détail mineur lors du changement de nom de plusieurs éléments. 

Il faut traiter pas mal d'informations. Si quelqu'un a besoin de précisions, de suggestions ou de corrections, veuillez m'en informer.

1
Alejandro Núñez

Bien que la version KitKat ne soit pas compatible avec le champ webview type = file, nous pourrions utiliser la méthode addJavascriptInterface de webview pour accomplir la tâche de téléchargement de fichier. Le côté serveur doit juger de la version d'Android. Si elle est inférieure à 4.4, utilisez les méthodes privées WebViewChromeClient, si la version 4.4 ou supérieure est utilisée, laissez le serveur appeler la méthode Android pour communiquer entre eux (par exemple, le contenu du fichier upload async.)

// code

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


Voici un lien qui pourrait aider ...

call-android-method-from-javascript

1
tounaobun

Le nouveau navigateur de fichiers de KitKat est tout aussi fou sur Chrome. Voyant comment WebView utilise maintenant Chromium, cela pourrait être un problème connexe. J'ai constaté que le téléchargement de fichiers directement à partir de l'appareil photo fonctionnait, mais pas à partir du dossier "Images". Si vous deviez télécharger à partir de 'Galerie' à la place, les mêmes fichiers sont accessibles. Gah.

On dirait qu'un correctif est prêt mais en attente de publication:

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

0
Igor Zinken

si vous allez simplement ajouter un wrapper WebView sur votre site Web et le lancer en tant qu'application, il suffit de ne pas regarder avec la vue Web par défaut d'Android, d'une manière ou d'une autre, c'est un énorme mal de tête ... pour moi, deux choses n'ont pas fonctionné out 1. Fichier d'entrée 2. Intégration de contrôle de bande (qui utilise une API JS avancée)

Ce que j'ai fait pour sortir des ténèbres 

Vient de créer un exemple d'application utilisant Cordova. C'est beaucoup plus simple que nous le pensons.

  1. Installez Cordova à partir de sa page officielle, créez un exemple d'application.
  2. Il vous donnera un fichier apk. ( Tu l'as eu)
  3. Vous accédez au dossier www de l'application créée et ouvrez index.js, recherchez et remplacez la ligne par OnDeviceReady: function () {window.open (' http://votredomaine.com/votre page ') } Exécutez l'application à nouveau, le site s'ouvrira.

  4. Maintenant le pas du maître. Jusqu’à présent, Cordova n’utilisait rien mais une Webview modérée Tout devrait changer un jour. Ajouter un passage pour piétons à votre application Cordova, il remplacera la Webview lente par une toute nouvelle vue chromée à part entière https://crosswalk-project.org/documentation/cordova.html

  5. lancez cordova clean, puis cordova build --release pour nettoyer l'ancienne version.

  6. Ouvrez le fichier config.xml dans le répertoire de l'application fourni par Cordva app et ajoutez <allow-navigation href="http://yourdomain.com/*" />
  7. Exécutez l'application à nouveau. La magie!.
0
Code Tree